diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 826bb602..f206c433 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -11,10 +11,11 @@ - `packages/ack_generator`: build_runner generator + unit/integration tests. - `packages/ack_firebase_ai`: Firebase AI schema adapter. - `packages/ack_json_schema_builder`: JSON Schema adapter. +- `packages/flutter_codec`: ACK codecs for portable Flutter value types. - `example`: sample usage. ## Environment and setup -- Required SDKs: Dart `>=3.9.0 <4.0.0`, Flutter `>=3.35.0` (see `/pubspec.yaml`). +- Required SDKs: Dart `>=3.9.0 <4.0.0`, Flutter `>=3.41.0` (see `/pubspec.yaml`). - CI pins Flutter to the version in `/.fvmrc`. Add a new version to `/.github/flutter-releases.json` with its checksum before a workflow may install it. - Use from repo root: 1. `dart pub get` diff --git a/.github/flutter-releases.json b/.github/flutter-releases.json index 78083a78..f61c5e1e 100644 --- a/.github/flutter-releases.json +++ b/.github/flutter-releases.json @@ -5,6 +5,10 @@ "dart": "3.9.0", "sha256": "ff2d9474d768fdb61c1b8d6b76fd4eb98235c271e68b10abf41bd9fb41bc273d" }, + "3.41.0": { + "dart": "3.11.0", + "sha256": "368ae5b6993c51861324e704c42d61c4e290fba7213a88fd0e9fec15ded54599" + }, "3.41.2": { "dart": "3.11.0", "sha256": "4a04f8a6152986d14fc137ffaf98106ca743c0f9ab66f1bc2f20ee84eb573e5c" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d2f8f94..205ed926 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,3 +49,24 @@ jobs: test/schemas/extensions/numeric_extensions_test.dart \ test/schemas/extensions/list_schema_extensions_test.dart \ test/utils/collection_utils_test.dart + + test-minimum: + name: Flutter 3.41.0 + runs-on: ubuntu-24.04 + timeout-minutes: 45 + steps: + - name: Checkout repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + + - name: Set up the minimum workspace Flutter SDK + uses: ./.github/actions/setup-flutter + with: + flutter-version: '3.41.0' + + - name: Resolve workspace dependencies + run: dart pub get + + - name: Analyze and test every package + run: dart run melos run ci --no-select diff --git a/README.md b/README.md index dfd0f8f5..c822d3fe 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ This repository is a monorepo containing: - **[ack_generator](./packages/ack_generator)**: Generates models from schemas and schemas from hand-written models - **[ack_firebase_ai](./packages/ack_firebase_ai)**: Firebase AI (Gemini) schema converter for structured-output generation - **[ack_json_schema_builder](./packages/ack_json_schema_builder)**: Converter to `json_schema_builder` schemas +- **[flutter_codec](./packages/flutter_codec)**: ACK codecs for portable Flutter painting, rendering, and widget values - **[example](./example)**: Example projects demonstrating usage of all packages ## Community and support diff --git a/llms.txt b/llms.txt index b4d7650f..0b8d04f0 100644 --- a/llms.txt +++ b/llms.txt @@ -14,6 +14,7 @@ There is no `@AckSchema()` annotation; `AckSchema` is the runtime schema type. 3. `ack_generator`: generates models from schemas and schemas from models 4. `ack_firebase_ai`: converts Ack schemas to Firebase AI structured-output schemas 5. `ack_json_schema_builder`: converts Ack schemas to `json_schema_builder` schemas +6. `flutter_codec`: ACK codecs for portable Flutter painting, rendering, and widget values ## Core runtime usage diff --git a/packages/flutter_codec/CHANGELOG.md b/packages/flutter_codec/CHANGELOG.md new file mode 100644 index 00000000..e8f27f3a --- /dev/null +++ b/packages/flutter_codec/CHANGELOG.md @@ -0,0 +1,56 @@ +# Changelog + +## 0.1.1 + +- Harden codec-boundary validation for Flutter values that only assert in + debug/release-unsafe code paths: recursive `Container.child` nesting is + capped, `StarBorder` rejects point/valley rounding sums above `1`, gradient + stops must be within `[0, 1]` and ascending, `TextStyle.fontSize` must be + positive, and `StrutStyle.package` requires a `fontFamily` or a non-empty + `fontFamilyFallback` (empty fallback is treated as omitted, matching + Flutter). Encoding `Text.rich` now fails with a dedicated unsupported-span + diagnostic instead of a generic missing-`data` error. +- Document that the `EdgeInsets` primitive intentionally remains permissive; + widget codecs enforce non-negative inset rules where Flutter asserts them. + +## 0.1.0 + +Initial release. JSON value codecs for Flutter's painting and rendering layers, +plus a small set of widget codecs, built on [`ack`](../ack/README.md). +Requires Flutter `>=3.41.0`. + +- **Primitives**: `Color`, `Offset`, `Radius`, `Rect`, `Alignment` / + `AlignmentDirectional` / `AlignmentGeometry`, `EdgeInsets` / + `EdgeInsetsDirectional` / `EdgeInsetsGeometry`, `BorderRadius` / + `BorderRadiusDirectional` / `BorderRadiusGeometry`, `FontWeight`, + `FontFeature`, `FontVariation`, `TextDecoration`, `Locale`. +- **Enums**: 30+ painting / rendering / widget enums in a single + `lib/src/enums.dart` (e.g. `blendModeCodec`, `boxShapeCodec`, + `tileModeCodec`, `fontStyleCodec`). +- **Borders**: `BorderSide`, `Border`, `BorderDirectional`, `BoxBorder`, + `StrokeAlign`. +- **Shape borders** (discriminated by `"type"`): `CircleBorder`, + `StadiumBorder`, `RoundedRectangleBorder`, `BeveledRectangleBorder`, + `ContinuousRectangleBorder`, `RoundedSuperellipseBorder`, `StarBorder`, + `LinearBorder` (with `LinearBorderEdge`) → `ShapeBorder`. +- **Shadows**: `Shadow`, `BoxShadow`. +- **Gradients** (discriminated by `"type"`): `LinearGradient`, + `RadialGradient`, `SweepGradient` → `Gradient`. +- **Image providers** (discriminated by `"type"`): `NetworkImage`, + `AssetImage` → `ImageProvider`. +- **Decoration image**: `DecorationImage` (composes `imageProviderCodec`, + `rectCodec`, and the relevant enum codecs). +- **Text style**: `TextStyle` (including `fontFeatures` and `fontVariations` + lists), `StrutStyle` (sibling layout style), `TextHeightBehavior`. +- **Decorations** (discriminated by `"type"`): `BoxDecoration`, + `ShapeDecoration` → `Decoration`. +- **Constraints**: `BoxConstraints`, `Constraints` (discriminated by `"type"`). +- **Matrix**: `Matrix4`. +- **Widgets**: `Container`, `Text`, and portable `Key` / `ValueKey` codecs, + plus a `widgetCodec` union (discriminated by `"type"`). + +`FontWeight` accepts and emits arbitrary integer weights (`[1, 1000]`) for +variable fonts in addition to the `"w100"`–`"w900"` / `"normal"` / `"bold"` +aliases. + +Every codec exposes `.parse`, `.safeParse`, `.encode`, and `.toJsonSchema`. diff --git a/packages/flutter_codec/LICENSE b/packages/flutter_codec/LICENSE new file mode 100644 index 00000000..c936b029 --- /dev/null +++ b/packages/flutter_codec/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2025, Leo Farias +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/packages/flutter_codec/README.md b/packages/flutter_codec/README.md new file mode 100644 index 00000000..ad11c552 --- /dev/null +++ b/packages/flutter_codec/README.md @@ -0,0 +1,174 @@ +# flutter_codec + +JSON value codecs for Flutter's painting and rendering layers — plus a small, +growing set of widget codecs (`Container`, `Text`, `Key`) — built on +[`ack`](https://pub.dev/packages/ack). + +Every codec is an Ack `CodecSchema` and exposes the same surface: + +```dart +codec.parse(json); // decode, throws on failure +codec.safeParse(json); // decode, returns SchemaResult +codec.encode(value); // encode to a JSON-safe map / scalar +codec.safeEncode(value); // encode, returns SchemaResult +codec.toJsonSchema(); // emit JSON Schema for downstream tooling +``` + +Codecs compose: composite types reuse their dependents, so a `BoxDecoration` +codec inherits the validation and schema output of `Color`, `BoxBorder`, +`Gradient`, `BoxShadow`, and so on. + +## Quick example + +```dart +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; + +final decoration = BoxDecoration( + color: const Color(0xFF2196F3), + border: Border.all(color: const Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + gradient: const LinearGradient( + colors: [Color(0xFFFF0000), Color(0xFF0000FF)], + ), +); + +final json = boxDecorationCodec.encode(decoration); +// json is a Map safe for jsonEncode + +final roundTripped = boxDecorationCodec.parse(json); +assert(roundTripped == decoration); +``` + +## ACK patterns in this package + +- [`colorCodec`](lib/src/primitives/color.dart) shows a custom codec with a + compact boundary and a rich Flutter runtime value. +- [`boxDecorationCodec`](lib/src/decorations.dart) composes child codecs and + applies defaults while keeping its canonical output explicit. +- [`gradientCodec`](lib/src/gradients.dart) combines literals, named + refinements, and a discriminated union. +- [`widgetCodec`](lib/src/widgets/widget.dart) uses `Ack.lazy` through its + recursive `Container` branch, with a bounded runtime depth. + +Together, `safeParse`, `safeEncode`, and `toJsonSchema` provide the public +validation, encoding, and boundary-schema workflow for all of these patterns. + +## Coverage + +| Family | Type(s) | Codec(s) | Source | +|---|---|---|---| +| Primitives | `Color` | `colorCodec` | [lib/src/primitives/color.dart](lib/src/primitives/color.dart) | +| | `Offset` | `offsetCodec` | [lib/src/primitives/offset.dart](lib/src/primitives/offset.dart) | +| | `Radius` | `radiusCodec` | [lib/src/primitives/radius.dart](lib/src/primitives/radius.dart) | +| | `Rect` | `rectCodec` | [lib/src/primitives/rect.dart](lib/src/primitives/rect.dart) | +| | `Alignment` / `AlignmentDirectional` / `AlignmentGeometry` | `alignmentCodec`, `alignmentDirectionalCodec`, `alignmentGeometryCodec` | [lib/src/primitives/alignment.dart](lib/src/primitives/alignment.dart) | +| | `EdgeInsets` / `EdgeInsetsDirectional` / `EdgeInsetsGeometry` | `edgeInsetsCodec`, `edgeInsetsDirectionalCodec`, `edgeInsetsGeometryCodec` | [lib/src/primitives/edge_insets.dart](lib/src/primitives/edge_insets.dart) | +| | `BorderRadius` / `BorderRadiusDirectional` / `BorderRadiusGeometry` | `borderRadiusCodec`, `borderRadiusDirectionalCodec`, `borderRadiusGeometryCodec` | [lib/src/primitives/border_radius.dart](lib/src/primitives/border_radius.dart) | +| | `FontWeight` | `fontWeightCodec` | [lib/src/primitives/font_weight.dart](lib/src/primitives/font_weight.dart) | +| | `FontFeature` | `fontFeatureCodec` | [lib/src/primitives/font_feature.dart](lib/src/primitives/font_feature.dart) | +| | `FontVariation` | `fontVariationCodec` | [lib/src/primitives/font_variation.dart](lib/src/primitives/font_variation.dart) | +| | `TextDecoration` | `textDecorationCodec` | [lib/src/primitives/text_decoration.dart](lib/src/primitives/text_decoration.dart) | +| | `TextHeightBehavior` | `textHeightBehaviorCodec` | [lib/src/primitives/text_height_behavior.dart](lib/src/primitives/text_height_behavior.dart) | +| | `Locale` | `localeCodec` | [lib/src/primitives/locale.dart](lib/src/primitives/locale.dart) | +| Enums | 30+ painting/rendering enums (e.g. `blendModeCodec`, `boxShapeCodec`, `tileModeCodec`, `fontStyleCodec`) | see file | [lib/src/enums.dart](lib/src/enums.dart) | +| Borders | `BorderSide`, `Border`, `BorderDirectional`, `BoxBorder`, `StrokeAlign` | `borderSideCodec`, `borderCodec`, `borderDirectionalCodec`, `boxBorderCodec`, `strokeAlignCodec` | [lib/src/borders.dart](lib/src/borders.dart) | +| Shape borders | `CircleBorder`, `StadiumBorder`, `RoundedRectangleBorder`, `BeveledRectangleBorder`, `ContinuousRectangleBorder`, `RoundedSuperellipseBorder`, `StarBorder`, `LinearBorder`, `LinearBorderEdge`, `ShapeBorder` | `circleBorderCodec`, `stadiumBorderCodec`, `roundedRectangleBorderCodec`, `beveledRectangleBorderCodec`, `continuousRectangleBorderCodec`, `roundedSuperellipseBorderCodec`, `starBorderCodec`, `linearBorderCodec`, `linearBorderEdgeCodec`, `shapeBorderCodec` | [lib/src/shape_borders.dart](lib/src/shape_borders.dart) | +| Shadows | `Shadow`, `BoxShadow` | `shadowCodec`, `boxShadowCodec` | [lib/src/shadows.dart](lib/src/shadows.dart) | +| Gradients | `LinearGradient`, `RadialGradient`, `SweepGradient`, `Gradient` | `linearGradientCodec`, `radialGradientCodec`, `sweepGradientCodec`, `gradientCodec` | [lib/src/gradients.dart](lib/src/gradients.dart) | +| Image providers | `NetworkImage`, `AssetImage`, `ImageProvider` | `networkImageCodec`, `assetImageCodec`, `imageProviderCodec` | [lib/src/image_providers.dart](lib/src/image_providers.dart) | +| Decoration image | `DecorationImage` | `decorationImageCodec` | [lib/src/decoration_image.dart](lib/src/decoration_image.dart) | +| Text style | `TextStyle` | `textStyleCodec` | [lib/src/text_style.dart](lib/src/text_style.dart) | +| Strut style | `StrutStyle` | `strutStyleCodec` | [lib/src/strut_style.dart](lib/src/strut_style.dart) | +| Decorations | `BoxDecoration`, `ShapeDecoration`, `Decoration` | `boxDecorationCodec`, `shapeDecorationCodec`, `decorationCodec` | [lib/src/decorations.dart](lib/src/decorations.dart) | +| Constraints | `BoxConstraints`, `Constraints` | `boxConstraintsCodec`, `constraintsCodec` | [lib/src/constraints.dart](lib/src/constraints.dart) | +| Matrix | `Matrix4` | `matrix4Codec` | [lib/src/primitives/matrix4.dart](lib/src/primitives/matrix4.dart) | +| Widgets | `Container`, `Text`, `Key` (`ValueKey`) | `containerWidgetCodec`, `textWidgetCodec`, `keyCodec`, `widgetCodec` | [lib/src/widgets/](lib/src/widgets/) | + +## Discriminated unions + +Polymorphic types are encoded as `{ "type": "", ...fields }`. The +discriminator key is injected by the union at encode time. Most standalone +branch codecs do not require it on input; the gradient branches are the +exception — they embed a `"type"` literal in their own schema, so they self-tag +and accept (and require) the key on input as well. + +| Union | Discriminator key | Branches | +|---|---|---| +| `gradientCodec` | `"type"` | `"linear"`, `"radial"`, `"sweep"` | +| `imageProviderCodec` | `"type"` | `"network"`, `"asset"` | +| `shapeBorderCodec` | `"type"` | `"circle"`, `"stadium"`, `"roundedRectangle"`, `"beveledRectangle"`, `"continuousRectangle"`, `"roundedSuperellipse"`, `"star"`, `"linear"` | +| `decorationCodec` | `"type"` | `"box"`, `"shape"` | +| `keyCodec` | `"type"` | `"value"` | +| `widgetCodec` | `"type"` | `"container"`, `"text"` | +| `constraintsCodec` | `"type"` | `"box"` | + +## Intentionally excluded + +These types have no portable JSON shape, or their JSON representation would +mislead more than it helps. Each is documented at the call site rather than +silently falling back. + +- **Opaque `dart:ui` state — encode impossible via public API**: + `ColorFilter` and `ImageFilter`. `ColorFilter` keeps `_color`, `_blendMode`, + `_matrix`, and `_type` in library-private fields and exposes the same + `runtimeType` for all four constructor variants, so an existing instance + cannot be inspected back to JSON. `ImageFilter` is abstract with a private + constructor (`ImageFilter._()`) and returns library-private subtypes + (`_GaussianBlurImageFilter`, `_MatrixImageFilter`, etc.) from its factories + — external code cannot `is`-check or downcast them. The only state-revealing + surface is `toString()`, which is a debug format Flutter is free to change + between releases. A bidirectional codec is not achievable here without + introducing parallel descriptor types; the same goes for + `DecorationImage.colorFilter` (which embeds a `ColorFilter`). Because + `colorFilter` *is* part of `DecorationImage` equality, encoding a + `DecorationImage` that carries one **throws** rather than silently dropping it. +- **No portable JSON shape (encode throws)**: `Gradient.transform` + (`GradientTransform` is an open abstract type — encoding a transformed + gradient throws rather than dropping it silently). `Text.rich` / inline + `TextSpan` trees are also rejected on encode instead of dropping the span. +- **No portable JSON shape**: `Paint`, `Path`, `Shader`, + `TextStyle.foreground` / `TextStyle.background`, + `DecorationImage.onError`, `FlutterLogoDecoration`. +- **Local or recursive providers**: `FileImage` (local path), `MemoryImage` + (base64 bloat), `ResizeImage` (wraps another provider), custom + `AssetBundle` instances on `AssetImage`. +- **8-bit sRGB color**: `Color` encodes as `#RRGGBB` / `#AARRGGBB`. Integer sRGB + colors round-trip exactly, but sub-8-bit float-channel precision (from + `Color.withValues` / `Color.lerp`) is quantized and a non-sRGB `colorSpace` + (display P3, extended sRGB) is flattened to sRGB. +- **Lossy narrowing**: `OvalBorder` extends `CircleBorder`, so it round-trips + as `CircleBorder` — the runtime subtype is lost. The painted output is + equivalent to `CircleBorder(eccentricity: 1.0)`. Likewise `StarBorder.polygon` + round-trips as the equivalent regular `StarBorder` (its null + `innerRadiusRatio` becomes the resolved value), and `StarBorder.rotation` + survives only to floating-point precision (degrees↔radians). Both are + painted-equivalent but not `==`-equal. +- **Font-family `packages/` ambiguity**: a literal `fontFamily: + 'packages//'` supplied without a `package:` argument is read back as + package-qualified (the common case), so it does not round-trip under + `TextStyle` equality although the resolved family string is preserved. +- **Separate plans**: `InputBorder` family (Material — `OutlineInputBorder`, + `UnderlineInputBorder`). + +## JSON Schema export + +Every codec implements `.toJsonSchema()`, returning a `Map` +that round-trips through `jsonEncode`. Composition flows through: the schema +for `boxDecorationCodec` embeds the schemas for its dependent codecs (color +pattern, gradient discriminator, shape enum, and so on). + +Draft-7 output describes the portable boundary and the constraints that JSON +Schema can express. Cross-field Dart refinements, such as correlated gradient +stops or `Container` constructor invariants, and the `Ack.lazy` widget recursion +cap remain runtime-only. Use `safeParse` and `safeEncode` when those checks must +be enforced; exported JSON Schema alone does not include them. + +## Roadmap + +The painting- and rendering-layer surface is feature-complete for the types +Flutter exposes JSON-safely. The widget codecs (`Container`, `Text`, `Key`) are +a deliberately small surface that will grow over time. Further additions to the +painting layer would require either upstream changes to `dart:ui` (to expose +`ColorFilter` / `ImageFilter` state) or a parallel descriptor-type design that +we'd own outside the raw Flutter types. diff --git a/packages/flutter_codec/analysis_options.yaml b/packages/flutter_codec/analysis_options.yaml new file mode 100644 index 00000000..4e885bbe --- /dev/null +++ b/packages/flutter_codec/analysis_options.yaml @@ -0,0 +1,16 @@ +# Inherits the shared workspace config (lints + DCM presets/rules). +# See /analysis_options.yaml at the workspace root. +include: ../../analysis_options.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + +dart_code_metrics: + rules: + # Dot shorthands require Dart 3.10; this package's SDK floor is 3.8 (see + # pubspec.yaml). Same constraint as the workspace root's + # prefer-shorthands-with-enums override. + prefer-shorthands-with-static-fields: false diff --git a/packages/flutter_codec/lib/flutter_codec.dart b/packages/flutter_codec/lib/flutter_codec.dart new file mode 100644 index 00000000..18a2ee68 --- /dev/null +++ b/packages/flutter_codec/lib/flutter_codec.dart @@ -0,0 +1,16 @@ +/// Flutter value codecs built on ACK schemas. +library; + +export 'src/borders.dart'; +export 'src/constraints.dart'; +export 'src/decoration_image.dart'; +export 'src/decorations.dart'; +export 'src/enums.dart'; +export 'src/gradients.dart'; +export 'src/image_providers.dart'; +export 'src/primitives.dart'; +export 'src/shadows.dart'; +export 'src/shape_borders.dart'; +export 'src/strut_style.dart'; +export 'src/text_style.dart'; +export 'src/widgets.dart'; diff --git a/packages/flutter_codec/lib/src/borders.dart b/packages/flutter_codec/lib/src/borders.dart new file mode 100644 index 00000000..85a5f1c1 --- /dev/null +++ b/packages/flutter_codec/lib/src/borders.dart @@ -0,0 +1,184 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show Border, BorderDirectional, BorderSide, BorderStyle, BoxBorder, Color; + +import 'enums.dart' show borderStyleCodec; +import 'json_readers.dart'; +import 'primitives/color.dart' show colorCodec; + +/// Named [BorderSide.strokeAlign] offsets, encoded as string aliases. +enum _StrokeAlign { inside, center, outside } + +/// Codec for [BorderSide.strokeAlign] values. +/// +/// Accepts the named aliases `"inside"`, `"center"`, and `"outside"` (mapping +/// to [BorderSide.strokeAlignInside], [BorderSide.strokeAlignCenter], and +/// [BorderSide.strokeAlignOutside]) as well as any finite number. Encoding +/// canonicalizes the three named offsets back to their aliases and emits any +/// other finite value as a number. +final strokeAlignCodec = Ack.codec( + input: Ack.anyOf([Ack.enumCodec(_StrokeAlign.values), Ack.number()]), + decode: _decodeStrokeAlign, + encode: _encodeStrokeAlign, +); + +double _decodeStrokeAlign(Object value) { + if (value is num) return value.toDouble(); + + return switch (value as _StrokeAlign) { + _StrokeAlign.inside => BorderSide.strokeAlignInside, + _StrokeAlign.center => BorderSide.strokeAlignCenter, + _StrokeAlign.outside => BorderSide.strokeAlignOutside, + }; +} + +Object _encodeStrokeAlign(double value) { + return switch (value) { + BorderSide.strokeAlignInside => _StrokeAlign.inside, + BorderSide.strokeAlignCenter => _StrokeAlign.center, + BorderSide.strokeAlignOutside => _StrokeAlign.outside, + _ => value, + }; +} + +/// Codec for [BorderSide], composing [colorCodec], [borderStyleCodec], and +/// [strokeAlignCodec]. +/// +/// The string `"none"` is a shorthand for [BorderSide.none]. Otherwise an +/// object `{color, width, style, strokeAlign}` is used, with each field +/// optional and falling back to the [BorderSide] constructor defaults — so +/// `{}` decodes to `const BorderSide()` (1px solid black, NOT +/// [BorderSide.none]; use `"none"` for that). +/// +/// Encoding canonicalizes [BorderSide.none] to `"none"` and emits a full +/// canonical `{color, width, style, strokeAlign}` object for any other value. +final borderSideCodec = Ack.codec( + input: Ack.anyOf([ + Ack.literal('none'), + Ack.object({ + 'color': colorCodec.withDefault(const Color(0xFF000000)), + 'width': Ack.number().min(0).withDefault(1.0), + 'style': borderStyleCodec.withDefault(BorderStyle.solid), + 'strokeAlign': strokeAlignCodec.withDefault(BorderSide.strokeAlignInside), + }), + ]), + decode: _decodeBorderSide, + encode: _encodeBorderSide, +); + +BorderSide _decodeBorderSide(Object value) { + if (value == 'none') return BorderSide.none; + + final map = value as JsonMap; + + return BorderSide( + color: readValue(map, 'color'), + width: readDouble(map, 'width'), + style: readValue(map, 'style'), + strokeAlign: readValue(map, 'strokeAlign'), + ); +} + +// Returns runtime property values (Color, BorderStyle, double), not JSON. The +// object schema re-encodes each property through its own schema (colorCodec, +// borderStyleCodec, strokeAlignCodec) to produce the JSON-safe boundary. +Object _encodeBorderSide(BorderSide value) { + if (value == BorderSide.none) return 'none'; + + return { + 'color': value.color, + 'width': value.width, + 'style': value.style, + 'strokeAlign': value.strokeAlign, + }; +} + +/// Codec for [Border]. A bare [BorderSide] shorthand (via [borderSideCodec]) +/// fans the same side across all four edges via [Border.fromBorderSide]; an +/// object `{top, right, bottom, left}` (each side optional, defaulting to +/// [BorderSide.none]) sets them individually. Encoding canonicalizes uniform +/// borders back to the side shorthand, so `Border()` round-trips through +/// `"none"` and `Border.all(...)` through a single side object. +/// +/// Note: `{}` decodes through the side branch to `Border.fromBorderSide(const +/// BorderSide())` — four 1px solid black sides — *not* `Border()`. Use +/// `"none"` for an empty border. +final borderCodec = Ack.codec( + input: Ack.anyOf([ + borderSideCodec, + Ack.object({ + 'top': borderSideCodec.withDefault(BorderSide.none), + 'right': borderSideCodec.withDefault(BorderSide.none), + 'bottom': borderSideCodec.withDefault(BorderSide.none), + 'left': borderSideCodec.withDefault(BorderSide.none), + }), + ]), + decode: _decodeBorder, + encode: _encodeBorder, +); + +Border _decodeBorder(Object value) { + if (value is BorderSide) return Border.fromBorderSide(value); + + final map = value as JsonMap; + + return Border( + top: readValue(map, 'top'), + right: readValue(map, 'right'), + bottom: readValue(map, 'bottom'), + left: readValue(map, 'left'), + ); +} + +Object _encodeBorder(Border value) { + if (value.top == value.right && + value.right == value.bottom && + value.bottom == value.left) { + return value.top; + } + + return { + 'top': value.top, + 'right': value.right, + 'bottom': value.bottom, + 'left': value.left, + }; +} + +/// Codec for [BorderDirectional], an object `{top, start, end, bottom}` (each +/// side optional, defaulting to [BorderSide.none]). Always encodes to the +/// object form — never a side shorthand — so the directional type round-trips +/// even when uniform or empty (a bare side is reserved for [Border]). +final borderDirectionalCodec = + Ack.object({ + 'top': borderSideCodec.withDefault(BorderSide.none), + 'start': borderSideCodec.withDefault(BorderSide.none), + 'end': borderSideCodec.withDefault(BorderSide.none), + 'bottom': borderSideCodec.withDefault(BorderSide.none), + }).codec( + decode: (data) => BorderDirectional( + top: readValue(data, 'top'), + start: readValue(data, 'start'), + end: readValue(data, 'end'), + bottom: readValue(data, 'bottom'), + ), + encode: (value) => { + 'top': value.top, + 'start': value.start, + 'end': value.end, + 'bottom': value.bottom, + }, + ); + +/// Codec for [BoxBorder], unioning [borderCodec] and [borderDirectionalCodec]. +/// +/// A bare side shorthand, an `{top, right, bottom, left}` object, and the +/// `"none"` alias decode to [Border]; objects carrying `start`/`end` decode to +/// [BorderDirectional] ([borderCodec] is tried first). Encoding dispatches by +/// runtime type. Mixed borders (the result of adding a [Border] to a +/// [BorderDirectional]) are not supported. +final boxBorderCodec = Ack.anyOf([borderCodec, borderDirectionalCodec]) + .codec( + decode: (value) => value as BoxBorder, + encode: (value) => value, + ); diff --git a/packages/flutter_codec/lib/src/constraints.dart b/packages/flutter_codec/lib/src/constraints.dart new file mode 100644 index 00000000..96b9fc42 --- /dev/null +++ b/packages/flutter_codec/lib/src/constraints.dart @@ -0,0 +1,74 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/rendering.dart' show BoxConstraints, Constraints; + +/// Codec for [BoxConstraints]. +/// +/// Bounds are emitted as a full canonical map. `double.infinity` is encoded as +/// `null` because JSON has no non-finite number literal. Omitted min bounds +/// decode to `0`; explicit null min bounds decode to `double.infinity`. +/// Omitted or null max bounds decode to `double.infinity`. +final boxConstraintsCodec = + Ack.object({ + 'minWidth': Ack.number().min(0).nullable().optional(), + 'maxWidth': Ack.number().min(0).nullable().optional(), + 'minHeight': Ack.number().min(0).nullable().optional(), + 'maxHeight': Ack.number().min(0).nullable().optional(), + }) + // Reject inverted bounds. The same null/infinity resolution the decoder + // uses is applied first, so this matches the BoxConstraints actually + // produced (and keeps the invariant in release builds, where Flutter's + // own `isNormalized` assert is stripped). + .refine( + (data) => + _readMinBound(data, 'minWidth') <= + _readMaxBound(data, 'maxWidth') && + _readMinBound(data, 'minHeight') <= + _readMaxBound(data, 'maxHeight'), + message: + 'BoxConstraints require minWidth <= maxWidth and ' + 'minHeight <= maxHeight.', + ) + .codec( + decode: (data) => BoxConstraints( + minWidth: _readMinBound(data, 'minWidth'), + maxWidth: _readMaxBound(data, 'maxWidth'), + minHeight: _readMinBound(data, 'minHeight'), + maxHeight: _readMaxBound(data, 'maxHeight'), + ), + encode: (value) => { + 'minWidth': _encodeBound(value.minWidth), + 'maxWidth': _encodeBound(value.maxWidth), + 'minHeight': _encodeBound(value.minHeight), + 'maxHeight': _encodeBound(value.maxHeight), + }, + ); + +/// Codec for Flutter [Constraints], discriminated by `"type"`. +/// +/// Fields that are statically typed as [BoxConstraints] should continue to use +/// [boxConstraintsCodec] directly. Use this union only where the runtime +/// constraints subtype is ambiguous. +final DiscriminatedObjectSchema constraintsCodec = + Ack.discriminated( + discriminatorKey: 'type', + schemas: {'box': boxConstraintsCodec}, + ); + +double _readMinBound(JsonMap data, String key) { + if (!data.containsKey(key)) return 0; + final value = data[key]; + if (value == null) return double.infinity; + + return (value as num).toDouble(); +} + +double _readMaxBound(JsonMap data, String key) { + final value = data[key]; + if (value == null) return double.infinity; + + return (value as num).toDouble(); +} + +double? _encodeBound(double value) { + return value == double.infinity ? null : value; +} diff --git a/packages/flutter_codec/lib/src/decoration_image.dart b/packages/flutter_codec/lib/src/decoration_image.dart new file mode 100644 index 00000000..140234ef --- /dev/null +++ b/packages/flutter_codec/lib/src/decoration_image.dart @@ -0,0 +1,89 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show Alignment, BoxFit, DecorationImage, FilterQuality, ImageRepeat; + +import 'enums.dart' show boxFitCodec, filterQualityCodec, imageRepeatCodec; +import 'image_providers.dart' show imageProviderCodec; +import 'json_readers.dart'; +import 'primitives/alignment.dart' show alignmentGeometryCodec; +import 'primitives/rect.dart' show rectCodec; + +/// Codec for [DecorationImage]. +/// +/// Composes [imageProviderCodec] (the required image), the [BoxFit] / +/// [ImageRepeat] / [FilterQuality] enum codecs, [alignmentGeometryCodec], and +/// [rectCodec]. All non-`image` fields default to the Flutter +/// [DecorationImage] constructor defaults. +/// +/// Note: `opacity` is range-validated `[0, 1]` here. Flutter only clamps it +/// at paint time, so this codec is stricter than the constructor — invalid +/// inputs fail to parse rather than silently clamp. +/// +/// Intentionally unsupported: +/// * `colorFilter` — `ColorFilter` keeps its constructor arguments +/// (`color`, `blendMode`, `matrix`, type discriminator) in library-private +/// fields with no public getters, and exposes the same `runtimeType` for +/// all four constructor variants. There is no portable, contract-stable +/// way to inspect an existing instance back to JSON, so a bidirectional +/// codec is not achievable via the public API. The same constraint applies +/// to `ImageFilter` (private subtypes, private state). +/// * `onError` — callback type, not serializable. +/// +/// Both are dropped because the schema has no field for them. [onError] is +/// excluded from [DecorationImage]'s `==`, so its loss is invisible. But +/// `colorFilter` *is* compared by `==` and `hashCode`, so a [DecorationImage] +/// with a non-null `colorFilter` cannot round-trip: encoding one throws +/// (rather than silently producing an unequal value), mirroring the +/// `assetImageCodec` `bundle` guard. +final decorationImageCodec = + Ack.object({ + 'image': imageProviderCodec, + 'fit': boxFitCodec.nullable().optional(), + 'alignment': alignmentGeometryCodec.withDefault(Alignment.center), + 'centerSlice': rectCodec.nullable().optional(), + 'repeat': imageRepeatCodec.withDefault(ImageRepeat.noRepeat), + 'matchTextDirection': Ack.boolean().withDefault(false), + 'scale': Ack.number().withDefault(1.0), + 'opacity': Ack.number().min(0).max(1).withDefault(1.0), + 'filterQuality': filterQualityCodec.withDefault(FilterQuality.medium), + 'invertColors': Ack.boolean().withDefault(false), + 'isAntiAlias': Ack.boolean().withDefault(false), + }).codec( + decode: (data) => DecorationImage( + image: readValue(data, 'image'), + fit: readNullableValue(data, 'fit'), + alignment: readValue(data, 'alignment'), + centerSlice: readNullableValue(data, 'centerSlice'), + repeat: readValue(data, 'repeat'), + matchTextDirection: readValue(data, 'matchTextDirection'), + scale: readDouble(data, 'scale'), + opacity: readDouble(data, 'opacity'), + filterQuality: readValue(data, 'filterQuality'), + invertColors: readValue(data, 'invertColors'), + isAntiAlias: readValue(data, 'isAntiAlias'), + ), + encode: (value) { + if (value.colorFilter != null) { + throw FormatException( + 'DecorationImage.colorFilter cannot be encoded: ColorFilter keeps ' + 'its state in library-private fields with no public getters, so it ' + 'has no portable JSON shape, and it is part of DecorationImage ' + 'equality. Remove the colorFilter before encoding.', + ); + } + + return { + 'image': value.image, + 'fit': value.fit, + 'alignment': value.alignment, + 'centerSlice': value.centerSlice, + 'repeat': value.repeat, + 'matchTextDirection': value.matchTextDirection, + 'scale': value.scale, + 'opacity': value.opacity, + 'filterQuality': value.filterQuality, + 'invertColors': value.invertColors, + 'isAntiAlias': value.isAntiAlias, + }; + }, + ); diff --git a/packages/flutter_codec/lib/src/decorations.dart b/packages/flutter_codec/lib/src/decorations.dart new file mode 100644 index 00000000..6c18aeeb --- /dev/null +++ b/packages/flutter_codec/lib/src/decorations.dart @@ -0,0 +1,152 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show BoxDecoration, BoxShape, Decoration, ShapeDecoration; + +import 'borders.dart' show boxBorderCodec; +import 'decoration_image.dart' show decorationImageCodec; +import 'enums.dart' show blendModeCodec, boxShapeCodec; +import 'gradients.dart' show gradientCodec; +import 'json_readers.dart'; +import 'primitives/border_radius.dart' show borderRadiusGeometryCodec; +import 'primitives/color.dart' show colorCodec; +import 'shadows.dart' show boxShadowCodec; +import 'shape_borders.dart' show shapeBorderCodec; + +/// Codec for [BoxDecoration]. +/// +/// Composes every JSON-safe constructor field: `color` ([colorCodec]), +/// `image` ([decorationImageCodec]), `border` ([boxBorderCodec]), +/// `borderRadius` ([borderRadiusGeometryCodec]), `boxShadow` +/// ([boxShadowCodec]), `gradient` ([gradientCodec]), `backgroundBlendMode` +/// ([blendModeCodec]), and `shape` ([boxShapeCodec], default +/// [BoxShape.rectangle]). The `"type"` discriminator is added by +/// [decorationCodec] when this codec is used as one of its branches. +final boxDecorationCodec = + Ack.object({ + 'color': colorCodec.nullable().optional(), + 'image': decorationImageCodec.nullable().optional(), + 'border': boxBorderCodec.nullable().optional(), + 'borderRadius': borderRadiusGeometryCodec.nullable().optional(), + 'boxShadow': Ack.list(boxShadowCodec).nullable().optional(), + 'gradient': gradientCodec.nullable().optional(), + 'backgroundBlendMode': blendModeCodec.nullable().optional(), + 'shape': boxShapeCodec.withDefault(BoxShape.rectangle), + }) + // Enforced here (not just by the constructor's debug assert) so the + // check holds in release builds. + .refine( + (data) => + data['backgroundBlendMode'] == null || + data['color'] != null || + data['gradient'] != null, + message: + 'BoxDecoration.backgroundBlendMode requires a color or gradient.', + ) + // BoxDecoration asserts a circle has no borderRadius; enforce it here + // too so the rule holds in release builds. + .refine( + (data) => + data['shape'] != BoxShape.circle || data['borderRadius'] == null, + message: + 'BoxDecoration with shape BoxShape.circle cannot set borderRadius.', + ) + .codec( + decode: _decodeBoxDecoration, + encode: _encodeBoxDecoration, + ); + +BoxDecoration _decodeBoxDecoration(JsonMap data) { + return BoxDecoration( + color: readNullableValue(data, 'color'), + image: readNullableValue(data, 'image'), + border: readNullableValue(data, 'border'), + borderRadius: readNullableValue(data, 'borderRadius'), + boxShadow: readNullableList(data, 'boxShadow'), + gradient: readNullableValue(data, 'gradient'), + backgroundBlendMode: readNullableValue(data, 'backgroundBlendMode'), + shape: readValue(data, 'shape'), + ); +} + +JsonMap _encodeBoxDecoration(BoxDecoration value) { + return { + 'color': value.color, + 'image': value.image, + 'border': value.border, + 'borderRadius': value.borderRadius, + 'boxShadow': value.boxShadow, + 'gradient': value.gradient, + 'backgroundBlendMode': value.backgroundBlendMode, + 'shape': value.shape, + }; +} + +/// Codec for [ShapeDecoration]. +/// +/// Composes every JSON-safe constructor field: `color` ([colorCodec]), +/// `image` ([decorationImageCodec]), `gradient` ([gradientCodec]), `shadows` +/// ([boxShadowCodec]), and the required `shape` ([shapeBorderCodec]). Unset +/// optional fields are emitted as explicit nulls for round-trip stability, +/// matching the canonical-map convention used by [boxDecorationCodec]. The +/// `"type"` discriminator is added by [decorationCodec] when this codec is +/// used as one of its branches. +/// +/// [ShapeDecoration] asserts that `color` and `gradient` cannot both be +/// non-null; this codec enforces the same rule with a refinement so it holds +/// in release builds (where the constructor assert is stripped). +final shapeDecorationCodec = + Ack.object({ + 'color': colorCodec.nullable().optional(), + 'image': decorationImageCodec.nullable().optional(), + 'gradient': gradientCodec.nullable().optional(), + 'shadows': Ack.list(boxShadowCodec).nullable().optional(), + 'shape': shapeBorderCodec, + }) + .refine( + (data) => data['color'] == null || data['gradient'] == null, + message: 'ShapeDecoration cannot set both color and gradient.', + ) + .codec( + decode: _decodeShapeDecoration, + encode: _encodeShapeDecoration, + ); + +ShapeDecoration _decodeShapeDecoration(JsonMap data) { + return ShapeDecoration( + color: readNullableValue(data, 'color'), + image: readNullableValue(data, 'image'), + gradient: readNullableValue(data, 'gradient'), + shadows: readNullableList(data, 'shadows'), + shape: readValue(data, 'shape'), + ); +} + +JsonMap _encodeShapeDecoration(ShapeDecoration value) { + return { + 'color': value.color, + 'image': value.image, + 'gradient': value.gradient, + 'shadows': value.shadows, + 'shape': value.shape, + }; +} + +/// Codec for the abstract [Decoration] type, discriminated by `"type"`. +/// +/// * `"box"` → [BoxDecoration] via [boxDecorationCodec] +/// * `"shape"` → [ShapeDecoration] via [shapeDecorationCodec] +/// +/// The `"type"` discriminator is synthesized by the union: encoding adds the +/// key automatically, and parsing uses it to select the branch. Each +/// underlying codec ([boxDecorationCodec], [shapeDecorationCodec]) remains +/// usable on its own without a `"type"` field — unlike the gradient family, +/// the decoration branches do not embed a `"type"` literal in their standalone +/// schemas, so the discriminator only exists at the union layer. +/// +/// Other [Decoration] subtypes ([FlutterLogoDecoration], custom decorations) +/// are intentionally not covered — they either lack a portable JSON shape or +/// belong outside the painting layer. +final decorationCodec = Ack.discriminated( + discriminatorKey: 'type', + schemas: {'box': boxDecorationCodec, 'shape': shapeDecorationCodec}, +); diff --git a/packages/flutter_codec/lib/src/enums.dart b/packages/flutter_codec/lib/src/enums.dart new file mode 100644 index 00000000..4f3698f3 --- /dev/null +++ b/packages/flutter_codec/lib/src/enums.dart @@ -0,0 +1,147 @@ +import 'dart:ui' show BoxHeightStyle, BoxWidthStyle; + +import 'package:ack/ack.dart'; +import 'package:flutter/foundation.dart' show Brightness, TargetPlatform; +import 'package:flutter/gestures.dart' show DragStartBehavior; +import 'package:flutter/material.dart' show MaterialTapTargetSize, ThemeMode; +import 'package:flutter/painting.dart' + show + Axis, + AxisDirection, + BlendMode, + BlurStyle, + BorderStyle, + BoxFit, + BoxShape, + Clip, + FilterQuality, + FontStyle, + ImageRepeat, + PaintingStyle, + PathFillType, + PlaceholderAlignment, + StrokeCap, + StrokeJoin, + TextAlign, + TextBaseline, + TextDecorationStyle, + TextDirection, + TextLeadingDistribution, + TextOverflow, + TextWidthBasis, + TileMode, + VerticalDirection, + WebHtmlElementStrategy; +import 'package:flutter/rendering.dart' + show + CrossAxisAlignment, + DecorationPosition, + FlexFit, + GrowthDirection, + HitTestBehavior, + MainAxisAlignment, + MainAxisSize, + ScrollDirection, + StackFit, + WrapAlignment, + WrapCrossAlignment; +import 'package:flutter/services.dart' show TextCapitalization; +import 'package:flutter/widgets.dart' show ScrollViewKeyboardDismissBehavior; + +final axisCodec = Ack.enumCodec(Axis.values); + +final axisDirectionCodec = Ack.enumCodec(AxisDirection.values); + +final blendModeCodec = Ack.enumCodec(BlendMode.values); + +final blurStyleCodec = Ack.enumCodec(BlurStyle.values); + +final borderStyleCodec = Ack.enumCodec(BorderStyle.values); + +final boxFitCodec = Ack.enumCodec(BoxFit.values); + +final boxHeightStyleCodec = Ack.enumCodec(BoxHeightStyle.values); + +final boxShapeCodec = Ack.enumCodec(BoxShape.values); + +final boxWidthStyleCodec = Ack.enumCodec(BoxWidthStyle.values); + +final brightnessCodec = Ack.enumCodec(Brightness.values); + +final clipCodec = Ack.enumCodec(Clip.values); + +final crossAxisAlignmentCodec = Ack.enumCodec(CrossAxisAlignment.values); + +final decorationPositionCodec = Ack.enumCodec(DecorationPosition.values); + +final dragStartBehaviorCodec = Ack.enumCodec(DragStartBehavior.values); + +final filterQualityCodec = Ack.enumCodec(FilterQuality.values); + +final flexFitCodec = Ack.enumCodec(FlexFit.values); + +final fontStyleCodec = Ack.enumCodec(FontStyle.values); + +final growthDirectionCodec = Ack.enumCodec(GrowthDirection.values); + +final hitTestBehaviorCodec = Ack.enumCodec(HitTestBehavior.values); + +final imageRepeatCodec = Ack.enumCodec(ImageRepeat.values); + +final webHtmlElementStrategyCodec = Ack.enumCodec( + WebHtmlElementStrategy.values, +); + +final mainAxisAlignmentCodec = Ack.enumCodec(MainAxisAlignment.values); + +final mainAxisSizeCodec = Ack.enumCodec(MainAxisSize.values); + +final materialTapTargetSizeCodec = Ack.enumCodec(MaterialTapTargetSize.values); + +final paintingStyleCodec = Ack.enumCodec(PaintingStyle.values); + +final pathFillTypeCodec = Ack.enumCodec(PathFillType.values); + +final placeholderAlignmentCodec = Ack.enumCodec(PlaceholderAlignment.values); + +final scrollDirectionCodec = Ack.enumCodec(ScrollDirection.values); + +final scrollViewKeyboardDismissBehaviorCodec = Ack.enumCodec( + ScrollViewKeyboardDismissBehavior.values, +); + +final stackFitCodec = Ack.enumCodec(StackFit.values); + +final strokeCapCodec = Ack.enumCodec(StrokeCap.values); + +final strokeJoinCodec = Ack.enumCodec(StrokeJoin.values); + +final targetPlatformCodec = Ack.enumCodec(TargetPlatform.values); + +final textAlignCodec = Ack.enumCodec(TextAlign.values); + +final textBaselineCodec = Ack.enumCodec(TextBaseline.values); + +final textCapitalizationCodec = Ack.enumCodec(TextCapitalization.values); + +final textDecorationStyleCodec = Ack.enumCodec(TextDecorationStyle.values); + +final textDirectionCodec = Ack.enumCodec(TextDirection.values); + +final textLeadingDistributionCodec = Ack.enumCodec( + TextLeadingDistribution.values, +); + +final textOverflowCodec = Ack.enumCodec(TextOverflow.values); + +final textWidthBasisCodec = Ack.enumCodec(TextWidthBasis.values); + +final themeModeCodec = Ack.enumCodec(ThemeMode.values); + +final tileModeCodec = Ack.enumCodec(TileMode.values); + +final verticalDirectionCodec = Ack.enumCodec(VerticalDirection.values); + +final wrapAlignmentCodec = Ack.enumCodec(WrapAlignment.values); + +final wrapCrossAlignmentCodec = Ack.enumCodec(WrapCrossAlignment.values); diff --git a/packages/flutter_codec/lib/src/font_family_packing.dart b/packages/flutter_codec/lib/src/font_family_packing.dart new file mode 100644 index 00000000..6c82c60a --- /dev/null +++ b/packages/flutter_codec/lib/src/font_family_packing.dart @@ -0,0 +1,80 @@ +// Internal helpers shared by [textStyleCodec] and [strutStyleCodec] for +// unfolding Flutter's `packages//` storage back to the +// user-supplied `(fontFamily, fontFamilyFallback, package)` triple. +// +// Flutter folds `package` into `fontFamily` at construction +// (`fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily'`) +// and stores the original `package` privately, so codecs have to recover +// the split heuristically when all referenced families share the same +// `packages//` prefix. + +/// Unfolds Flutter's `packages//` storage back to the +/// `(fontFamily, fontFamilyFallback, package)` triple when all referenced +/// families share the same prefix. Falls back to the stored (prefixed) form +/// when the prefix is missing or inconsistent. +/// +/// The primary [family] drives package recovery: +/// * A Dart `null` primary family (e.g. only a package-prefixed fallback was +/// supplied) recovers no package. Re-folding a recovered `package` into a +/// null family would yield the literal string `'packages//null'` (the +/// constructor interpolates the null family), corrupting the round-trip; +/// keeping the fallback verbatim with `package: null` reproduces the +/// original exactly because decode then performs no folding. +/// * A primary family that is already that folded-null *string* +/// `'packages//null'` — the shape Flutter stores for +/// `TextStyle(package: )` with no `fontFamily` — is recovered as a +/// genuine `null` primary family plus `package: `. Emitting the +/// four-char string `'null'` instead would round-trip through this library +/// but be wrong JSON for any other consumer. +/// +/// Note: a literal `fontFamily: 'packages//'` supplied without a +/// `package:` argument is indistinguishable from the folded +/// `(fontFamily: '', package: '')` form (the original `_package` is +/// private and is compared by `TextStyle` equality). It is intentionally +/// interpreted as package-qualified — the common case — so such a literal +/// does not round-trip under `TextStyle` equality, though the resolved font +/// family string is preserved. This includes the ` == 'null'` sentinel: a +/// literal `'packages//null'` is read as `package: ` with a null +/// family, the same documented tradeoff. +({String? family, List? fallback, String? packageName}) +unpackFontFamily(String? family, List? fallback) { + final pkg = _sharedPackagePrefix([if (family != null) family, ...?fallback]); + if (pkg == null || family == null) { + return (family: family, fallback: fallback, packageName: null); + } + + final prefix = 'packages/$pkg/'; + String strip(String f) => + f.startsWith(prefix) ? f.substring(prefix.length) : f; + + // Flutter folds a null fontFamily with a package into the literal + // 'packages//null' (it interpolates the null family). Recover that as a + // genuine null primary family instead of the four-char string 'null'. + final resolvedFamily = family == '${prefix}null' ? null : strip(family); + + return ( + family: resolvedFamily, + fallback: fallback?.map(strip).toList(), + packageName: pkg, + ); +} + +// Returns the package name shared by every `packages//` entry +// in `families`, or null if any entry lacks the prefix or disagrees. +String? _sharedPackagePrefix(List families) { + const prefix = 'packages/'; + String? shared; + for (final family in families) { + if (!family.startsWith(prefix)) return null; + + final rest = family.substring(prefix.length); + final separator = rest.indexOf('/'); + if (separator <= 0 || separator == rest.length - 1) return null; + + final name = rest.substring(0, separator); + shared ??= name; + if (shared != name) return null; + } + + return shared; +} diff --git a/packages/flutter_codec/lib/src/gradients.dart b/packages/flutter_codec/lib/src/gradients.dart new file mode 100644 index 00000000..4d59ed42 --- /dev/null +++ b/packages/flutter_codec/lib/src/gradients.dart @@ -0,0 +1,200 @@ +import 'dart:math' as math; + +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show + Alignment, + Gradient, + GradientTransform, + LinearGradient, + RadialGradient, + SweepGradient, + TileMode; + +import 'enums.dart' show tileModeCodec; +import 'json_readers.dart'; +import 'primitives/alignment.dart' show alignmentGeometryCodec; +import 'primitives/color.dart' show colorCodec; + +// Gradients accept an arbitrary [GradientTransform] — an open abstract type +// with no public, portable representation. Encoding one would silently drop it +// (`Gradient.==` compares `transform`), so it is rejected loudly instead. +void _requireEncodableTransform(GradientTransform? transform) { + if (transform != null) { + throw FormatException( + 'Gradient.transform cannot be encoded: GradientTransform has no portable ' + 'JSON shape. Apply gradient transforms outside the codec layer.', + ); + } +} + +// `stops`, when non-null, must align 1:1 with `colors`. Flutter only enforces +// this at paint time, so a mismatched-length gradient would otherwise encode to +// an invalid shape. Absent/null `stops` is valid (evenly distributed). +bool _stopsMatchColors(JsonMap data) { + final stops = data['stops']; + if (stops is! List) return true; + final colors = data['colors']; + + return colors is List && stops.length == colors.length; +} + +bool _stopsAscending(JsonMap data) { + final stops = data['stops']; + if (stops is! List) return true; + for (var index = 0; index < stops.length - 1; index++) { + final current = stops[index]; + final next = stops[index + 1]; + if (current is! num || next is! num) return true; + if (current > next) return false; + } + + return true; +} + +const _stopsLengthMessage = + 'Gradient stops, when provided, must have the same length as colors.'; +const _stopsAscendingMessage = 'Gradient stops must be in ascending order.'; + +final _gradientStopsSchema = Ack.list( + Ack.number().min(0).max(1), +).nullable().optional(); + +/// Codec for [LinearGradient]. Tagged with `"type": "linear"`. +/// +/// `colors` is required and must contain at least two entries. `stops`, when +/// non-null, must have the same length as `colors`, be ordered ascending, and +/// stay within `[0, 1]`. `transform` is not supported — apply gradient +/// transforms outside the codec layer. +final linearGradientCodec = + Ack.object({ + 'type': Ack.literal('linear'), + 'begin': alignmentGeometryCodec.withDefault(Alignment.centerLeft), + 'end': alignmentGeometryCodec.withDefault(Alignment.centerRight), + 'colors': Ack.list(colorCodec).minItems(2), + 'stops': _gradientStopsSchema, + 'tileMode': tileModeCodec.withDefault(TileMode.clamp), + }) + .refine(_stopsMatchColors, message: _stopsLengthMessage) + .refine(_stopsAscending, message: _stopsAscendingMessage) + .codec( + decode: (data) => LinearGradient( + begin: readValue(data, 'begin'), + end: readValue(data, 'end'), + colors: readList(data, 'colors'), + stops: readNullableDoubleList(data, 'stops'), + tileMode: readValue(data, 'tileMode'), + ), + encode: (value) { + _requireEncodableTransform(value.transform); + + return { + 'type': 'linear', + 'begin': value.begin, + 'end': value.end, + 'colors': value.colors, + 'stops': value.stops, + 'tileMode': value.tileMode, + }; + }, + ); + +/// Codec for [RadialGradient]. Tagged with `"type": "radial"`. +/// +/// `radius` and `focalRadius` are non-negative. `focal` is optional. See +/// [linearGradientCodec] for shared notes on `colors`, `stops`, and +/// `transform`. +final radialGradientCodec = + Ack.object({ + 'type': Ack.literal('radial'), + 'center': alignmentGeometryCodec.withDefault(Alignment.center), + 'radius': Ack.number().min(0).withDefault(0.5), + 'colors': Ack.list(colorCodec).minItems(2), + 'stops': _gradientStopsSchema, + 'tileMode': tileModeCodec.withDefault(TileMode.clamp), + 'focal': alignmentGeometryCodec.nullable().optional(), + 'focalRadius': Ack.number().min(0).withDefault(0.0), + }) + .refine(_stopsMatchColors, message: _stopsLengthMessage) + .refine(_stopsAscending, message: _stopsAscendingMessage) + .codec( + decode: (data) => RadialGradient( + center: readValue(data, 'center'), + radius: readDouble(data, 'radius'), + colors: readList(data, 'colors'), + stops: readNullableDoubleList(data, 'stops'), + tileMode: readValue(data, 'tileMode'), + focal: readNullableValue(data, 'focal'), + focalRadius: readDouble(data, 'focalRadius'), + ), + encode: (value) { + _requireEncodableTransform(value.transform); + + return { + 'type': 'radial', + 'center': value.center, + 'radius': value.radius, + 'colors': value.colors, + 'stops': value.stops, + 'tileMode': value.tileMode, + 'focal': value.focal, + 'focalRadius': value.focalRadius, + }; + }, + ); + +/// Codec for [SweepGradient]. Tagged with `"type": "sweep"`. +/// +/// `startAngle` and `endAngle` are radians (default `0.0` and `2π`). See +/// [linearGradientCodec] for shared notes on `colors`, `stops`, and +/// `transform`. +final sweepGradientCodec = + Ack.object({ + 'type': Ack.literal('sweep'), + 'center': alignmentGeometryCodec.withDefault(Alignment.center), + 'startAngle': Ack.number().withDefault(0.0), + 'endAngle': Ack.number().withDefault(math.pi * 2), + 'colors': Ack.list(colorCodec).minItems(2), + 'stops': _gradientStopsSchema, + 'tileMode': tileModeCodec.withDefault(TileMode.clamp), + }) + .refine(_stopsMatchColors, message: _stopsLengthMessage) + .refine(_stopsAscending, message: _stopsAscendingMessage) + .codec( + decode: (data) => SweepGradient( + center: readValue(data, 'center'), + startAngle: readDouble(data, 'startAngle'), + endAngle: readDouble(data, 'endAngle'), + colors: readList(data, 'colors'), + stops: readNullableDoubleList(data, 'stops'), + tileMode: readValue(data, 'tileMode'), + ), + encode: (value) { + _requireEncodableTransform(value.transform); + + return { + 'type': 'sweep', + 'center': value.center, + 'startAngle': value.startAngle, + 'endAngle': value.endAngle, + 'colors': value.colors, + 'stops': value.stops, + 'tileMode': value.tileMode, + }; + }, + ); + +/// Codec for [Gradient], discriminated by a `"type"` key (`"linear"`, +/// `"radial"`, or `"sweep"`). Each branch is the corresponding concrete +/// codec, upcast to the union runtime type. The standalone codecs +/// ([linearGradientCodec], [radialGradientCodec], [sweepGradientCodec]) carry +/// the same `"type"` literal, so a value encoded through this union round-trips +/// through them and vice versa. +final gradientCodec = Ack.discriminated( + discriminatorKey: 'type', + schemas: { + 'linear': linearGradientCodec, + 'radial': radialGradientCodec, + 'sweep': sweepGradientCodec, + }, +); diff --git a/packages/flutter_codec/lib/src/image_providers.dart b/packages/flutter_codec/lib/src/image_providers.dart new file mode 100644 index 00000000..2ba70c81 --- /dev/null +++ b/packages/flutter_codec/lib/src/image_providers.dart @@ -0,0 +1,83 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show AssetImage, ImageProvider, NetworkImage, WebHtmlElementStrategy; +import 'package:flutter/services.dart' show AssetBundle; + +import 'enums.dart' show webHtmlElementStrategyCodec; +import 'json_readers.dart'; + +final _headersCodec = Ack.object({}, additionalProperties: true) + .refine( + (value) => value.values.every((headerValue) => headerValue is String), + message: 'NetworkImage headers must be a JSON object with string values.', + ) + .codec>( + decode: (value) => value.cast(), + encode: (value) => Map.unmodifiable(value), + ); + +/// Codec for [NetworkImage]. +/// +/// Maps the portable public constructor fields only: `url`, `scale`, +/// `headers`, and `webHtmlElementStrategy`. The `"type"` discriminator is +/// added by [imageProviderCodec] when this codec is used as one of its +/// branches. +final networkImageCodec = + Ack.object({ + 'url': Ack.string().notEmpty(), + 'scale': Ack.number().min(0).withDefault(1.0), + 'headers': _headersCodec.nullable().optional(), + 'webHtmlElementStrategy': webHtmlElementStrategyCodec.withDefault( + WebHtmlElementStrategy.never, + ), + }).codec( + decode: (data) => NetworkImage( + readValue(data, 'url'), + scale: readDouble(data, 'scale'), + headers: readNullableValue(data, 'headers'), + webHtmlElementStrategy: readValue(data, 'webHtmlElementStrategy'), + ), + encode: (value) => { + 'url': value.url, + 'scale': value.scale, + 'headers': value.headers, + 'webHtmlElementStrategy': value.webHtmlElementStrategy, + }, + ); + +/// Codec for [AssetImage]. +/// +/// Custom [AssetBundle] instances are intentionally unsupported because they +/// are not portable through JSON. Use package-qualified assets for JSON-safe +/// asset references. The `"type"` discriminator is added by +/// [imageProviderCodec] when this codec is used as one of its branches. +final assetImageCodec = + Ack.object({ + 'assetName': Ack.string().notEmpty(), + 'package': Ack.string().nullable().optional(), + }).codec( + decode: (data) => AssetImage( + readValue(data, 'assetName'), + package: readNullableValue(data, 'package'), + ), + encode: (value) { + if (value.bundle != null) { + throw FormatException( + 'AssetImage.bundle is not supported by assetImageCodec.', + ); + } + + return {'assetName': value.assetName, 'package': value.package}; + }, + ); + +/// Codec for JSON-safe [ImageProvider] values, discriminated by `"type"`. +/// +/// Support is intentionally limited to [NetworkImage] (`"network"`) and +/// [AssetImage] (`"asset"`). Recursive providers ([ResizeImage]), local files +/// ([FileImage]), memory blobs ([MemoryImage]), custom providers, and custom +/// asset bundles are rejected instead of guessing a non-portable JSON shape. +final imageProviderCodec = Ack.discriminated>( + discriminatorKey: 'type', + schemas: {'network': networkImageCodec, 'asset': assetImageCodec}, +); diff --git a/packages/flutter_codec/lib/src/json_readers.dart b/packages/flutter_codec/lib/src/json_readers.dart new file mode 100644 index 00000000..6d8e19ec --- /dev/null +++ b/packages/flutter_codec/lib/src/json_readers.dart @@ -0,0 +1,41 @@ +import 'package:ack/ack.dart'; + +/// Reads the required field [key] from a decoded [map] as [T]. +T readValue(JsonMap map, String key) => map[key]! as T; + +/// Reads the optional field [key] from a decoded [map] as [T]. +T? readNullableValue(JsonMap map, String key) => map[key] as T?; + +/// Reads the required numeric field [key] from a decoded [map] as a `double`. +/// +/// The schema has already validated the field, so the value is present and a +/// `num`; this centralizes the cast and `toDouble` conversion shared by +/// object-shaped codec decoders. +double readDouble(JsonMap map, String key) => (map[key]! as num).toDouble(); + +/// Reads the optional numeric field [key] from a decoded [map] as a `double`. +double? readNullableDouble(JsonMap map, String key) => + (map[key] as num?)?.toDouble(); + +/// Reads the required list field [key] from a decoded [map] as `List`. +/// +/// Not for numeric `T`: `cast()` does not coerce JSON ints and would +/// throw on iteration. Use [readDoubleList] / [readNullableDoubleList] for +/// numeric lists. +List readList(JsonMap map, String key) => + (map[key]! as List).cast().toList(); + +/// Reads the optional list field [key] from a decoded [map] as `List`. +List? readNullableList(JsonMap map, String key) => + (map[key] as List?)?.cast().toList(); + +/// Reads the required numeric list field [key] as `List`. +/// +/// Coerces JSON ints to doubles (unlike `readList`, whose `cast` would +/// throw on a JSON int). +List readDoubleList(JsonMap map, String key) => + (map[key]! as List).map((value) => (value as num).toDouble()).toList(); + +/// Reads the optional numeric list field [key] as `List`. +List? readNullableDoubleList(JsonMap map, String key) => + (map[key] as List?)?.map((value) => (value as num).toDouble()).toList(); diff --git a/packages/flutter_codec/lib/src/primitives.dart b/packages/flutter_codec/lib/src/primitives.dart new file mode 100644 index 00000000..2aef18bb --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives.dart @@ -0,0 +1,14 @@ +export 'primitives/alignment.dart'; +export 'primitives/border_radius.dart'; +export 'primitives/color.dart'; +export 'primitives/edge_insets.dart'; +export 'primitives/font_feature.dart'; +export 'primitives/font_variation.dart'; +export 'primitives/font_weight.dart'; +export 'primitives/locale.dart'; +export 'primitives/matrix4.dart'; +export 'primitives/offset.dart'; +export 'primitives/radius.dart'; +export 'primitives/rect.dart'; +export 'primitives/text_decoration.dart'; +export 'primitives/text_height_behavior.dart'; diff --git a/packages/flutter_codec/lib/src/primitives/alignment.dart b/packages/flutter_codec/lib/src/primitives/alignment.dart new file mode 100644 index 00000000..28dfc455 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/alignment.dart @@ -0,0 +1,159 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show Alignment, AlignmentDirectional, AlignmentGeometry; + +import '../json_readers.dart'; + +/// Named [Alignment] constants, encoded as string aliases. +enum _Alignment { + topLeft(Alignment.topLeft), + topCenter(Alignment.topCenter), + topRight(Alignment.topRight), + centerLeft(Alignment.centerLeft), + center(Alignment.center), + centerRight(Alignment.centerRight), + bottomLeft(Alignment.bottomLeft), + bottomCenter(Alignment.bottomCenter), + bottomRight(Alignment.bottomRight); + + const _Alignment(this.value); + + final Alignment value; +} + +/// Codec for [Alignment]. Named constants (`"center"`, `"topLeft"`, …) encode +/// and decode as strings; arbitrary values use `{"x": ..., "y": ...}`. Encoding +/// emits the name when the value matches a constant, otherwise the object. +final alignmentCodec = Ack.codec( + input: Ack.anyOf([ + Ack.enumCodec(_Alignment.values), + Ack.object({'x': Ack.number(), 'y': Ack.number()}), + ]), + decode: _decodeAlignment, + encode: _encodeAlignment, +); + +Alignment _decodeAlignment(Object value) { + if (value is _Alignment) return value.value; + + final map = value as JsonMap; + + return Alignment(readDouble(map, 'x'), readDouble(map, 'y')); +} + +Object _encodeAlignment(Alignment value) { + for (final named in _Alignment.values) { + if (named.value == value) return named; + } + + return {'x': value.x, 'y': value.y}; +} + +/// Named [AlignmentDirectional] constants, encoded as string aliases. +enum _AlignmentDirectional { + topStart(AlignmentDirectional.topStart), + topCenter(AlignmentDirectional.topCenter), + topEnd(AlignmentDirectional.topEnd), + centerStart(AlignmentDirectional.centerStart), + center(AlignmentDirectional.center), + centerEnd(AlignmentDirectional.centerEnd), + bottomStart(AlignmentDirectional.bottomStart), + bottomCenter(AlignmentDirectional.bottomCenter), + bottomEnd(AlignmentDirectional.bottomEnd); + + const _AlignmentDirectional(this.value); + + final AlignmentDirectional value; +} + +/// Codec for [AlignmentDirectional]. Named constants (`"centerStart"`, +/// `"topEnd"`, …) encode and decode as strings; arbitrary values use +/// `{"start": ..., "y": ...}`. Encoding emits the name when the value matches a +/// constant, otherwise the object. +final alignmentDirectionalCodec = + Ack.codec( + input: Ack.anyOf([ + Ack.enumCodec(_AlignmentDirectional.values), + Ack.object({'start': Ack.number(), 'y': Ack.number()}), + ]), + decode: _decodeAlignmentDirectional, + encode: _encodeAlignmentDirectional, + ); + +AlignmentDirectional _decodeAlignmentDirectional(Object value) { + if (value is _AlignmentDirectional) return value.value; + + final map = value as JsonMap; + + return AlignmentDirectional(readDouble(map, 'start'), readDouble(map, 'y')); +} + +Object _encodeAlignmentDirectional(AlignmentDirectional value) { + for (final named in _AlignmentDirectional.values) { + if (named.value == value) return named; + } + + return {'start': value.start, 'y': value.y}; +} + +/// Codec for [AlignmentGeometry]. +/// +/// Decoding: the regular names and `{x, y}` produce [Alignment]; the +/// directional names and `{start, y}` produce [AlignmentDirectional]. The +/// shared center-column names (`"center"`, `"topCenter"`, `"bottomCenter"`) +/// decode to [Alignment], since the [Alignment] forms are tried first. +/// +/// Encoding: an [Alignment] uses its name or `{x, y}`. An [AlignmentDirectional] +/// uses its name too, except the three center-column constants +/// ([AlignmentDirectional.topCenter], `.center`, `.bottomCenter`) whose names +/// collide with [Alignment] and would otherwise decode back as [Alignment]; +/// those are emitted as `{start, y}` so they round-trip as directional values. +/// (The standalone [alignmentDirectionalCodec] has no such collision and keeps +/// emitting names.) +/// +/// Mixed alignments (the result of adding an [Alignment] to an +/// [AlignmentDirectional]) are not supported. +final alignmentGeometryCodec = Ack.codec( + input: Ack.anyOf([ + Ack.enumCodec(_Alignment.values), + Ack.object({'x': Ack.number(), 'y': Ack.number()}), + Ack.enumCodec(_AlignmentDirectional.values), + Ack.object({'start': Ack.number(), 'y': Ack.number()}), + ]), + decode: _decodeAlignmentGeometry, + encode: _encodeAlignmentGeometry, +); + +AlignmentGeometry _decodeAlignmentGeometry(Object value) { + final isDirectional = + value is _AlignmentDirectional || + (value is JsonMap && value.containsKey('start')); + + return isDirectional + ? _decodeAlignmentDirectional(value) + : _decodeAlignment(value); +} + +/// The center-column directional constants share a spelling with [Alignment] +/// names, so they must not be emitted as names through [alignmentGeometryCodec]. +/// (Not `const`: [AlignmentDirectional] overrides `==`.) +final _centerColumnDirectionals = { + AlignmentDirectional.topCenter, + AlignmentDirectional.center, + AlignmentDirectional.bottomCenter, +}; + +Object _encodeAlignmentGeometry(AlignmentGeometry value) { + if (value is Alignment) return _encodeAlignment(value); + if (value is AlignmentDirectional) { + // The center-column names would decode back as Alignment; emit the + // {start, y} object form for them so they stay directional. + return _centerColumnDirectionals.contains(value) + ? {'start': value.start, 'y': value.y} + : _encodeAlignmentDirectional(value); + } + throw FormatException( + 'alignmentGeometryCodec cannot encode ${value.runtimeType}; only ' + 'Alignment and AlignmentDirectional are supported.', + ); +} diff --git a/packages/flutter_codec/lib/src/primitives/border_radius.dart b/packages/flutter_codec/lib/src/primitives/border_radius.dart new file mode 100644 index 00000000..eebd3354 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/border_radius.dart @@ -0,0 +1,95 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show BorderRadius, BorderRadiusDirectional, BorderRadiusGeometry, Radius; + +import '../json_readers.dart'; +import 'radius.dart' show radiusCodec; + +/// Codec for [BorderRadius]. A single radius (a number or `{x,y}`) sets all four +/// corners; an object `{topLeft, topRight, bottomLeft, bottomRight}` (each corner +/// optional, defaulting to `Radius.zero`) sets them individually. Encoding emits +/// a single radius when all corners are equal, otherwise the full object. +final borderRadiusCodec = Ack.codec( + input: Ack.anyOf([ + radiusCodec, + Ack.object({ + 'topLeft': radiusCodec.withDefault(Radius.zero), + 'topRight': radiusCodec.withDefault(Radius.zero), + 'bottomLeft': radiusCodec.withDefault(Radius.zero), + 'bottomRight': radiusCodec.withDefault(Radius.zero), + }), + ]), + decode: _decodeBorderRadius, + encode: _encodeBorderRadius, +); + +BorderRadius _decodeBorderRadius(Object value) { + if (value is Radius) return BorderRadius.all(value); + + final map = value as JsonMap; + + return BorderRadius.only( + topLeft: readValue(map, 'topLeft'), + topRight: readValue(map, 'topRight'), + bottomLeft: readValue(map, 'bottomLeft'), + bottomRight: readValue(map, 'bottomRight'), + ); +} + +Object _encodeBorderRadius(BorderRadius value) { + if (value.topLeft == value.topRight && + value.topRight == value.bottomLeft && + value.bottomLeft == value.bottomRight) { + return value.topLeft; + } + + return { + 'topLeft': value.topLeft, + 'topRight': value.topRight, + 'bottomLeft': value.bottomLeft, + 'bottomRight': value.bottomRight, + }; +} + +/// Codec for [BorderRadiusDirectional], an object +/// `{topStart, topEnd, bottomStart, bottomEnd}` (each corner optional, defaulting +/// to `Radius.zero`). Always encodes to the object form — never a shorthand — so +/// the directional type round-trips even when uniform or zero (a single radius is +/// reserved for [BorderRadius]). +final borderRadiusDirectionalCodec = + Ack.object({ + 'topStart': radiusCodec.withDefault(Radius.zero), + 'topEnd': radiusCodec.withDefault(Radius.zero), + 'bottomStart': radiusCodec.withDefault(Radius.zero), + 'bottomEnd': radiusCodec.withDefault(Radius.zero), + }).codec( + decode: (data) => BorderRadiusDirectional.only( + topStart: readValue(data, 'topStart'), + topEnd: readValue(data, 'topEnd'), + bottomStart: readValue(data, 'bottomStart'), + bottomEnd: readValue(data, 'bottomEnd'), + ), + encode: (value) => { + 'topStart': value.topStart, + 'topEnd': value.topEnd, + 'bottomStart': value.bottomStart, + 'bottomEnd': value.bottomEnd, + }, + ); + +/// Codec for [BorderRadiusGeometry], unioning [borderRadiusCodec] and +/// [borderRadiusDirectionalCodec]. +/// +/// A radius shorthand, an `{topLeft, …}` object, and `{}` decode to +/// [BorderRadius]; objects carrying `topStart`/`topEnd`/`bottomStart`/`bottomEnd` +/// decode to [BorderRadiusDirectional] ([borderRadiusCodec] is tried first). +/// Encoding dispatches by runtime type. Mixed radii (from adding a [BorderRadius] +/// to a [BorderRadiusDirectional]) are not supported. +final borderRadiusGeometryCodec = + Ack.anyOf([ + borderRadiusCodec, + borderRadiusDirectionalCodec, + ]).codec( + decode: (value) => value as BorderRadiusGeometry, + encode: (value) => value, + ); diff --git a/packages/flutter_codec/lib/src/primitives/color.dart b/packages/flutter_codec/lib/src/primitives/color.dart new file mode 100644 index 00000000..b53ca5be --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/color.dart @@ -0,0 +1,127 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show Color; + +// Matches a single 0–255 color channel. The decoder also range-checks, but the +// JSON Schema pattern must not admit channels (256+) the codec rejects. +const _rgbChannel = r'(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)'; + +final _rgbPattern = + r'^rgb\(\s*' + + _rgbChannel + + r'\s*,\s*' + + _rgbChannel + + r'\s*,\s*' + + _rgbChannel + + r'\s*\)$'; + +final _rgbaPattern = + r'^rgba\(\s*' + + _rgbChannel + + r'\s*,\s*' + + _rgbChannel + + r'\s*,\s*' + + _rgbChannel + + r'\s*,\s*(?:0|1|0?\.\d+|1\.0+)\s*\)$'; + +/// Codec for [Color]. Accepts `#RRGGBB`, `#AARRGGBB`, `rgb(r,g,b)`, and +/// `rgba(r,g,b,a)` strings; encodes to canonical hex (`#RRGGBB`, or `#AARRGGBB` +/// when translucent). +/// +/// The wire format is 8-bit sRGB (via [Color.toARGB32]). Integer-constructed +/// sRGB colors ([Color.new], `Colors.*`, [Color.fromARGB]) round-trip exactly. +/// Two losses are intentional and not preserved: sub-8-bit float-channel +/// precision (e.g. from [Color.withValues] or [Color.lerp]) is quantized, and +/// a non-sRGB [Color.colorSpace] (display P3, extended sRGB) is flattened to +/// sRGB. See `test/primitives/color_test.dart` for the pinned behavior. +final colorCodec = Ack.codec( + input: Ack.anyOf([ + Ack.string().matches(r'^#[0-9A-Fa-f]{6}$'), + Ack.string().matches(r'^#[0-9A-Fa-f]{8}$'), + Ack.string().matches(_rgbPattern), + Ack.string().matches(_rgbaPattern), + ]), + decode: (value) => _parseColor(value as String), + encode: _encodeColor, +); + +Color _parseColor(String value) { + if (value.startsWith('#')) { + return _parseHexColor(value); + } + if (value.startsWith('rgb(')) { + return _parseRgbColor(value); + } + if (value.startsWith('rgba(')) { + return _parseRgbaColor(value); + } + throw FormatException('Unsupported color format: $value'); +} + +Color _parseHexColor(String value) { + final hex = value.substring(1); + final argb = hex.length == 6 ? 'FF$hex' : hex; + + return Color(int.parse(argb, radix: 16)); +} + +Color _parseRgbColor(String value) { + final channels = _parseChannelList(value, prefix: 'rgb(', count: 3); + + return Color.fromARGB(0xFF, channels[0], channels[1], channels[2]); +} + +Color _parseRgbaColor(String value) { + final channels = _parseChannelList(value, prefix: 'rgba(', count: 4); + final alpha = channels[3]; + + return Color.fromARGB(alpha, channels[0], channels[1], channels[2]); +} + +List _parseChannelList( + String value, { + required String prefix, + required int count, +}) { + final rawParts = value.substring(prefix.length, value.length - 1).split(','); + if (rawParts.length != count) { + throw FormatException('Expected $count color channels.'); + } + + final rgb = rawParts + .take(3) + .map((part) { + final channel = int.parse(part.trim()); + if (channel < 0 || channel > 255) { + throw FormatException('Color channel out of range: $channel'); + } + + return channel; + }) + .toList(growable: false); + + if (count == 3) return rgb; + + final alpha = double.parse(rawParts[3].trim()); + if (alpha < 0 || alpha > 1) { + throw FormatException('Alpha channel out of range: $alpha'); + } + + return [...rgb, (alpha * 255).round()]; +} + +Object _encodeColor(Color value) { + final argb = value.toARGB32(); + final alpha = (argb >> 24) & 0xFF; + final red = (argb >> 16) & 0xFF; + final green = (argb >> 8) & 0xFF; + final blue = argb & 0xFF; + + if (alpha == 0xFF) { + return '#${_hex2(red)}${_hex2(green)}${_hex2(blue)}'; + } + + return '#${_hex2(alpha)}${_hex2(red)}${_hex2(green)}${_hex2(blue)}'; +} + +String _hex2(int value) => + value.toRadixString(16).padLeft(2, '0').toUpperCase(); diff --git a/packages/flutter_codec/lib/src/primitives/edge_insets.dart b/packages/flutter_codec/lib/src/primitives/edge_insets.dart new file mode 100644 index 00000000..55dff5ca --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/edge_insets.dart @@ -0,0 +1,99 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show EdgeInsets, EdgeInsetsDirectional, EdgeInsetsGeometry; + +import '../json_readers.dart'; + +/// Codec for [EdgeInsets]. A bare number sets all four sides; an object +/// `{"left": ..., "top": ..., "right": ..., "bottom": ...}` (each side optional, +/// defaulting to `0`) sets them individually. Encoding emits a scalar when all +/// sides are equal, otherwise the full object. +/// +/// This primitive intentionally allows negative values to match Flutter's +/// [EdgeInsets]. Widget codecs that assert non-negative insets, such as +/// [Container], enforce that constraint at the widget boundary. Direct consumers +/// that need non-negative insets should add their own refinement. +final edgeInsetsCodec = Ack.codec( + input: Ack.anyOf([ + Ack.number(), + Ack.object({ + 'left': Ack.number().withDefault(0.0), + 'top': Ack.number().withDefault(0.0), + 'right': Ack.number().withDefault(0.0), + 'bottom': Ack.number().withDefault(0.0), + }), + ]), + decode: _decodeEdgeInsets, + encode: _encodeEdgeInsets, +); + +EdgeInsets _decodeEdgeInsets(Object value) { + if (value is num) return EdgeInsets.all(value.toDouble()); + + final map = value as JsonMap; + + return EdgeInsets.fromLTRB( + readDouble(map, 'left'), + readDouble(map, 'top'), + readDouble(map, 'right'), + readDouble(map, 'bottom'), + ); +} + +Object _encodeEdgeInsets(EdgeInsets value) { + if (value.left == value.top && + value.top == value.right && + value.right == value.bottom) { + return value.left; + } + + return { + 'left': value.left, + 'top': value.top, + 'right': value.right, + 'bottom': value.bottom, + }; +} + +/// Codec for [EdgeInsetsDirectional], an object +/// `{"start": ..., "top": ..., "end": ..., "bottom": ...}` (each side optional, +/// defaulting to `0`). Always encodes to the object form — never a scalar — so +/// the directional type round-trips even when uniform or zero (a bare number is +/// reserved for [EdgeInsets]). +final edgeInsetsDirectionalCodec = + Ack.object({ + 'start': Ack.number().withDefault(0.0), + 'top': Ack.number().withDefault(0.0), + 'end': Ack.number().withDefault(0.0), + 'bottom': Ack.number().withDefault(0.0), + }).codec( + decode: (data) => EdgeInsetsDirectional.fromSTEB( + readDouble(data, 'start'), + readDouble(data, 'top'), + readDouble(data, 'end'), + readDouble(data, 'bottom'), + ), + encode: (value) => { + 'start': value.start, + 'top': value.top, + 'end': value.end, + 'bottom': value.bottom, + }, + ); + +/// Codec for [EdgeInsetsGeometry], unioning [edgeInsetsCodec] and +/// [edgeInsetsDirectionalCodec]. +/// +/// A scalar, an `{left, top, right, bottom}` object, a shared `top`/`bottom`-only +/// object, and `{}` decode to [EdgeInsets]; objects carrying `start`/`end` decode +/// to [EdgeInsetsDirectional] ([edgeInsetsCodec] is tried first). Encoding +/// dispatches by runtime type. Mixed insets (from adding an [EdgeInsets] to an +/// [EdgeInsetsDirectional]) are not supported. +final edgeInsetsGeometryCodec = + Ack.anyOf([ + edgeInsetsCodec, + edgeInsetsDirectionalCodec, + ]).codec( + decode: (value) => value as EdgeInsetsGeometry, + encode: (value) => value, + ); diff --git a/packages/flutter_codec/lib/src/primitives/font_feature.dart b/packages/flutter_codec/lib/src/primitives/font_feature.dart new file mode 100644 index 00000000..f5c2842a --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/font_feature.dart @@ -0,0 +1,31 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show FontFeature; + +import '../json_readers.dart'; + +// 4-character printable-ASCII tag pattern shared by OpenType feature names +// and variation axis identifiers. Flutter only asserts `.length == 4` at +// construction; the printable-ASCII range is tightened here because OpenType +// tags are by spec ASCII and the wire format should reject control-character +// payloads that the Dart constructor would silently accept. +const _tagPattern = r'^[\x20-\x7E]{4}$'; + +/// Codec for [FontFeature]. +/// +/// Serializes the public [FontFeature.feature] (a 4-character OpenType +/// feature tag, e.g. `"smcp"` or `"liga"`) and [FontFeature.value] (a +/// non-negative integer; defaults to `1`, the conventional "enable" value). +/// +/// Convenience constructors like [FontFeature.enable] or +/// [FontFeature.alternative] are not preserved on round-trip because they all +/// materialize as the same `(feature, value)` pair on the resulting +/// [FontFeature] instance. +final fontFeatureCodec = + Ack.object({ + 'feature': Ack.string().matches(_tagPattern), + 'value': Ack.integer().min(0).withDefault(1), + }).codec( + decode: (data) => + FontFeature(readValue(data, 'feature'), readValue(data, 'value')), + encode: (value) => {'feature': value.feature, 'value': value.value}, + ); diff --git a/packages/flutter_codec/lib/src/primitives/font_variation.dart b/packages/flutter_codec/lib/src/primitives/font_variation.dart new file mode 100644 index 00000000..fc613766 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/font_variation.dart @@ -0,0 +1,29 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show FontVariation; + +import '../json_readers.dart'; + +// 4-character printable-ASCII axis tag pattern. Flutter only asserts +// `.length == 4` at construction; see `font_feature.dart` for the rationale +// behind the tighter printable-ASCII check applied at the wire layer. +const _axisPattern = r'^[\x20-\x7E]{4}$'; + +/// Codec for [FontVariation]. +/// +/// Serializes the public [FontVariation.axis] (a 4-character OpenType +/// variation axis tag, e.g. `"wght"` or `"wdth"`) and [FontVariation.value] +/// (a [double] constrained to the `[-32768, 32768)` 16.16 fixed-point range +/// that the [FontVariation] constructor requires). +/// +/// Convenience constructors like [FontVariation.weight] are not preserved on +/// round-trip because they all materialize as the same `(axis, value)` pair +/// on the resulting [FontVariation] instance. +final fontVariationCodec = + Ack.object({ + 'axis': Ack.string().matches(_axisPattern), + 'value': Ack.number().min(-32768).lessThan(32768), + }).codec( + decode: (data) => + FontVariation(readValue(data, 'axis'), readDouble(data, 'value')), + encode: (value) => {'axis': value.axis, 'value': value.value}, + ); diff --git a/packages/flutter_codec/lib/src/primitives/font_weight.dart b/packages/flutter_codec/lib/src/primitives/font_weight.dart new file mode 100644 index 00000000..bcc03e44 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/font_weight.dart @@ -0,0 +1,56 @@ +import 'dart:ui' show FontWeight; + +import 'package:ack/ack.dart'; + +// Named aliases accepted for [FontWeight]. +// +// w100..w900 occupy indices 0..8, so the canonical weight `100 * (index + 1)` +// maps to and from the enum arithmetically. The trailing `normal` and `bold` +// are accept-only aliases for w400/w700 and are never emitted on encode. +enum _FontWeight { + w100, + w200, + w300, + w400, + w500, + w600, + w700, + w800, + w900, + normal, + bold, +} + +/// Codec for [FontWeight]. +/// +/// Accepts the named aliases `"w100"` through `"w900"` plus `"normal"` and +/// `"bold"`, and any integer weight in `[1, 1000]` — Flutter's public +/// `const FontWeight(int)` supports arbitrary variable-font weights such as +/// `FontWeight(550)`. Encoding canonicalizes the nine standard weights to +/// their `"wNNN"` alias and emits any other weight as its integer +/// [FontWeight.value]. +final fontWeightCodec = Ack.codec( + input: Ack.anyOf([ + Ack.enumCodec(_FontWeight.values), + Ack.integer().min(1).max(1000), + ]), + decode: _decodeFontWeight, + encode: _encodeFontWeight, +); + +FontWeight _decodeFontWeight(Object value) { + if (value is int) return FontWeight(value); + + return switch (value as _FontWeight) { + _FontWeight.normal => FontWeight.normal, + _FontWeight.bold => FontWeight.bold, + final weight => FontWeight(100 * (weight.index + 1)), + }; +} + +Object _encodeFontWeight(FontWeight value) { + final weight = value.value; + final isCanonical = weight >= 100 && weight <= 900 && weight % 100 == 0; + + return isCanonical ? _FontWeight.values[weight ~/ 100 - 1] : weight; +} diff --git a/packages/flutter_codec/lib/src/primitives/locale.dart b/packages/flutter_codec/lib/src/primitives/locale.dart new file mode 100644 index 00000000..cb361c34 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/locale.dart @@ -0,0 +1,30 @@ +import 'dart:ui' show Locale; + +import 'package:ack/ack.dart'; + +// BCP-47 subset: required language (2-3 lowercase), optional script +// (4-character title case), optional region (2 uppercase letters or 3 digits). +// Capture groups extract each subtag for the inline decoder on [localeCodec]; +// they don't affect validation behavior. +const _localePattern = + r'^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\d{3}))?$'; +final _localeRegex = RegExp(_localePattern); + +/// Codec for [Locale] using BCP-47 language tags. +/// +/// Supports language-only tags (`"en"`), language-region tags (`"en-US"`), +/// and language-script-region tags (`"zh-Hans-CN"`). Encoding delegates to +/// [Locale.toLanguageTag]. +final localeCodec = Ack.codec( + input: Ack.string().matches(_localePattern), + decode: (value) { + final match = _localeRegex.firstMatch(value)!; + + return Locale.fromSubtags( + languageCode: match.group(1)!, + scriptCode: match.group(2), + countryCode: match.group(3), + ); + }, + encode: (value) => value.toLanguageTag(), +); diff --git a/packages/flutter_codec/lib/src/primitives/matrix4.dart b/packages/flutter_codec/lib/src/primitives/matrix4.dart new file mode 100644 index 00000000..629cdd7a --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/matrix4.dart @@ -0,0 +1,14 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/widgets.dart' show Matrix4; + +/// Codec for [Matrix4]. +/// +/// The encoded list contains exactly 16 finite numbers in [Matrix4.storage] +/// order, which is column-major. +final matrix4Codec = Ack.list(Ack.number()) + .length(16) + .codec( + decode: (values) => + Matrix4.fromList(values.map((value) => value.toDouble()).toList()), + encode: (value) => value.storage.toList(), + ); diff --git a/packages/flutter_codec/lib/src/primitives/offset.dart b/packages/flutter_codec/lib/src/primitives/offset.dart new file mode 100644 index 00000000..793dc1ab --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/offset.dart @@ -0,0 +1,11 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show Offset; + +import '../json_readers.dart'; + +/// Codec for [Offset], represented as `{"x": ..., "y": ...}`. +final offsetCodec = Ack.object({'x': Ack.number(), 'y': Ack.number()}) + .codec( + decode: (data) => Offset(readDouble(data, 'x'), readDouble(data, 'y')), + encode: (value) => {'x': value.dx, 'y': value.dy}, + ); diff --git a/packages/flutter_codec/lib/src/primitives/radius.dart b/packages/flutter_codec/lib/src/primitives/radius.dart new file mode 100644 index 00000000..ecb3af6f --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/radius.dart @@ -0,0 +1,31 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show Radius; + +import '../json_readers.dart'; + +/// Codec for [Radius]. A single non-negative number is a circular radius; +/// `{"x": ..., "y": ...}` is elliptical. Circular radii encode back to a number. +final radiusCodec = Ack.codec( + input: Ack.anyOf([ + Ack.number().min(0), + Ack.object({'x': Ack.number().min(0), 'y': Ack.number().min(0)}), + ]), + decode: _decodeRadius, + encode: _encodeRadius, +); + +Radius _decodeRadius(Object value) { + if (value is num) { + return Radius.circular(value.toDouble()); + } + + final map = value as JsonMap; + + return Radius.elliptical(readDouble(map, 'x'), readDouble(map, 'y')); +} + +Object _encodeRadius(Radius value) { + if (value.x == value.y) return value.x; + + return {'x': value.x, 'y': value.y}; +} diff --git a/packages/flutter_codec/lib/src/primitives/rect.dart b/packages/flutter_codec/lib/src/primitives/rect.dart new file mode 100644 index 00000000..45e372d5 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/rect.dart @@ -0,0 +1,28 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show Rect; + +import '../json_readers.dart'; + +/// Codec for [Rect], represented as `{"left": ..., "top": ..., "right": ..., +/// "bottom": ...}`. All four sides are required; encoding uses LTRB form +/// to match the canonical Flutter constructor [Rect.fromLTRB]. +final rectCodec = + Ack.object({ + 'left': Ack.number(), + 'top': Ack.number(), + 'right': Ack.number(), + 'bottom': Ack.number(), + }).codec( + decode: (data) => Rect.fromLTRB( + readDouble(data, 'left'), + readDouble(data, 'top'), + readDouble(data, 'right'), + readDouble(data, 'bottom'), + ), + encode: (value) => { + 'left': value.left, + 'top': value.top, + 'right': value.right, + 'bottom': value.bottom, + }, + ); diff --git a/packages/flutter_codec/lib/src/primitives/text_decoration.dart b/packages/flutter_codec/lib/src/primitives/text_decoration.dart new file mode 100644 index 00000000..811c6a3e --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/text_decoration.dart @@ -0,0 +1,54 @@ +import 'dart:ui' show TextDecoration; + +import 'package:ack/ack.dart'; + +// Atomic TextDecoration aliases, encoded as string names. +enum _TextDecoration { none, underline, overline, lineThrough } + +final _atomicCodec = Ack.enumCodec(_TextDecoration.values); + +/// Codec for [TextDecoration]. +/// +/// Accepts atomic aliases such as `"underline"` and combined arrays such as +/// `["underline", "overline"]`. Encoding emits the shortest canonical form: +/// a bare string for atomic values and an array for composed values. +final textDecorationCodec = Ack.codec( + input: Ack.anyOf([_atomicCodec, Ack.list(_atomicCodec)]), + decode: _decodeTextDecoration, + encode: _encodeTextDecoration, +); + +TextDecoration _decodeTextDecoration(Object value) { + if (value is _TextDecoration) return _atomicToTextDecoration(value); + + final decorations = (value as List) + .cast<_TextDecoration>() + .where((atomic) => atomic != _TextDecoration.none) + .map(_atomicToTextDecoration) + .toList(); + if (decorations.isEmpty) return TextDecoration.none; + + return TextDecoration.combine(decorations); +} + +TextDecoration _atomicToTextDecoration(_TextDecoration value) { + return switch (value) { + _TextDecoration.none => TextDecoration.none, + _TextDecoration.underline => TextDecoration.underline, + _TextDecoration.overline => TextDecoration.overline, + _TextDecoration.lineThrough => TextDecoration.lineThrough, + }; +} + +Object _encodeTextDecoration(TextDecoration value) { + if (value == TextDecoration.none) return _TextDecoration.none; + if (value == TextDecoration.underline) return _TextDecoration.underline; + if (value == TextDecoration.overline) return _TextDecoration.overline; + if (value == TextDecoration.lineThrough) return _TextDecoration.lineThrough; + + return [ + if (value.contains(TextDecoration.underline)) _TextDecoration.underline, + if (value.contains(TextDecoration.overline)) _TextDecoration.overline, + if (value.contains(TextDecoration.lineThrough)) _TextDecoration.lineThrough, + ]; +} diff --git a/packages/flutter_codec/lib/src/primitives/text_height_behavior.dart b/packages/flutter_codec/lib/src/primitives/text_height_behavior.dart new file mode 100644 index 00000000..818381c3 --- /dev/null +++ b/packages/flutter_codec/lib/src/primitives/text_height_behavior.dart @@ -0,0 +1,33 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show TextHeightBehavior, TextLeadingDistribution; + +import '../enums.dart' show textLeadingDistributionCodec; +import '../json_readers.dart'; + +/// Codec for [TextHeightBehavior]. +/// +/// Composes `applyHeightToFirstAscent` and `applyHeightToLastDescent` +/// (booleans, both default `true`) with [textLeadingDistributionCodec] for +/// `leadingDistribution` (default [TextLeadingDistribution.proportional]). +/// All three fields match Flutter's constructor defaults, so encoding a +/// default [TextHeightBehavior] round-trips through both encode and parse. +final textHeightBehaviorCodec = + Ack.object({ + 'applyHeightToFirstAscent': Ack.boolean().withDefault(true), + 'applyHeightToLastDescent': Ack.boolean().withDefault(true), + 'leadingDistribution': textLeadingDistributionCodec.withDefault( + TextLeadingDistribution.proportional, + ), + }).codec( + decode: (data) => TextHeightBehavior( + applyHeightToFirstAscent: readValue(data, 'applyHeightToFirstAscent'), + applyHeightToLastDescent: readValue(data, 'applyHeightToLastDescent'), + leadingDistribution: readValue(data, 'leadingDistribution'), + ), + encode: (value) => { + 'applyHeightToFirstAscent': value.applyHeightToFirstAscent, + 'applyHeightToLastDescent': value.applyHeightToLastDescent, + 'leadingDistribution': value.leadingDistribution, + }, + ); diff --git a/packages/flutter_codec/lib/src/shadows.dart b/packages/flutter_codec/lib/src/shadows.dart new file mode 100644 index 00000000..88b5639d --- /dev/null +++ b/packages/flutter_codec/lib/src/shadows.dart @@ -0,0 +1,59 @@ +import 'dart:ui' as ui show Shadow; + +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show BlurStyle, BoxShadow, Color, Offset; + +import 'enums.dart' show blurStyleCodec; +import 'json_readers.dart'; +import 'primitives/color.dart' show colorCodec; +import 'primitives/offset.dart' show offsetCodec; + +/// Codec for [ui.Shadow], an object `{color, offset, blurRadius}` with each +/// field optional and falling back to the [ui.Shadow] constructor defaults. +/// `{}` decodes to `const ui.Shadow()`. +final shadowCodec = + Ack.object({ + 'color': colorCodec.withDefault(const Color(0xFF000000)), + 'offset': offsetCodec.withDefault(Offset.zero), + 'blurRadius': Ack.number().min(0).withDefault(0.0), + }).codec( + decode: (data) => ui.Shadow( + color: readValue(data, 'color'), + offset: readValue(data, 'offset'), + blurRadius: readDouble(data, 'blurRadius'), + ), + encode: (value) => { + 'color': value.color, + 'offset': value.offset, + 'blurRadius': value.blurRadius, + }, + ); + +/// Codec for [BoxShadow], extending the [shadowCodec] field set with +/// `spreadRadius` and `blurStyle`. `{}` decodes to `const BoxShadow()`. +/// +/// `blurRadius` is non-negative (Flutter requirement). `spreadRadius` is +/// unconstrained — negative values shrink the shadow. +final boxShadowCodec = + Ack.object({ + 'color': colorCodec.withDefault(const Color(0xFF000000)), + 'offset': offsetCodec.withDefault(Offset.zero), + 'blurRadius': Ack.number().min(0).withDefault(0.0), + 'spreadRadius': Ack.number().withDefault(0.0), + 'blurStyle': blurStyleCodec.withDefault(BlurStyle.normal), + }).codec( + decode: (data) => BoxShadow( + color: readValue(data, 'color'), + offset: readValue(data, 'offset'), + blurRadius: readDouble(data, 'blurRadius'), + spreadRadius: readDouble(data, 'spreadRadius'), + blurStyle: readValue(data, 'blurStyle'), + ), + encode: (value) => { + 'color': value.color, + 'offset': value.offset, + 'blurRadius': value.blurRadius, + 'spreadRadius': value.spreadRadius, + 'blurStyle': value.blurStyle, + }, + ); diff --git a/packages/flutter_codec/lib/src/shape_borders.dart b/packages/flutter_codec/lib/src/shape_borders.dart new file mode 100644 index 00000000..81bde6bc --- /dev/null +++ b/packages/flutter_codec/lib/src/shape_borders.dart @@ -0,0 +1,305 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show + BeveledRectangleBorder, + BorderRadius, + BorderSide, + CircleBorder, + ContinuousRectangleBorder, + LinearBorder, + LinearBorderEdge, + OutlinedBorder, + RoundedRectangleBorder, + RoundedSuperellipseBorder, + ShapeBorder, + StadiumBorder, + StarBorder; + +import 'borders.dart' show borderSideCodec; +import 'json_readers.dart'; +import 'primitives/border_radius.dart' show borderRadiusGeometryCodec; + +// Shared `{side, borderRadius}` schema for the four corner-rounded +// rectangular border codecs ([roundedRectangleBorderCodec], +// [beveledRectangleBorderCodec], [continuousRectangleBorderCodec], +// [roundedSuperellipseBorderCodec]). They accept the same JSON payload and +// differ only in the runtime [ShapeBorder] subtype they decode to. +final _rectangleBorderSchema = Ack.object({ + 'side': borderSideCodec.withDefault(BorderSide.none), + 'borderRadius': borderRadiusGeometryCodec.withDefault(BorderRadius.zero), +}); + +/// Codec for [CircleBorder]. +/// +/// Composes [borderSideCodec] for [CircleBorder.side] and a non-negative +/// `eccentricity` in `[0, 1]` (default `0.0`, a perfect circle; `1.0` is a +/// fully flattened ellipse — matching the bounds Flutter's constructor +/// asserts). The `"type"` discriminator is added by [shapeBorderCodec] when +/// this codec is used as one of its branches. +final circleBorderCodec = + Ack.object({ + 'side': borderSideCodec.withDefault(BorderSide.none), + 'eccentricity': Ack.number().min(0).max(1).withDefault(0.0), + }).codec( + decode: (data) => CircleBorder( + side: readValue(data, 'side'), + eccentricity: readDouble(data, 'eccentricity'), + ), + encode: (value) => { + 'side': value.side, + 'eccentricity': value.eccentricity, + }, + ); + +/// Codec for [StadiumBorder]. +/// +/// Composes [borderSideCodec] for [StadiumBorder.side]. The `"type"` +/// discriminator is added by [shapeBorderCodec] when this codec is used as +/// one of its branches. +final stadiumBorderCodec = + Ack.object({ + 'side': borderSideCodec.withDefault(BorderSide.none), + }).codec( + decode: (data) => StadiumBorder(side: readValue(data, 'side')), + encode: (value) => {'side': value.side}, + ); + +/// Codec for [RoundedRectangleBorder]. +/// +/// Composes [borderSideCodec] for [RoundedRectangleBorder.side] and +/// [borderRadiusGeometryCodec] for [RoundedRectangleBorder.borderRadius] +/// (default [BorderRadius.zero], matching the constructor). The `"type"` +/// discriminator is added by [shapeBorderCodec] when this codec is used as +/// one of its branches. +final roundedRectangleBorderCodec = _rectangleBorderSchema + .codec( + decode: (data) => RoundedRectangleBorder( + side: readValue(data, 'side'), + borderRadius: readValue(data, 'borderRadius'), + ), + encode: (value) => { + 'side': value.side, + 'borderRadius': value.borderRadius, + }, + ); + +/// Codec for [BeveledRectangleBorder]. +/// +/// Shares the `{side, borderRadius}` shape with [roundedRectangleBorderCodec] +/// and [continuousRectangleBorderCodec]; the runtime [ShapeBorder] subtype is +/// the only difference. The `"type"` discriminator is added by +/// [shapeBorderCodec] when this codec is used as one of its branches. +final beveledRectangleBorderCodec = _rectangleBorderSchema + .codec( + decode: (data) => BeveledRectangleBorder( + side: readValue(data, 'side'), + borderRadius: readValue(data, 'borderRadius'), + ), + encode: (value) => { + 'side': value.side, + 'borderRadius': value.borderRadius, + }, + ); + +/// Codec for [ContinuousRectangleBorder]. +/// +/// Shares the `{side, borderRadius}` shape with [roundedRectangleBorderCodec] +/// and [beveledRectangleBorderCodec]; the runtime [ShapeBorder] subtype is +/// the only difference. The `"type"` discriminator is added by +/// [shapeBorderCodec] when this codec is used as one of its branches. +final continuousRectangleBorderCodec = _rectangleBorderSchema + .codec( + decode: (data) => ContinuousRectangleBorder( + side: readValue(data, 'side'), + borderRadius: readValue(data, 'borderRadius'), + ), + encode: (value) => { + 'side': value.side, + 'borderRadius': value.borderRadius, + }, + ); + +/// Codec for [RoundedSuperellipseBorder]. +/// +/// Shares the `{side, borderRadius}` shape with the other corner-rounded +/// rectangle border codecs ([roundedRectangleBorderCodec], +/// [beveledRectangleBorderCodec], [continuousRectangleBorderCodec]); only the +/// runtime [ShapeBorder] subtype differs. Requires Flutter 3.32 or later. +/// The `"type"` discriminator is added by [shapeBorderCodec] when this codec +/// is used as one of its branches. +final roundedSuperellipseBorderCodec = _rectangleBorderSchema + .codec( + decode: (data) => RoundedSuperellipseBorder( + side: readValue(data, 'side'), + borderRadius: readValue(data, 'borderRadius'), + ), + encode: (value) => { + 'side': value.side, + 'borderRadius': value.borderRadius, + }, + ); + +bool _starRoundingSumValid(JsonMap data) { + final pointRounding = data['pointRounding'] as num; + final valleyRounding = data['valleyRounding'] as num; + + return pointRounding + valleyRounding <= 1; +} + +/// Codec for [StarBorder]. +/// +/// Composes [borderSideCodec] for [StarBorder.side] (default +/// [BorderSide.none]) with the six shape-control doubles: `points` +/// (default `5`, `>= 2`), `innerRadiusRatio` (default `0.4`, `[0, 1]`), +/// `pointRounding` and `valleyRounding` (each default `0`, each in +/// `[0, 1]`), `rotation` in degrees (default `0`), and `squash` +/// (default `0`, `[0, 1]`). +/// +/// `points` is intentionally typed as a number rather than an integer to +/// match Flutter's constructor: non-integer values produce an additional +/// shorter point or corner to finish the shape, enabling smooth +/// animation between point counts. +/// +/// The codec also enforces the constructor's +/// `pointRounding + valleyRounding <= 1` invariant so validation holds in +/// release builds too. The `"type"` discriminator is added by [shapeBorderCodec] +/// when this codec is used as one of its branches. +/// +/// `StarBorder.polygon` round-trips through the regular `StarBorder` +/// constructor: encoding reads the computed `innerRadiusRatio` and +/// `valleyRounding` (always `0` for polygons), so the painted output is +/// identical even though the runtime "this came from `.polygon`" +/// information is lost. +/// +/// `rotation` is stored internally as radians and compared exactly by +/// `StarBorder` equality, while this codec round-trips it as degrees. The +/// degrees↔radians conversion is not bit-stable, so some rotations are +/// painted-equivalent but not `==`-equal after a round-trip. +final starBorderCodec = + Ack.object({ + 'side': borderSideCodec.withDefault(BorderSide.none), + 'points': Ack.number().min(2).withDefault(5), + 'innerRadiusRatio': Ack.number().min(0).max(1).withDefault(0.4), + 'pointRounding': Ack.number().min(0).max(1).withDefault(0.0), + 'valleyRounding': Ack.number().min(0).max(1).withDefault(0.0), + 'rotation': Ack.number().withDefault(0.0), + 'squash': Ack.number().min(0).max(1).withDefault(0.0), + }) + .refine( + _starRoundingSumValid, + message: + 'StarBorder pointRounding + valleyRounding must not exceed 1.', + ) + .codec( + decode: (data) => StarBorder( + side: readValue(data, 'side'), + points: readDouble(data, 'points'), + innerRadiusRatio: readDouble(data, 'innerRadiusRatio'), + pointRounding: readDouble(data, 'pointRounding'), + valleyRounding: readDouble(data, 'valleyRounding'), + rotation: readDouble(data, 'rotation'), + squash: readDouble(data, 'squash'), + ), + encode: (value) => { + 'side': value.side, + 'points': value.points, + 'innerRadiusRatio': value.innerRadiusRatio, + 'pointRounding': value.pointRounding, + 'valleyRounding': value.valleyRounding, + 'rotation': value.rotation, + 'squash': value.squash, + }, + ); + +/// Codec for [LinearBorderEdge]. +/// +/// Composes `size` (default `1.0`, `[0, 1]` matching the constructor +/// assert) and `alignment` (default `0.0`, `[-1, 1]` per dartdoc — the +/// constructor does not assert this bound but the codec enforces it). +/// Used as a sub-codec by [linearBorderCodec] for its four edge slots. +final linearBorderEdgeCodec = + Ack.object({ + 'size': Ack.number().min(0).max(1).withDefault(1.0), + 'alignment': Ack.number().min(-1).max(1).withDefault(0.0), + }).codec( + decode: (data) => LinearBorderEdge( + size: readDouble(data, 'size'), + alignment: readDouble(data, 'alignment'), + ), + encode: (value) => {'size': value.size, 'alignment': value.alignment}, + ); + +/// Codec for [LinearBorder]. +/// +/// Composes [borderSideCodec] for [LinearBorder.side] (default +/// [BorderSide.none]) and four optional [LinearBorderEdge] slots — +/// `start`, `end`, `top`, `bottom` — via [linearBorderEdgeCodec]. The +/// convenience factories (`LinearBorder.start`, `.end`, `.top`, +/// `.bottom`, and `LinearBorder.none`) round-trip through the regular +/// constructor since their fields are publicly observable. +/// +/// The `"type"` discriminator is added by [shapeBorderCodec] when this +/// codec is used as one of its branches. +final linearBorderCodec = + Ack.object({ + 'side': borderSideCodec.withDefault(BorderSide.none), + 'start': linearBorderEdgeCodec.nullable().optional(), + 'end': linearBorderEdgeCodec.nullable().optional(), + 'top': linearBorderEdgeCodec.nullable().optional(), + 'bottom': linearBorderEdgeCodec.nullable().optional(), + }).codec( + decode: (data) => LinearBorder( + side: readValue(data, 'side'), + start: readNullableValue(data, 'start'), + end: readNullableValue(data, 'end'), + top: readNullableValue(data, 'top'), + bottom: readNullableValue(data, 'bottom'), + ), + encode: (value) => { + 'side': value.side, + 'start': value.start, + 'end': value.end, + 'top': value.top, + 'bottom': value.bottom, + }, + ); + +/// Codec for JSON-safe [ShapeBorder] values, discriminated by `"type"`. +/// +/// Covers the eight concrete [OutlinedBorder] subtypes Flutter exposes from +/// `package:flutter/painting.dart`: +/// +/// * `"circle"` → [CircleBorder] +/// * `"stadium"` → [StadiumBorder] +/// * `"roundedRectangle"` → [RoundedRectangleBorder] +/// * `"beveledRectangle"` → [BeveledRectangleBorder] +/// * `"continuousRectangle"` → [ContinuousRectangleBorder] +/// * `"roundedSuperellipse"` → [RoundedSuperellipseBorder] (Flutter 3.32+) +/// * `"star"` → [StarBorder] +/// * `"linear"` → [LinearBorder] +/// +/// `InputBorder` subtypes (Material — `OutlineInputBorder`, +/// `UnderlineInputBorder`) are intentionally not covered here — they live +/// in `package:flutter/material.dart` rather than the painting layer and +/// belong to a separate plan. +/// +/// `OvalBorder` extends [CircleBorder], so it round-trips as a +/// [CircleBorder] (the runtime subtype is lost). Its painted output is +/// equivalent to `CircleBorder(eccentricity: 1.0)`, but callers that depend +/// on the precise runtime type should handle that conversion themselves. +/// +/// Custom user-defined [ShapeBorder] subtypes are rejected on encode rather +/// than guessing a non-portable JSON shape. +final shapeBorderCodec = Ack.discriminated( + discriminatorKey: 'type', + schemas: { + 'circle': circleBorderCodec, + 'stadium': stadiumBorderCodec, + 'roundedRectangle': roundedRectangleBorderCodec, + 'beveledRectangle': beveledRectangleBorderCodec, + 'continuousRectangle': continuousRectangleBorderCodec, + 'roundedSuperellipse': roundedSuperellipseBorderCodec, + 'star': starBorderCodec, + 'linear': linearBorderCodec, + }, +); diff --git a/packages/flutter_codec/lib/src/strut_style.dart b/packages/flutter_codec/lib/src/strut_style.dart new file mode 100644 index 00000000..37248dc8 --- /dev/null +++ b/packages/flutter_codec/lib/src/strut_style.dart @@ -0,0 +1,100 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show StrutStyle; + +import 'enums.dart' show fontStyleCodec, textLeadingDistributionCodec; +import 'font_family_packing.dart' show unpackFontFamily; +import 'json_readers.dart'; +import 'primitives/font_weight.dart' show fontWeightCodec; + +/// Codec for [StrutStyle]. +/// +/// Supported fields are the JSON-safe constructor parameters: `fontFamily`, +/// `fontFamilyFallback`, `package`, `fontSize` (positive when non-null), +/// `height`, `leadingDistribution` ([textLeadingDistributionCodec]), +/// `leading` (non-negative when non-null), `fontWeight` +/// ([fontWeightCodec]), `fontStyle` ([fontStyleCodec]), and +/// `forceStrutHeight`. +/// +/// Encoding unfolds Flutter's internal `packages//` storage +/// back to a `(fontFamily, fontFamilyFallback, package)` triple when all +/// referenced families share the same prefix (matching [textStyleCodec]). +/// When the prefix is missing or inconsistent, `package` is emitted as +/// `null` and the stored (prefixed) `fontFamily` is preserved verbatim. +/// +/// [StrutStyle] asserts `package == null || (fontFamily != null || +/// fontFamilyFallback != null)`. The constructor interpolates a null +/// `fontFamily` into the literal `'packages//null'`, and Flutter +/// treats an empty fallback list as omitted, so this codec requires a +/// non-null family or a non-empty fallback when `package` is set. The +/// check is enforced here so it holds in release builds too. +/// +/// [StrutStyle.debugLabel] is excluded — it's debug metadata, ignored by +/// [StrutStyle] equality. +final strutStyleCodec = + Ack.object({ + 'fontFamily': Ack.string().nullable().optional(), + 'fontFamilyFallback': Ack.list(Ack.string()).nullable().optional(), + 'package': Ack.string().nullable().optional(), + 'fontSize': Ack.number().positive().nullable().optional(), + 'height': Ack.number().nullable().optional(), + 'leadingDistribution': textLeadingDistributionCodec + .nullable() + .optional(), + 'leading': Ack.number().min(0).nullable().optional(), + 'fontWeight': fontWeightCodec.nullable().optional(), + 'fontStyle': fontStyleCodec.nullable().optional(), + 'forceStrutHeight': Ack.boolean().nullable().optional(), + }) + .refine( + _strutStylePackageHasFamily, + message: + 'StrutStyle package requires fontFamily or ' + 'fontFamilyFallback.', + ) + .codec( + decode: _decodeStrutStyle, + encode: _encodeStrutStyle, + ); + +bool _strutStylePackageHasFamily(JsonMap data) { + if (data['package'] == null) return true; + if (data['fontFamily'] != null) return true; + final fallback = data['fontFamilyFallback']; + + return fallback is List && fallback.isNotEmpty; +} + +StrutStyle _decodeStrutStyle(JsonMap data) { + return StrutStyle( + fontFamily: readNullableValue(data, 'fontFamily'), + fontFamilyFallback: readNullableList(data, 'fontFamilyFallback'), + package: readNullableValue(data, 'package'), + fontSize: readNullableDouble(data, 'fontSize'), + height: readNullableDouble(data, 'height'), + leadingDistribution: readNullableValue(data, 'leadingDistribution'), + leading: readNullableDouble(data, 'leading'), + fontWeight: readNullableValue(data, 'fontWeight'), + fontStyle: readNullableValue(data, 'fontStyle'), + forceStrutHeight: readNullableValue(data, 'forceStrutHeight'), + ); +} + +JsonMap _encodeStrutStyle(StrutStyle value) { + final fontFamilyFields = unpackFontFamily( + value.fontFamily, + value.fontFamilyFallback, + ); + + return { + 'fontFamily': fontFamilyFields.family, + 'fontFamilyFallback': fontFamilyFields.fallback, + 'package': fontFamilyFields.packageName, + 'fontSize': value.fontSize, + 'height': value.height, + 'leadingDistribution': value.leadingDistribution, + 'leading': value.leading, + 'fontWeight': value.fontWeight, + 'fontStyle': value.fontStyle, + 'forceStrutHeight': value.forceStrutHeight, + }; +} diff --git a/packages/flutter_codec/lib/src/text_style.dart b/packages/flutter_codec/lib/src/text_style.dart new file mode 100644 index 00000000..f9f66078 --- /dev/null +++ b/packages/flutter_codec/lib/src/text_style.dart @@ -0,0 +1,142 @@ +import 'dart:ui' as ui show Locale; + +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' + show FontWeight, TextDecoration, TextStyle; + +import 'enums.dart' + show + fontStyleCodec, + textBaselineCodec, + textDecorationStyleCodec, + textLeadingDistributionCodec, + textOverflowCodec; +import 'font_family_packing.dart' show unpackFontFamily; +import 'json_readers.dart'; +import 'primitives/color.dart' show colorCodec; +import 'primitives/font_feature.dart' show fontFeatureCodec; +import 'primitives/font_variation.dart' show fontVariationCodec; +import 'primitives/font_weight.dart' show fontWeightCodec; +import 'primitives/locale.dart' show localeCodec; +import 'primitives/text_decoration.dart' show textDecorationCodec; +import 'shadows.dart' show shadowCodec; + +/// Codec for [TextStyle]. +/// +/// Supported fields are the JSON-safe constructor parameters: colors, +/// typography scalars, enum fields, [FontWeight], [ui.Locale], +/// [TextStyle.shadows], [TextDecoration], [TextStyle.fontFamily], +/// [TextStyle.fontFamilyFallback], [TextStyle.package], +/// [TextStyle.overflow], [TextStyle.fontFeatures], and +/// [TextStyle.fontVariations]. +/// +/// Unsupported fields: +/// * [TextStyle.foreground] and [TextStyle.background] are nullable [Paint] +/// values, which are not JSON-safe. Encoding a [TextStyle] that sets either +/// fails validation rather than dropping the paint silently. +/// * [TextStyle.debugLabel] is debug metadata and is excluded from +/// [TextStyle] equality. +final textStyleCodec = Ack.object({ + 'inherit': Ack.boolean().withDefault(true), + 'color': colorCodec.nullable().optional(), + 'backgroundColor': colorCodec.nullable().optional(), + 'fontSize': Ack.number().positive().nullable().optional(), + 'fontWeight': fontWeightCodec.nullable().optional(), + 'fontStyle': fontStyleCodec.nullable().optional(), + 'letterSpacing': Ack.number().nullable().optional(), + 'wordSpacing': Ack.number().nullable().optional(), + 'textBaseline': textBaselineCodec.nullable().optional(), + 'height': Ack.number().nullable().optional(), + 'leadingDistribution': textLeadingDistributionCodec.nullable().optional(), + 'locale': localeCodec.nullable().optional(), + 'shadows': Ack.list(shadowCodec).nullable().optional(), + 'decoration': textDecorationCodec.nullable().optional(), + 'decorationColor': colorCodec.nullable().optional(), + 'decorationStyle': textDecorationStyleCodec.nullable().optional(), + 'decorationThickness': Ack.number().nullable().optional(), + 'fontFamily': Ack.string().nullable().optional(), + 'fontFamilyFallback': Ack.list(Ack.string()).nullable().optional(), + 'package': Ack.string().nullable().optional(), + 'overflow': textOverflowCodec.nullable().optional(), + 'fontFeatures': Ack.list(fontFeatureCodec).nullable().optional(), + 'fontVariations': Ack.list(fontVariationCodec).nullable().optional(), +}).codec(decode: _decodeTextStyle, encode: _encodeTextStyle); + +TextStyle _decodeTextStyle(JsonMap data) { + return TextStyle( + inherit: readValue(data, 'inherit'), + color: readNullableValue(data, 'color'), + backgroundColor: readNullableValue(data, 'backgroundColor'), + fontSize: readNullableDouble(data, 'fontSize'), + fontWeight: readNullableValue(data, 'fontWeight'), + fontStyle: readNullableValue(data, 'fontStyle'), + letterSpacing: readNullableDouble(data, 'letterSpacing'), + wordSpacing: readNullableDouble(data, 'wordSpacing'), + textBaseline: readNullableValue(data, 'textBaseline'), + height: readNullableDouble(data, 'height'), + leadingDistribution: readNullableValue(data, 'leadingDistribution'), + locale: readNullableValue(data, 'locale'), + shadows: readNullableList(data, 'shadows'), + decoration: readNullableValue(data, 'decoration'), + decorationColor: readNullableValue(data, 'decorationColor'), + decorationStyle: readNullableValue(data, 'decorationStyle'), + decorationThickness: readNullableDouble(data, 'decorationThickness'), + fontFamily: readNullableValue(data, 'fontFamily'), + fontFamilyFallback: readNullableList(data, 'fontFamilyFallback'), + package: readNullableValue(data, 'package'), + overflow: readNullableValue(data, 'overflow'), + fontFeatures: readNullableList(data, 'fontFeatures'), + fontVariations: readNullableList(data, 'fontVariations'), + ); +} + +JsonMap _encodeTextStyle(TextStyle value) { + // [TextStyle.foreground]/[TextStyle.background] are [Paint]s with no portable + // JSON shape. They are mutually exclusive with color/backgroundColor, so a + // value that sets them carries paint state this codec cannot represent. + // Fail loudly instead of silently dropping it to a colorless style. + if (value.foreground != null) { + throw FormatException( + 'TextStyle.foreground is a Paint with no portable JSON shape and cannot ' + 'be encoded. Use TextStyle.color, or apply the Paint outside the codec.', + ); + } + if (value.background != null) { + throw FormatException( + 'TextStyle.background is a Paint with no portable JSON shape and cannot ' + 'be encoded. Use TextStyle.backgroundColor, or apply the Paint outside ' + 'the codec.', + ); + } + + final fontFamilyFields = unpackFontFamily( + value.fontFamily, + value.fontFamilyFallback, + ); + + return { + 'inherit': value.inherit, + 'color': value.color, + 'backgroundColor': value.backgroundColor, + 'fontSize': value.fontSize, + 'fontWeight': value.fontWeight, + 'fontStyle': value.fontStyle, + 'letterSpacing': value.letterSpacing, + 'wordSpacing': value.wordSpacing, + 'textBaseline': value.textBaseline, + 'height': value.height, + 'leadingDistribution': value.leadingDistribution, + 'locale': value.locale, + 'shadows': value.shadows, + 'decoration': value.decoration, + 'decorationColor': value.decorationColor, + 'decorationStyle': value.decorationStyle, + 'decorationThickness': value.decorationThickness, + 'fontFamily': fontFamilyFields.family, + 'fontFamilyFallback': fontFamilyFields.fallback, + 'package': fontFamilyFields.packageName, + 'overflow': value.overflow, + 'fontFeatures': value.fontFeatures, + 'fontVariations': value.fontVariations, + }; +} diff --git a/packages/flutter_codec/lib/src/widgets.dart b/packages/flutter_codec/lib/src/widgets.dart new file mode 100644 index 00000000..b65d82ff --- /dev/null +++ b/packages/flutter_codec/lib/src/widgets.dart @@ -0,0 +1,4 @@ +export 'widgets/container.dart'; +export 'widgets/key.dart'; +export 'widgets/text.dart'; +export 'widgets/widget.dart'; diff --git a/packages/flutter_codec/lib/src/widgets/container.dart b/packages/flutter_codec/lib/src/widgets/container.dart new file mode 100644 index 00000000..3eb20478 --- /dev/null +++ b/packages/flutter_codec/lib/src/widgets/container.dart @@ -0,0 +1,114 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/painting.dart' show EdgeInsetsGeometry; +import 'package:flutter/widgets.dart' show Clip, Container, Widget; + +import '../constraints.dart' show boxConstraintsCodec; +import '../decorations.dart' show decorationCodec; +import '../enums.dart' show clipCodec; +import '../json_readers.dart'; +import '../primitives/alignment.dart' show alignmentGeometryCodec; +import '../primitives/color.dart' show colorCodec; +import '../primitives/edge_insets.dart' show edgeInsetsGeometryCodec; +import '../primitives/matrix4.dart' show matrix4Codec; +import 'key.dart' show keyCodec; +import 'widget.dart' show widgetCodec; + +/// Maximum supported depth for recursive [Container.child] widget decoding and +/// encoding. +const int containerWidgetMaxDepth = 64; + +/// Codec for [Container]. +/// +/// `width` and `height` are accepted on decode because they are constructor +/// parameters, but Flutter stores them by tightening [Container.constraints]. +/// Encoding therefore canonicalizes both shorthands to `constraints`. +final CodecSchema containerWidgetCodec = + Ack.object({ + 'key': keyCodec.nullable().optional(), + 'alignment': alignmentGeometryCodec.nullable().optional(), + 'padding': edgeInsetsGeometryCodec.nullable().optional(), + 'color': colorCodec.nullable().optional(), + 'isAntiAlias': Ack.boolean().withDefault(true), + 'decoration': decorationCodec.nullable().optional(), + 'foregroundDecoration': decorationCodec.nullable().optional(), + 'width': Ack.number().min(0).nullable().optional(), + 'height': Ack.number().min(0).nullable().optional(), + 'constraints': boxConstraintsCodec.nullable().optional(), + 'margin': edgeInsetsGeometryCodec.nullable().optional(), + 'transform': matrix4Codec.nullable().optional(), + 'transformAlignment': alignmentGeometryCodec.nullable().optional(), + 'clipBehavior': clipCodec.withDefault(Clip.none), + 'child': Ack.lazy( + 'widgetCodec', + () => widgetCodec, + maxDepth: containerWidgetMaxDepth, + ).nullable().optional(), + }) + // Enforce the constructor's cross-field invariants here so validation holds + // in release builds too (Flutter's asserts are stripped outside debug). + .refine( + (data) => data['color'] == null || data['decoration'] == null, + message: 'Container cannot set both color and decoration.', + ) + .refine( + (data) => + data['decoration'] != null || data['clipBehavior'] == Clip.none, + message: 'Container clipBehavior requires a decoration.', + ) + // Reject negative insets: Flutter's Padding/margin handling asserts + // non-negative edges in debug, and the assert is stripped in release. + .refine( + (data) => _hasNonNegativeInset(data, 'padding'), + message: 'Container padding must not be negative.', + ) + .refine( + (data) => _hasNonNegativeInset(data, 'margin'), + message: 'Container margin must not be negative.', + ) + .codec(decode: _decodeContainer, encode: _encodeContainer); + +bool _hasNonNegativeInset(JsonMap data, String key) { + final inset = data[key]; + + return inset is! EdgeInsetsGeometry || inset.isNonNegative; +} + +Container _decodeContainer(JsonMap data) { + return Container( + key: readNullableValue(data, 'key'), + alignment: readNullableValue(data, 'alignment'), + padding: readNullableValue(data, 'padding'), + color: readNullableValue(data, 'color'), + isAntiAlias: readValue(data, 'isAntiAlias'), + decoration: readNullableValue(data, 'decoration'), + foregroundDecoration: readNullableValue(data, 'foregroundDecoration'), + width: readNullableDouble(data, 'width'), + height: readNullableDouble(data, 'height'), + constraints: readNullableValue(data, 'constraints'), + margin: readNullableValue(data, 'margin'), + transform: readNullableValue(data, 'transform'), + transformAlignment: readNullableValue(data, 'transformAlignment'), + clipBehavior: readValue(data, 'clipBehavior'), + child: readNullableValue(data, 'child'), + ); +} + +JsonMap _encodeContainer(Container value) { + return { + 'key': value.key, + 'alignment': value.alignment, + 'padding': value.padding, + 'color': value.color, + 'isAntiAlias': value.isAntiAlias, + 'decoration': value.decoration, + 'foregroundDecoration': value.foregroundDecoration, + 'width': null, + 'height': null, + 'constraints': value.constraints, + 'margin': value.margin, + 'transform': value.transform, + 'transformAlignment': value.transformAlignment, + 'clipBehavior': value.clipBehavior, + 'child': value.child, + }; +} diff --git a/packages/flutter_codec/lib/src/widgets/key.dart b/packages/flutter_codec/lib/src/widgets/key.dart new file mode 100644 index 00000000..7256487e --- /dev/null +++ b/packages/flutter_codec/lib/src/widgets/key.dart @@ -0,0 +1,103 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/widgets.dart' show Key, ValueKey; + +import '../json_readers.dart'; + +const _valueKeyType = 'value'; + +enum _ValueKeyValueType { string, int, double, bool } + +/// Codec for portable [Key] values. +/// +/// Only the exact scalar [ValueKey] types are supported. Identity-based keys +/// (`ObjectKey`, `UniqueKey`, and `GlobalKey` variants) cannot be serialized +/// because their equality depends on object identity or Flutter runtime state. +/// [ValueKey] subclasses such as `PageStorageKey` are also rejected on encode: +/// re-encoding them as a plain [ValueKey] would silently drop the subclass. +final keyCodec = Ack.discriminated( + discriminatorKey: 'type', + schemas: {_valueKeyType: _valueKeyCodec}, +); + +final _valueKeyCodec = + Ack.object({ + 'valueType': Ack.enumCodec(_ValueKeyValueType.values), + 'value': Ack.anyOf([ + Ack.string(), + Ack.integer(), + Ack.double(), + Ack.boolean(), + ]), + }) + .refine( + _valueMatchesValueType, + message: 'ValueKey value must match its declared valueType.', + ) + .codec(decode: _decodeKey, encode: _encodeKey); + +bool _valueMatchesValueType(JsonMap data) { + final valueType = readValue<_ValueKeyValueType>(data, 'valueType'); + final value = data['value']; + + return switch (valueType) { + _ValueKeyValueType.string => value is String, + _ValueKeyValueType.int => value is int, + _ValueKeyValueType.double => value is num, + _ValueKeyValueType.bool => value is bool, + }; +} + +Key _decodeKey(JsonMap data) { + final valueType = readValue<_ValueKeyValueType>(data, 'valueType'); + final value = data['value']; + + return switch (valueType) { + _ValueKeyValueType.string => ValueKey(value as String), + _ValueKeyValueType.int => ValueKey(value as int), + _ValueKeyValueType.double => ValueKey((value as num).toDouble()), + _ValueKeyValueType.bool => ValueKey(value as bool), + }; +} + +JsonMap _encodeKey(Key value) { + // Match the exact runtime type, not `is`: `ValueKey` subclasses such as + // `PageStorageKey` satisfy `is ValueKey` and would otherwise + // be silently re-encoded as a plain `ValueKey`, losing the subclass on + // decode. + final type = value.runtimeType; + if (type == ValueKey) { + return _encodeValueKey( + _ValueKeyValueType.string, + (value as ValueKey).value, + ); + } + if (type == ValueKey) { + return _encodeValueKey( + _ValueKeyValueType.int, + (value as ValueKey).value, + ); + } + if (type == ValueKey) { + return _encodeValueKey( + _ValueKeyValueType.double, + (value as ValueKey).value, + ); + } + if (type == ValueKey) { + return _encodeValueKey( + _ValueKeyValueType.bool, + (value as ValueKey).value, + ); + } + + throw FormatException( + 'keyCodec can only encode exactly ValueKey; ' + '${value.runtimeType} cannot be serialized because it is identity-based, ' + 'a ValueKey subclass, or has no portable JSON shape.', + ); +} + +JsonMap _encodeValueKey(_ValueKeyValueType valueType, Object value) => { + 'valueType': valueType, + 'value': value, +}; diff --git a/packages/flutter_codec/lib/src/widgets/text.dart b/packages/flutter_codec/lib/src/widgets/text.dart new file mode 100644 index 00000000..1b6cedc6 --- /dev/null +++ b/packages/flutter_codec/lib/src/widgets/text.dart @@ -0,0 +1,98 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/widgets.dart' show Text; + +import '../enums.dart' + show + textAlignCodec, + textDirectionCodec, + textOverflowCodec, + textWidthBasisCodec; +import '../json_readers.dart'; +import '../primitives/color.dart' show colorCodec; +import '../primitives/locale.dart' show localeCodec; +import '../primitives/text_height_behavior.dart' show textHeightBehaviorCodec; +import '../strut_style.dart' show strutStyleCodec; +import '../text_style.dart' show textStyleCodec; +import 'key.dart' show keyCodec; + +/// Codec for plain [Text]. +/// +/// [Text.rich] is intentionally excluded until inline span trees have their own +/// codec. `textScaler` has no portable JSON shape (Flutter exposes no stable +/// public state for its concrete implementations); encoding a [Text] that sets +/// it fails validation rather than dropping it silently. The +/// deprecated `textScaleFactor` constructor parameter is not encoded. +final CodecSchema textWidgetCodec = Ack.object({ + 'key': keyCodec.nullable().optional(), + 'data': Ack.string(), + 'style': textStyleCodec.nullable().optional(), + 'strutStyle': strutStyleCodec.nullable().optional(), + 'textAlign': textAlignCodec.nullable().optional(), + 'textDirection': textDirectionCodec.nullable().optional(), + 'locale': localeCodec.nullable().optional(), + 'softWrap': Ack.boolean().nullable().optional(), + 'overflow': textOverflowCodec.nullable().optional(), + 'maxLines': Ack.integer().min(1).nullable().optional(), + 'semanticsLabel': Ack.string().nullable().optional(), + 'semanticsIdentifier': Ack.string().nullable().optional(), + 'textWidthBasis': textWidthBasisCodec.nullable().optional(), + 'textHeightBehavior': textHeightBehaviorCodec.nullable().optional(), + 'selectionColor': colorCodec.nullable().optional(), +}).codec(decode: _decodeText, encode: _encodeText); + +Text _decodeText(JsonMap data) { + return Text( + readValue(data, 'data'), + key: readNullableValue(data, 'key'), + style: readNullableValue(data, 'style'), + strutStyle: readNullableValue(data, 'strutStyle'), + textAlign: readNullableValue(data, 'textAlign'), + textDirection: readNullableValue(data, 'textDirection'), + locale: readNullableValue(data, 'locale'), + softWrap: readNullableValue(data, 'softWrap'), + overflow: readNullableValue(data, 'overflow'), + maxLines: readNullableValue(data, 'maxLines'), + semanticsLabel: readNullableValue(data, 'semanticsLabel'), + semanticsIdentifier: readNullableValue(data, 'semanticsIdentifier'), + textWidthBasis: readNullableValue(data, 'textWidthBasis'), + textHeightBehavior: readNullableValue(data, 'textHeightBehavior'), + selectionColor: readNullableValue(data, 'selectionColor'), + ); +} + +JsonMap _encodeText(Text value) { + if (value.textSpan != null) { + throw FormatException( + 'Text.rich inline span trees are not supported by textWidgetCodec. ' + 'Use Text with plain data instead.', + ); + } + + // Flutter exposes no stable public state for a [TextScaler] implementation, + // so it has no portable JSON shape. Fail loudly when one is set instead of + // dropping it and decoding back an unscaled [Text]. + if (value.textScaler != null) { + throw FormatException( + 'Text.textScaler has no portable JSON shape and cannot be encoded. ' + 'Resolve text scaling outside the codec, or omit textScaler.', + ); + } + + return { + 'key': value.key, + 'data': value.data, + 'style': value.style, + 'strutStyle': value.strutStyle, + 'textAlign': value.textAlign, + 'textDirection': value.textDirection, + 'locale': value.locale, + 'softWrap': value.softWrap, + 'overflow': value.overflow, + 'maxLines': value.maxLines, + 'semanticsLabel': value.semanticsLabel, + 'semanticsIdentifier': value.semanticsIdentifier, + 'textWidthBasis': value.textWidthBasis, + 'textHeightBehavior': value.textHeightBehavior, + 'selectionColor': value.selectionColor, + }; +} diff --git a/packages/flutter_codec/lib/src/widgets/widget.dart b/packages/flutter_codec/lib/src/widgets/widget.dart new file mode 100644 index 00000000..5aeb2eb4 --- /dev/null +++ b/packages/flutter_codec/lib/src/widgets/widget.dart @@ -0,0 +1,14 @@ +import 'package:ack/ack.dart'; +import 'package:flutter/widgets.dart' show Widget; + +import 'container.dart' show containerWidgetCodec; +import 'text.dart' show textWidgetCodec; + +/// Codec for the supported [Widget] union, discriminated by `"type"`. +/// +/// Current branches are [Container] (`"container"`) and [Text] (`"text"`). +/// Additional widget branches register here as they gain first-class codecs. +final DiscriminatedObjectSchema widgetCodec = Ack.discriminated( + discriminatorKey: 'type', + schemas: {'container': containerWidgetCodec, 'text': textWidgetCodec}, +); diff --git a/packages/flutter_codec/pubspec.yaml b/packages/flutter_codec/pubspec.yaml new file mode 100644 index 00000000..088da18a --- /dev/null +++ b/packages/flutter_codec/pubspec.yaml @@ -0,0 +1,24 @@ +name: flutter_codec +description: JSON codecs for Flutter painting and rendering value types (Color, Gradient, TextStyle, ShapeBorder, EdgeInsets, and more), built on ACK schemas. +version: 0.1.1 +repository: https://github.com/btwld/ack +homepage: https://github.com/btwld/ack/tree/main/packages/flutter_codec +issue_tracker: https://github.com/btwld/ack/issues +resolution: workspace + +environment: + sdk: '>=3.8.0 <4.0.0' + # Floor is 3.41.0: FontWeight(int) and Container.isAntiAlias are part of the + # codec contract and are unavailable in Flutter 3.38.1. + flutter: '>=3.41.0' + +dependencies: + ack: ^1.0.1 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + lints: ^5.0.0 + test: ^1.25.15 diff --git a/packages/flutter_codec/test/borders/borders_test.dart b/packages/flutter_codec/test/borders/borders_test.dart new file mode 100644 index 00000000..33f7a865 --- /dev/null +++ b/packages/flutter_codec/test/borders/borders_test.dart @@ -0,0 +1,403 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('strokeAlignCodec decode', () { + const namedCases = [ + ('inside', BorderSide.strokeAlignInside), + ('center', BorderSide.strokeAlignCenter), + ('outside', BorderSide.strokeAlignOutside), + ]; + + for (final (input, expected) in namedCases) { + test('decodes "$input"', () { + expect(strokeAlignCodec.parse(input), expected); + }); + } + + test('decodes a double as itself', () { + expect(strokeAlignCodec.parse(0.5), 0.5); + }); + + test('decodes an int as a double', () { + expect(strokeAlignCodec.parse(2), 2.0); + }); + + test('decodes values beyond the named range', () { + expect(strokeAlignCodec.parse(-3.5), -3.5); + }); + }); + + group('strokeAlignCodec encode', () { + test('canonicalizes named offsets to aliases', () { + for (final (offset, alias) in const [ + (BorderSide.strokeAlignInside, 'inside'), + (BorderSide.strokeAlignCenter, 'center'), + (BorderSide.strokeAlignOutside, 'outside'), + ]) { + final encoded = strokeAlignCodec.encode(offset); + expect(encoded, alias); + expectJsonSafe(encoded); + } + }); + + test('encodes other finite values as numbers', () { + final encoded = strokeAlignCodec.encode(0.5); + expect(encoded, 0.5); + expectJsonSafe(encoded); + }); + }); + + group('strokeAlignCodec rejects invalid input', () { + test('rejects unknown strings', () { + expect(strokeAlignCodec.safeParse('diagonal').isFail, isTrue); + }); + + test('rejects non-finite numbers', () { + expect(strokeAlignCodec.safeParse(double.infinity).isFail, isTrue); + expect(strokeAlignCodec.safeParse(double.nan).isFail, isTrue); + }); + }); + + group('borderSideCodec decode', () { + test('parses "none" as BorderSide.none', () { + expect(borderSideCodec.parse('none'), BorderSide.none); + }); + + test('parses an empty object as the default BorderSide', () { + // Distinct from "none": `{}` falls through to the object branch and + // produces a default-filled BorderSide (1px solid black), not + // BorderSide.none (0px style:none). + expect(borderSideCodec.parse({}), const BorderSide()); + expect(borderSideCodec.parse({}), isNot(BorderSide.none)); + }); + + test('applies defaults to a partial object, decoding nested color', () { + expect( + borderSideCodec.parse({'color': '#2196F3'}), + const BorderSide(color: Color(0xFF2196F3)), + ); + }); + + test('parses a full object', () { + expect( + borderSideCodec.parse({ + 'color': '#FF0000', + 'width': 2.0, + 'style': 'none', + 'strokeAlign': 'outside', + }), + const BorderSide( + color: Color(0xFFFF0000), + width: 2, + style: BorderStyle.none, + strokeAlign: BorderSide.strokeAlignOutside, + ), + ); + }); + }); + + group('borderSideCodec encode', () { + test('canonicalizes BorderSide.none to "none"', () { + final encoded = borderSideCodec.encode(BorderSide.none); + expect(encoded, 'none'); + expectJsonSafe(encoded); + }); + + test('emits a full canonical object including defaults', () { + final encoded = borderSideCodec.encode(const BorderSide()); + expect(encoded, { + 'color': '#000000', + 'width': 1.0, + 'style': 'solid', + 'strokeAlign': 'inside', + }); + expectJsonSafe(encoded); + }); + + test('encodes a customized BorderSide', () { + final encoded = borderSideCodec.encode( + const BorderSide( + color: Color(0xFFFF0000), + width: 2, + style: BorderStyle.none, + strokeAlign: BorderSide.strokeAlignCenter, + ), + ); + expect(encoded, { + 'color': '#FF0000', + 'width': 2.0, + 'style': 'none', + 'strokeAlign': 'center', + }); + expectJsonSafe(encoded); + }); + }); + + group('borderSideCodec rejects invalid input', () { + const invalidCases = { + 'invalid color': {'color': 'not-a-color'}, + 'negative width': {'width': -1}, + 'non-finite width': {'width': double.infinity}, + 'invalid style': {'style': 'dotted'}, + 'invalid strokeAlign': {'strokeAlign': 'diagonal'}, + 'extra property': {'unexpected': true}, + 'unknown string alias': 'thin', + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(borderSideCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('borderCodec decode', () { + test('decodes "none" as Border()', () { + expect(borderCodec.parse('none'), const Border()); + }); + + test('decodes a side shorthand as Border.all', () { + expect( + borderCodec.parse({'color': '#FF0000', 'width': 2}), + Border.all(color: const Color(0xFFFF0000), width: 2), + ); + }); + + test('decodes a full per-side object', () { + final parsed = borderCodec.parse({ + 'top': {'color': '#FF0000', 'width': 2}, + 'right': {'color': '#00FF00', 'width': 1}, + 'bottom': {'color': '#0000FF', 'width': 3}, + 'left': 'none', + }); + expect( + parsed, + const Border( + top: BorderSide(color: Color(0xFFFF0000), width: 2), + right: BorderSide(color: Color(0xFF00FF00)), + bottom: BorderSide(color: Color(0xFF0000FF), width: 3), + left: BorderSide.none, + ), + ); + }); + + test( + 'decodes a partial per-side object, defaulting omitted sides to none', + () { + expect( + borderCodec.parse({ + 'top': {'color': '#FF0000'}, + }), + const Border(top: BorderSide(color: Color(0xFFFF0000))), + ); + }, + ); + + test('decodes {} via the side branch (NOT Border())', () { + // Quirk lock-in: empty object falls through borderSideCodec to a default + // BorderSide (1px solid black), then fan-outs to all four sides. The + // canonical empty border is `"none"`, not `{}`. + expect(borderCodec.parse({}), const Border.fromBorderSide(BorderSide())); + expect(borderCodec.parse({}), isNot(const Border())); + }); + }); + + group('borderCodec encode', () { + test('canonicalizes Border() to "none"', () { + final encoded = borderCodec.encode(const Border()); + expect(encoded, 'none'); + expectJsonSafe(encoded); + }); + + test('canonicalizes uniform sides to the side shorthand', () { + final encoded = borderCodec.encode( + Border.all(color: const Color(0xFFFF0000), width: 2), + ); + expect(encoded, { + 'color': '#FF0000', + 'width': 2.0, + 'style': 'solid', + 'strokeAlign': 'inside', + }); + expectJsonSafe(encoded); + }); + + test('emits the full {top, right, bottom, left} map for mixed sides', () { + final encoded = borderCodec.encode( + const Border( + top: BorderSide(color: Color(0xFFFF0000), width: 2), + bottom: BorderSide(color: Color(0xFF0000FF), width: 3), + ), + ); + expect(encoded, { + 'top': { + 'color': '#FF0000', + 'width': 2.0, + 'style': 'solid', + 'strokeAlign': 'inside', + }, + 'right': 'none', + 'bottom': { + 'color': '#0000FF', + 'width': 3.0, + 'style': 'solid', + 'strokeAlign': 'inside', + }, + 'left': 'none', + }); + expectJsonSafe(encoded); + }); + }); + + group('borderCodec rejects invalid input', () { + test('rejects unknown keys', () { + expect(borderCodec.safeParse({'foo': 1}).isFail, isTrue); + }); + + test('rejects mixed LTR + directional keys', () { + expect( + borderCodec.safeParse({ + 'top': 'none', + 'right': 'none', + 'start': 'none', + }).isFail, + isTrue, + ); + }); + }); + + group('borderDirectionalCodec decode', () { + test('parses {} as BorderDirectional()', () { + expect(borderDirectionalCodec.parse({}), const BorderDirectional()); + }); + + test('parses a full per-side object with "none" aliases', () { + final parsed = borderDirectionalCodec.parse({ + 'top': 'none', + 'start': {'color': '#FF0000', 'width': 2}, + 'end': 'none', + 'bottom': 'none', + }); + expect( + parsed, + const BorderDirectional( + start: BorderSide(color: Color(0xFFFF0000), width: 2), + ), + ); + }); + + test('rejects "none" at the top level (no scalar shorthand)', () { + expect(borderDirectionalCodec.safeParse('none').isFail, isTrue); + }); + }); + + group('borderDirectionalCodec encode', () { + test('always emits the full object form, never a side shorthand', () { + final encoded = borderDirectionalCodec.encode(const BorderDirectional()); + expect(encoded, { + 'top': 'none', + 'start': 'none', + 'end': 'none', + 'bottom': 'none', + }); + expectJsonSafe(encoded); + }); + + test('encodes mixed sides through borderSideCodec', () { + final encoded = borderDirectionalCodec.encode( + const BorderDirectional( + start: BorderSide(color: Color(0xFFFF0000), width: 2), + ), + ); + expect(encoded, { + 'top': 'none', + 'start': { + 'color': '#FF0000', + 'width': 2.0, + 'style': 'solid', + 'strokeAlign': 'inside', + }, + 'end': 'none', + 'bottom': 'none', + }); + expectJsonSafe(encoded); + }); + }); + + group('boxBorderCodec', () { + test('decodes {top, right, bottom, left} as a Border', () { + final parsed = boxBorderCodec.parse({ + 'top': 'none', + 'right': {'color': '#FF0000'}, + 'bottom': 'none', + 'left': 'none', + }); + expect(parsed, isA()); + expect(parsed, const Border(right: BorderSide(color: Color(0xFFFF0000)))); + }); + + test('decodes {top, start, end, bottom} as a BorderDirectional', () { + final parsed = boxBorderCodec.parse({ + 'top': 'none', + 'start': {'color': '#FF0000'}, + 'end': 'none', + 'bottom': 'none', + }); + expect(parsed, isA()); + expect( + parsed, + const BorderDirectional(start: BorderSide(color: Color(0xFFFF0000))), + ); + }); + + test('decodes "none" as Border (LTR wins on shared alias)', () { + final parsed = boxBorderCodec.parse('none'); + expect(parsed, isA()); + expect(parsed, const Border()); + }); + + test('Border and BorderDirectional encode to their canonical shapes', () { + final borderEncoded = boxBorderCodec.encode(const Border()); + expect(borderEncoded, 'none'); + expectJsonSafe(borderEncoded); + + final directionalEncoded = boxBorderCodec.encode( + const BorderDirectional(), + ); + expect(directionalEncoded, { + 'top': 'none', + 'start': 'none', + 'end': 'none', + 'bottom': 'none', + }); + expectJsonSafe(directionalEncoded); + }); + + test('rejects mixed LTR + directional keys', () { + expect( + boxBorderCodec.safeParse({ + 'top': 'none', + 'right': 'none', + 'start': 'none', + 'bottom': 'none', + }).isFail, + isTrue, + ); + }); + }); + + group('borderCodec JSON Schema', () { + test('width non-negativity flows through composition', () { + // Same pattern as radius_test.dart: ack's NumberSchema.min(0) emits + // `"minimum": 0`, propagated through borderSideCodec into borderCodec's + // anyOf composition. + expect(jsonEncode(borderCodec.toJsonSchema()), contains('"minimum":0')); + }); + }); +} diff --git a/packages/flutter_codec/test/constraints/constraints_test.dart b/packages/flutter_codec/test/constraints/constraints_test.dart new file mode 100644 index 00000000..70cb5df0 --- /dev/null +++ b/packages/flutter_codec/test/constraints/constraints_test.dart @@ -0,0 +1,170 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('boxConstraintsCodec decode', () { + test('decodes an empty object as default constraints', () { + expect(boxConstraintsCodec.parse({}), const BoxConstraints()); + }); + + test('decodes explicit null max bounds as unbounded', () { + expect( + boxConstraintsCodec.parse({ + 'minWidth': 0, + 'maxWidth': null, + 'minHeight': 0, + 'maxHeight': null, + }), + const BoxConstraints(), + ); + }); + + test('decodes explicit null min bounds as infinite', () { + expect( + boxConstraintsCodec.parse({ + 'minWidth': null, + 'maxWidth': null, + 'minHeight': null, + 'maxHeight': null, + }), + const BoxConstraints.expand(), + ); + }); + }); + + group('boxConstraintsCodec encode', () { + test('emits a full canonical map with nulls for infinite bounds', () { + final encoded = boxConstraintsCodec.encode(const BoxConstraints()); + + expect(encoded, { + 'minWidth': 0.0, + 'maxWidth': null, + 'minHeight': 0.0, + 'maxHeight': null, + }); + expectJsonSafe(encoded); + }); + + test('round-trips fully populated finite constraints', () { + const constraints = BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ); + + final encoded = boxConstraintsCodec.encode(constraints); + + expect(boxConstraintsCodec.parse(encoded), constraints); + expectJsonSafe(encoded); + }); + + test('round-trips tightFor constraints', () { + final constraints = BoxConstraints.tightFor(width: 12, height: 34); + + expect( + boxConstraintsCodec.parse(boxConstraintsCodec.encode(constraints)!), + constraints, + ); + }); + + test('round-trips expand constraints', () { + const constraints = BoxConstraints.expand(); + + expect( + boxConstraintsCodec.parse(boxConstraintsCodec.encode(constraints)!), + constraints, + ); + }); + }); + + group('boxConstraintsCodec rejects inverted bounds', () { + test('rejects minWidth greater than maxWidth on decode', () { + expect( + boxConstraintsCodec.safeParse({'minWidth': 100, 'maxWidth': 50}).isFail, + isTrue, + ); + }); + + test('rejects minHeight greater than maxHeight on decode', () { + expect( + boxConstraintsCodec.safeParse({ + 'minHeight': 100, + 'maxHeight': 50, + }).isFail, + isTrue, + ); + }); + + test('rejects an infinite min against a finite max (null min bound)', () { + // A null minWidth resolves to infinity, which exceeds a finite maxWidth. + expect( + boxConstraintsCodec.safeParse({ + 'minWidth': null, + 'maxWidth': 50, + }).isFail, + isTrue, + ); + }); + + test('fails to encode an inverted BoxConstraints', () { + expect( + boxConstraintsCodec + .safeEncode(const BoxConstraints(minWidth: 100, maxWidth: 50)) + .isFail, + isTrue, + ); + }); + }); + + group('constraintsCodec', () { + test('parses a box constraints branch', () { + final parsed = constraintsCodec.parse({ + 'type': 'box', + 'minWidth': 1, + 'maxWidth': 10, + 'minHeight': 2, + 'maxHeight': 20, + }); + + expect( + parsed, + const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ); + expect(parsed, isA()); + }); + + test('encodes BoxConstraints with a discriminator', () { + const constraints = BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ); + + final encoded = constraintsCodec.encode(constraints); + + expect(encoded, { + 'type': 'box', + 'minWidth': 1.0, + 'maxWidth': 10.0, + 'minHeight': 2.0, + 'maxHeight': 20.0, + }); + expect(constraintsCodec.parse(encoded), constraints); + expectJsonSafe(encoded); + }); + + test('rejects an unknown constraints discriminator', () { + expect(constraintsCodec.safeParse({'type': 'sliver'}).isFail, isTrue); + }); + }); +} diff --git a/packages/flutter_codec/test/decoration_image/decoration_image_test.dart b/packages/flutter_codec/test/decoration_image/decoration_image_test.dart new file mode 100644 index 00000000..bc68d621 --- /dev/null +++ b/packages/flutter_codec/test/decoration_image/decoration_image_test.dart @@ -0,0 +1,155 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +const _networkUrl = 'https://example.com/image.png'; + +void main() { + group('decorationImageCodec decode', () { + test('decodes a minimal input as DecorationImage with defaults', () { + final parsed = decorationImageCodec.parse({ + 'image': {'type': 'network', 'url': _networkUrl}, + }); + expect(parsed, DecorationImage(image: const NetworkImage(_networkUrl))); + }); + + test('decodes a full real-world DecorationImage', () { + final parsed = decorationImageCodec.parse({ + 'image': {'type': 'asset', 'assetName': 'icons/foo.png'}, + 'fit': 'cover', + 'alignment': 'topLeft', + 'centerSlice': {'left': 1, 'top': 2, 'right': 3, 'bottom': 4}, + 'repeat': 'repeat', + 'matchTextDirection': true, + 'scale': 2.0, + 'opacity': 0.5, + 'filterQuality': 'high', + 'invertColors': true, + 'isAntiAlias': true, + }); + expect( + parsed, + DecorationImage( + image: const AssetImage('icons/foo.png'), + fit: BoxFit.cover, + alignment: Alignment.topLeft, + centerSlice: const Rect.fromLTRB(1, 2, 3, 4), + repeat: ImageRepeat.repeat, + matchTextDirection: true, + scale: 2.0, + opacity: 0.5, + filterQuality: FilterQuality.high, + invertColors: true, + isAntiAlias: true, + ), + ); + }); + }); + + group('decorationImageCodec encode', () { + test('emits a full canonical map with explicit defaults', () { + final encoded = decorationImageCodec.encode( + DecorationImage(image: const NetworkImage(_networkUrl)), + ); + expect(encoded, { + 'image': { + 'type': 'network', + 'url': _networkUrl, + 'scale': 1.0, + 'headers': null, + 'webHtmlElementStrategy': 'never', + }, + 'fit': null, + 'alignment': 'center', + 'centerSlice': null, + 'repeat': 'noRepeat', + 'matchTextDirection': false, + 'scale': 1.0, + 'opacity': 1.0, + 'filterQuality': 'medium', + 'invertColors': false, + 'isAntiAlias': false, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a fully-populated DecorationImage', () { + final original = DecorationImage( + image: const AssetImage('icons/foo.png', package: 'my_pkg'), + fit: BoxFit.cover, + alignment: Alignment.bottomRight, + centerSlice: const Rect.fromLTRB(1, 2, 3, 4), + repeat: ImageRepeat.repeatX, + matchTextDirection: true, + scale: 1.5, + opacity: 0.75, + filterQuality: FilterQuality.low, + invertColors: true, + isAntiAlias: true, + ); + + final encoded = decorationImageCodec.encode(original); + expect(decorationImageCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + }); + + group('decorationImageCodec rejects invalid input', () { + const invalidCases = { + 'missing image': {}, + 'invalid image type': { + 'image': {'type': 'spiral', 'url': _networkUrl}, + }, + 'invalid fit': { + 'image': {'type': 'network', 'url': _networkUrl}, + 'fit': 'squoosh', + }, + 'opacity above 1': { + 'image': {'type': 'network', 'url': _networkUrl}, + 'opacity': 1.5, + }, + 'opacity below 0': { + 'image': {'type': 'network', 'url': _networkUrl}, + 'opacity': -0.1, + }, + 'unknown key': { + 'image': {'type': 'network', 'url': _networkUrl}, + 'foo': 1, + }, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(decorationImageCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('decorationImageCodec JSON Schema', () { + test('dependent codec markers flow through composition', () { + final schema = jsonEncode(decorationImageCodec.toJsonSchema()); + // image provider discriminator + expect(schema, contains('"network"')); + expect(schema, contains('"asset"')); + // opacity range + expect(schema, contains('"minimum":0')); + expect(schema, contains('"maximum":1')); + }); + }); + + group('decorationImageCodec colorFilter', () { + test('rejects a DecorationImage with a non-null colorFilter on encode', () { + // colorFilter is part of DecorationImage equality but has no portable + // JSON shape, so encoding must fail loudly rather than drop it silently. + final image = DecorationImage( + image: const NetworkImage(_networkUrl), + colorFilter: const ColorFilter.mode(Color(0xFFFF0000), BlendMode.srcIn), + ); + expect(decorationImageCodec.safeEncode(image).isFail, isTrue); + }); + }); +} diff --git a/packages/flutter_codec/test/decorations/decorations_test.dart b/packages/flutter_codec/test/decorations/decorations_test.dart new file mode 100644 index 00000000..dc680c38 --- /dev/null +++ b/packages/flutter_codec/test/decorations/decorations_test.dart @@ -0,0 +1,428 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +const _redBlueHex = ['#FF0000', '#0000FF']; +const _redBlue = [Color(0xFFFF0000), Color(0xFF0000FF)]; + +void main() { + // --- boxDecorationCodec ---------------------------------------------------- + + group('boxDecorationCodec decode', () { + test('decodes an empty object as the default BoxDecoration', () { + expect(boxDecorationCodec.parse({}), const BoxDecoration()); + }); + + test('decodes a full real-world BoxDecoration without image', () { + expect( + boxDecorationCodec.parse({ + 'color': '#2196F3', + 'border': {'color': '#FF0000', 'width': 2}, + 'borderRadius': 8, + 'boxShadow': [ + { + 'color': '#55000000', + 'offset': {'x': 1, 'y': 2}, + 'blurRadius': 3, + 'spreadRadius': 4, + 'blurStyle': 'outer', + }, + ], + 'gradient': { + 'type': 'linear', + 'begin': 'topLeft', + 'end': 'bottomRight', + 'colors': _redBlueHex, + 'stops': [0, 1], + 'tileMode': 'mirror', + }, + 'backgroundBlendMode': 'multiply', + 'shape': 'rectangle', + }), + BoxDecoration( + color: const Color(0xFF2196F3), + border: Border.all(color: const Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + boxShadow: const [ + BoxShadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + spreadRadius: 4, + blurStyle: BlurStyle.outer, + ), + ], + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0, 1], + tileMode: TileMode.mirror, + ), + backgroundBlendMode: BlendMode.multiply, + shape: BoxShape.rectangle, + ), + ); + }); + + test('rejects shape circle combined with a borderRadius', () { + // BoxDecoration.debugAssertIsValid forbids a borderRadius on a circle; + // enforce it at the codec boundary so it holds in release builds too. + expect( + boxDecorationCodec.safeParse({ + 'shape': 'circle', + 'borderRadius': 8, + }).isFail, + isTrue, + ); + }); + + test('decodes partial inputs', () { + expect( + boxDecorationCodec.parse({'color': '#00FF00'}), + const BoxDecoration(color: Color(0xFF00FF00)), + ); + expect( + boxDecorationCodec.parse({'shape': 'circle'}), + const BoxDecoration(shape: BoxShape.circle), + ); + }); + }); + + group('boxDecorationCodec encode', () { + test('emits a full canonical map with explicit nulls for defaults', () { + final encoded = boxDecorationCodec.encode(const BoxDecoration()); + + expect(encoded, { + 'color': null, + 'image': null, + 'border': null, + 'borderRadius': null, + 'boxShadow': null, + 'gradient': null, + 'backgroundBlendMode': null, + 'shape': 'rectangle', + }); + expectJsonSafe(encoded); + }); + + test('round-trips a full BoxDecoration without image', () { + final original = BoxDecoration( + color: const Color(0xFF2196F3), + border: Border.all(color: const Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + boxShadow: const [ + BoxShadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + spreadRadius: 4, + blurStyle: BlurStyle.outer, + ), + ], + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0, 1], + tileMode: TileMode.mirror, + ), + backgroundBlendMode: BlendMode.multiply, + ); + + final encoded = boxDecorationCodec.encode(original); + + expect(boxDecorationCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + }); + + group('boxDecorationCodec image integration', () { + test('decodes an image field via decorationImageCodec', () { + final parsed = boxDecorationCodec.parse({ + 'image': { + 'image': {'type': 'network', 'url': 'https://example.com/foo.png'}, + 'fit': 'cover', + }, + }); + expect(parsed!.image, isA()); + expect(parsed.image!.image, isA()); + expect(parsed.image!.fit, BoxFit.cover); + }); + + test('accepts an explicit null image', () { + expect(boxDecorationCodec.parse({'image': null}), const BoxDecoration()); + }); + + test('round-trips a BoxDecoration with an image', () { + final original = BoxDecoration( + image: DecorationImage( + image: const NetworkImage('https://example.com/foo.png'), + fit: BoxFit.cover, + alignment: Alignment.topLeft, + ), + ); + + final encoded = boxDecorationCodec.encode(original); + expect(boxDecorationCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + }); + + group('boxDecorationCodec rejects invalid input', () { + const invalidCases = { + 'unknown keys': {'foo': 1}, + 'invalid color': {'color': 'not-a-color'}, + 'mismatched border keys': { + 'border': {'top': 'none', 'right': 'none', 'start': 'none'}, + }, + 'invalid gradient discriminator': { + 'gradient': {'type': 'spiral', 'colors': _redBlueHex}, + }, + 'invalid nested image provider': { + 'image': { + 'image': {'type': 'spiral', 'url': 'https://example.com/x.png'}, + }, + }, + // backgroundBlendMode requires a color or gradient (release-safe refine). + 'backgroundBlendMode without color or gradient': { + 'backgroundBlendMode': 'multiply', + }, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(boxDecorationCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('boxDecorationCodec JSON Schema', () { + test('dependent codec schemas flow through composition', () { + final schema = jsonEncode(boxDecorationCodec.toJsonSchema()); + + expect(schema, contains('"circle"')); + expect(schema, contains('"const":"linear"')); + expect(schema, contains(r'^#[0-9A-Fa-f]{6}$')); + }); + }); + + // --- shapeDecorationCodec -------------------------------------------------- + + group('shapeDecorationCodec decode', () { + test('decodes a minimal ShapeDecoration with just a shape', () { + expect( + shapeDecorationCodec.parse({ + 'shape': {'type': 'circle'}, + }), + const ShapeDecoration(shape: CircleBorder()), + ); + }); + + test('decodes a full ShapeDecoration', () { + // ShapeDecoration asserts color XOR gradient — exercise the gradient + // branch here; color-only is exercised by the encode round-trip below. + final decoded = shapeDecorationCodec.parse({ + 'gradient': {'type': 'linear', 'colors': _redBlueHex}, + 'shadows': [ + { + 'color': '#55000000', + 'offset': {'x': 1, 'y': 2}, + 'blurRadius': 3, + }, + ], + 'shape': {'type': 'roundedRectangle', 'borderRadius': 8}, + }); + + expect( + decoded, + ShapeDecoration( + gradient: const LinearGradient(colors: _redBlue), + shadows: const [ + BoxShadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + ), + ], + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + ); + }); + }); + + group('shapeDecorationCodec encode', () { + test('emits a canonical map with explicit nulls for unset fields', () { + final encoded = shapeDecorationCodec.encode( + const ShapeDecoration(shape: CircleBorder()), + ); + + expect(encoded, { + 'color': null, + 'image': null, + 'gradient': null, + 'shadows': null, + // Nested codecs re-encode to JSON, so the shape arrives as its + // canonical map form (including the discriminator), not as the + // runtime CircleBorder instance. + 'shape': {'type': 'circle', 'side': 'none', 'eccentricity': 0.0}, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a populated ShapeDecoration', () { + final original = ShapeDecoration( + color: const Color(0xFF2196F3), + shadows: const [ + BoxShadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + ), + ], + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ); + + final encoded = shapeDecorationCodec.encode(original); + expect(shapeDecorationCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + + test('round-trips a ShapeDecoration carrying a DecorationImage', () { + final original = ShapeDecoration( + shape: const CircleBorder(), + image: const DecorationImage( + image: NetworkImage('https://example.com/image.png'), + fit: BoxFit.cover, + ), + ); + + final encoded = shapeDecorationCodec.encode(original); + expect(shapeDecorationCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + }); + + group('shapeDecorationCodec rejects invalid input', () { + test('rejects a missing required shape', () { + expect(shapeDecorationCodec.safeParse({}).isFail, isTrue); + }); + + test('rejects an unknown shape discriminator', () { + expect( + shapeDecorationCodec.safeParse({ + 'shape': {'type': 'oval'}, + }).isFail, + isTrue, + ); + }); + + test('rejects both color and gradient (release-safe refine)', () { + expect( + shapeDecorationCodec.safeParse({ + 'shape': {'type': 'circle'}, + 'color': '#FF0000', + 'gradient': {'type': 'linear', 'colors': _redBlueHex}, + }).isFail, + isTrue, + ); + }); + + test('rejects unknown keys', () { + expect( + shapeDecorationCodec.safeParse({ + 'shape': {'type': 'circle'}, + 'foo': true, + }).isFail, + isTrue, + ); + }); + }); + + // --- decorationCodec (union) ---------------------------------------------- + + group('decorationCodec decode', () { + test('parses {type: box, ...} as a BoxDecoration', () { + final decoded = decorationCodec.parse({ + 'type': 'box', + 'color': '#2196F3', + }); + expect(decoded, isA()); + expect((decoded as BoxDecoration).color, const Color(0xFF2196F3)); + }); + + test('parses {type: shape, ...} as a ShapeDecoration', () { + final decoded = decorationCodec.parse({ + 'type': 'shape', + 'shape': {'type': 'circle'}, + }); + expect(decoded, isA()); + expect((decoded as ShapeDecoration).shape, const CircleBorder()); + }); + }); + + group('decorationCodec encode', () { + test('emits {type: box, ...} for a BoxDecoration', () { + final encoded = + decorationCodec.encode(const BoxDecoration()) as Map; + expect(encoded['type'], 'box'); + expect(encoded.containsKey('color'), isTrue); + expect(encoded.containsKey('shape'), isTrue); + expectJsonSafe(encoded); + }); + + test('emits {type: shape, ...} for a ShapeDecoration', () { + final encoded = + decorationCodec.encode(const ShapeDecoration(shape: CircleBorder())) + as Map; + expect(encoded['type'], 'shape'); + expect(encoded['shape'], { + 'type': 'circle', + 'side': 'none', + 'eccentricity': 0.0, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a BoxDecoration through the union', () { + final original = const BoxDecoration( + color: Color(0xFF2196F3), + shape: BoxShape.circle, + ); + expect(decorationCodec.parse(decorationCodec.encode(original)), original); + }); + + test('round-trips a ShapeDecoration through the union', () { + final original = ShapeDecoration( + color: const Color(0xFF2196F3), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ); + expect(decorationCodec.parse(decorationCodec.encode(original)), original); + }); + }); + + group('decorationCodec rejects invalid input', () { + test('rejects an unknown discriminator', () { + expect( + decorationCodec.safeParse({'type': 'flutter-logo'}).isFail, + isTrue, + ); + }); + + test('rejects a missing discriminator', () { + expect(decorationCodec.safeParse({}).isFail, isTrue); + }); + }); + + group('decorationCodec JSON Schema', () { + test('surfaces both discriminator branches', () { + final schema = jsonEncode(decorationCodec.toJsonSchema()); + expect(schema, contains('"box"')); + expect(schema, contains('"shape"')); + }); + }); +} diff --git a/packages/flutter_codec/test/enums/enums_test.dart b/packages/flutter_codec/test/enums/enums_test.dart new file mode 100644 index 00000000..0229eb51 --- /dev/null +++ b/packages/flutter_codec/test/enums/enums_test.dart @@ -0,0 +1,210 @@ +import 'dart:ui'; + +import 'package:ack/ack.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('enum schemas', () { + for (final entry in _registry) { + group(entry.name, () { + test('round-trips every enum value', () { + for (final value in entry.values) { + final encoded = entry.encode(value); + expect(encoded, value.name); + expectJsonSafe(encoded); + expect(entry.parse(value.name), value); + } + }); + + test('rejects unknown strings', () { + expect(entry.rejects('__nope__'), isTrue); + }); + }); + } + }); +} + +final _registry = <_EnumCase>[ + _EnumCase('Axis', axisCodec, Axis.values), + _EnumCase( + 'AxisDirection', + axisDirectionCodec, + AxisDirection.values, + ), + _EnumCase('BlendMode', blendModeCodec, BlendMode.values), + _EnumCase('BlurStyle', blurStyleCodec, BlurStyle.values), + _EnumCase('BorderStyle', borderStyleCodec, BorderStyle.values), + _EnumCase('BoxFit', boxFitCodec, BoxFit.values), + _EnumCase( + 'BoxHeightStyle', + boxHeightStyleCodec, + BoxHeightStyle.values, + ), + _EnumCase('BoxShape', boxShapeCodec, BoxShape.values), + _EnumCase( + 'BoxWidthStyle', + boxWidthStyleCodec, + BoxWidthStyle.values, + ), + _EnumCase('Brightness', brightnessCodec, Brightness.values), + _EnumCase('Clip', clipCodec, Clip.values), + _EnumCase( + 'CrossAxisAlignment', + crossAxisAlignmentCodec, + CrossAxisAlignment.values, + ), + _EnumCase( + 'DecorationPosition', + decorationPositionCodec, + DecorationPosition.values, + ), + _EnumCase( + 'DragStartBehavior', + dragStartBehaviorCodec, + DragStartBehavior.values, + ), + _EnumCase( + 'FilterQuality', + filterQualityCodec, + FilterQuality.values, + ), + _EnumCase('FlexFit', flexFitCodec, FlexFit.values), + _EnumCase('FontStyle', fontStyleCodec, FontStyle.values), + _EnumCase( + 'GrowthDirection', + growthDirectionCodec, + GrowthDirection.values, + ), + _EnumCase( + 'HitTestBehavior', + hitTestBehaviorCodec, + HitTestBehavior.values, + ), + _EnumCase('ImageRepeat', imageRepeatCodec, ImageRepeat.values), + _EnumCase( + 'WebHtmlElementStrategy', + webHtmlElementStrategyCodec, + WebHtmlElementStrategy.values, + ), + _EnumCase( + 'MainAxisAlignment', + mainAxisAlignmentCodec, + MainAxisAlignment.values, + ), + _EnumCase( + 'MainAxisSize', + mainAxisSizeCodec, + MainAxisSize.values, + ), + _EnumCase( + 'MaterialTapTargetSize', + materialTapTargetSizeCodec, + MaterialTapTargetSize.values, + ), + _EnumCase( + 'PaintingStyle', + paintingStyleCodec, + PaintingStyle.values, + ), + _EnumCase( + 'PathFillType', + pathFillTypeCodec, + PathFillType.values, + ), + _EnumCase( + 'PlaceholderAlignment', + placeholderAlignmentCodec, + PlaceholderAlignment.values, + ), + _EnumCase( + 'ScrollDirection', + scrollDirectionCodec, + ScrollDirection.values, + ), + _EnumCase( + 'ScrollViewKeyboardDismissBehavior', + scrollViewKeyboardDismissBehaviorCodec, + ScrollViewKeyboardDismissBehavior.values, + ), + _EnumCase('StackFit', stackFitCodec, StackFit.values), + _EnumCase('StrokeCap', strokeCapCodec, StrokeCap.values), + _EnumCase('StrokeJoin', strokeJoinCodec, StrokeJoin.values), + _EnumCase( + 'TargetPlatform', + targetPlatformCodec, + TargetPlatform.values, + ), + _EnumCase('TextAlign', textAlignCodec, TextAlign.values), + _EnumCase( + 'TextBaseline', + textBaselineCodec, + TextBaseline.values, + ), + _EnumCase( + 'TextCapitalization', + textCapitalizationCodec, + TextCapitalization.values, + ), + _EnumCase( + 'TextDecorationStyle', + textDecorationStyleCodec, + TextDecorationStyle.values, + ), + _EnumCase( + 'TextDirection', + textDirectionCodec, + TextDirection.values, + ), + _EnumCase( + 'TextLeadingDistribution', + textLeadingDistributionCodec, + TextLeadingDistribution.values, + ), + _EnumCase( + 'TextOverflow', + textOverflowCodec, + TextOverflow.values, + ), + _EnumCase( + 'TextWidthBasis', + textWidthBasisCodec, + TextWidthBasis.values, + ), + _EnumCase('ThemeMode', themeModeCodec, ThemeMode.values), + _EnumCase('TileMode', tileModeCodec, TileMode.values), + _EnumCase( + 'VerticalDirection', + verticalDirectionCodec, + VerticalDirection.values, + ), + _EnumCase( + 'WrapAlignment', + wrapAlignmentCodec, + WrapAlignment.values, + ), + _EnumCase( + 'WrapCrossAlignment', + wrapCrossAlignmentCodec, + WrapCrossAlignment.values, + ), +]; + +final class _EnumCase { + const _EnumCase(this.name, this.schema, this.values); + + final String name; + final CodecSchema schema; + final List values; + + String? encode(Enum value) => schema.encode(value as T); + + T? parse(String value) => schema.parse(value); + + bool rejects(String value) => schema.safeParse(value).isFail; +} diff --git a/packages/flutter_codec/test/golden/README.md b/packages/flutter_codec/test/golden/README.md new file mode 100644 index 00000000..33561f25 --- /dev/null +++ b/packages/flutter_codec/test/golden/README.md @@ -0,0 +1,100 @@ +# Golden fixtures + +These files pin the exact JSON that every public codec in `flutter_codec` +produces, and `golden_test.dart` proves each one parses back. They are the +human-reviewable record of the package's wire format — if an encoder changes +shape, a fixture diff makes it obvious. + +`json_schema.json` separately pins the JSON Schema exported by all public +codecs. It uses one compact schema per line so a diff identifies the changed +codec without inflating the fixture with indentation for deeply composed +schemas. `schema_golden_test.dart` also checks that every public `*Codec` +declaration appears in that fixture. + +## How to read a fixture file + +Each file under `fixtures/` is one **family** (mirroring `lib/src/`), and is a +JSON object of the form: + +```jsonc +{ + "": , + ... +} +``` + +> [!IMPORTANT] +> The **top-level keys are test-case identifiers, not wire data.** They only +> exist to group many cases in one file. The thing the codec produces — the +> actual layout you care about — is always the **value**. + +For example, in `primitives.json`: + +```jsonc +{ + "color": "#2196F3", // case "color" -> colorCodec emits "#2196F3" + "offset": { "x": 12.0, "y": 4.5 } // case "offset" -> the real Offset wire shape +} +``` + +`color` and `offset` are labels. `"#2196F3"` and `{ "x": 12.0, "y": 4.5 }` are +the real encodings. `enums.json` follows the same rule: the key is the enum type +name, the value is the full ordered list of wire strings that codec accepts and +emits. + +## What the round-trip check asserts + +For every case the test: + +1. **Encodes** a representative typed value and asserts it equals the recorded + JSON (a shape change shows up as a golden diff). +2. **Parses the JSON back** and verifies the round-trip, one of: + - **value equality** (`==`) — the painting/rendering value types; + - **stability** (`encode(parse(json)) == json`) — `Container` / `Text` / + the widget union, which intentionally have no value equality; + - **documented narrowing** — e.g. `OvalBorder` routes through the `circle` + branch and round-trips as `CircleBorder(eccentricity: 1.0)`. + +## Null / optional / missing-key conventions + +- **Encoding always emits the full canonical map with explicit `null`s.** Every + supported-but-unset field is present as `null` (this is why the maps look + verbose). That makes the output self-documenting and gives clean diffs. +- **Decoding treats an absent key and an explicit `null` as identical** for + `nullable().optional()` fields, so compact input (`{}`, partial objects) and + the verbose canonical form decode to the same value. +- **Unsupported fields are omitted entirely, not nulled.** A *missing* key in + the output means "not part of this type's contract" (e.g. `Text.textScaler`), + whereas `"key": null` means "supported field, currently unset." +- **`BoxConstraints` is the deliberate exception where absent ≠ null:** an + *omitted* min bound decodes to `0`, but an explicit `"minWidth": null` decodes + to `infinity` (JSON has no infinity literal, so `null` stands in for it). + +## Intentional losses (covered by the dedicated unit tests, not these goldens) + +- `Color` is 8-bit sRGB hex; float-channel precision and non-sRGB color spaces + are not preserved. +- `Gradient.transform` and `DecorationImage.colorFilter` have no portable JSON + shape and **throw on encode** rather than dropping silently. +- `StarBorder.polygon` is intentionally *not* recorded here: its encoded + `innerRadiusRatio` is `cos(pi / sides)`, a libm value that is not guaranteed + bit-identical across platforms. Its narrowing is tested with a tolerance in + `test/shape_borders/shape_borders_test.dart`. + +## Determinism + +Fixtures must be byte-identical on any machine, so the representative values +avoid transcendental functions (matrix transforms use translate/scale, not +`rotateZ`). The only long decimal in the fixtures is `6.283185307179586`, which +is exactly `2 * math.pi` — constant arithmetic, not a libm call. + +## Regenerating after an intentional change + +```sh +UPDATE_GOLDENS=true flutter test test/golden/golden_test.dart +UPDATE_GOLDENS=true flutter test test/golden/schema_golden_test.dart +``` + +This rewrites every `fixtures/*.json` from the current encoders. Review the diff, +then run `flutter test test/golden/golden_test.dart` (without the flag) to +confirm everything still parses back. diff --git a/packages/flutter_codec/test/golden/fixtures/borders.json b/packages/flutter_codec/test/golden/fixtures/borders.json new file mode 100644 index 00000000..cc465808 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/borders.json @@ -0,0 +1,56 @@ +{ + "strokeAlignNamed": "outside", + "strokeAlignNumeric": 0.5, + "borderSideNone": "none", + "borderSideFull": { + "color": "#FF0000", + "width": 2.0, + "style": "none", + "strokeAlign": "center" + }, + "borderNone": "none", + "borderUniform": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "borderMixed": { + "top": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "right": "none", + "bottom": { + "color": "#0000FF", + "width": 3.0, + "style": "solid", + "strokeAlign": "inside" + }, + "left": "none" + }, + "borderDirectional": { + "top": "none", + "start": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "end": "none", + "bottom": "none" + }, + "boxBorderDirectional": { + "top": "none", + "start": { + "color": "#FF0000", + "width": 1.0, + "style": "solid", + "strokeAlign": "inside" + }, + "end": "none", + "bottom": "none" + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/constraints.json b/packages/flutter_codec/test/golden/fixtures/constraints.json new file mode 100644 index 00000000..30ccd171 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/constraints.json @@ -0,0 +1,27 @@ +{ + "boxConstraintsDefault": { + "minWidth": 0.0, + "maxWidth": null, + "minHeight": 0.0, + "maxHeight": null + }, + "boxConstraintsFinite": { + "minWidth": 1.0, + "maxWidth": 10.0, + "minHeight": 2.0, + "maxHeight": 20.0 + }, + "boxConstraintsExpand": { + "minWidth": null, + "maxWidth": null, + "minHeight": null, + "maxHeight": null + }, + "constraintsUnionBox": { + "type": "box", + "minWidth": 1.0, + "maxWidth": 10.0, + "minHeight": 2.0, + "maxHeight": 20.0 + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/decoration_image.json b/packages/flutter_codec/test/golden/fixtures/decoration_image.json new file mode 100644 index 00000000..3def99c0 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/decoration_image.json @@ -0,0 +1,43 @@ +{ + "decorationImageMinimal": { + "image": { + "type": "network", + "url": "https://example.com/image.png", + "scale": 1.0, + "headers": null, + "webHtmlElementStrategy": "never" + }, + "fit": null, + "alignment": "center", + "centerSlice": null, + "repeat": "noRepeat", + "matchTextDirection": false, + "scale": 1.0, + "opacity": 1.0, + "filterQuality": "medium", + "invertColors": false, + "isAntiAlias": false + }, + "decorationImageFull": { + "image": { + "type": "asset", + "assetName": "icons/foo.png", + "package": "my_pkg" + }, + "fit": "cover", + "alignment": "bottomRight", + "centerSlice": { + "left": 1.0, + "top": 2.0, + "right": 3.0, + "bottom": 4.0 + }, + "repeat": "repeatX", + "matchTextDirection": true, + "scale": 1.5, + "opacity": 0.75, + "filterQuality": "low", + "invertColors": true, + "isAntiAlias": true + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/decorations.json b/packages/flutter_codec/test/golden/fixtures/decorations.json new file mode 100644 index 00000000..65780246 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/decorations.json @@ -0,0 +1,164 @@ +{ + "boxDecorationDefault": { + "color": null, + "image": null, + "border": null, + "borderRadius": null, + "boxShadow": null, + "gradient": null, + "backgroundBlendMode": null, + "shape": "rectangle" + }, + "boxDecorationFull": { + "color": "#2196F3", + "image": null, + "border": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "borderRadius": 8.0, + "boxShadow": [ + { + "color": "#55000000", + "offset": { + "x": 1.0, + "y": 2.0 + }, + "blurRadius": 3.0, + "spreadRadius": 4.0, + "blurStyle": "outer" + } + ], + "gradient": { + "type": "linear", + "begin": "topLeft", + "end": "bottomRight", + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": [ + 0.0, + 1.0 + ], + "tileMode": "mirror" + }, + "backgroundBlendMode": "multiply", + "shape": "rectangle" + }, + "boxDecorationImage": { + "color": null, + "image": { + "image": { + "type": "network", + "url": "https://example.com/foo.png", + "scale": 1.0, + "headers": null, + "webHtmlElementStrategy": "never" + }, + "fit": "cover", + "alignment": "topLeft", + "centerSlice": null, + "repeat": "noRepeat", + "matchTextDirection": false, + "scale": 1.0, + "opacity": 1.0, + "filterQuality": "medium", + "invertColors": false, + "isAntiAlias": false + }, + "border": null, + "borderRadius": null, + "boxShadow": null, + "gradient": null, + "backgroundBlendMode": null, + "shape": "rectangle" + }, + "shapeDecorationCircle": { + "color": null, + "image": null, + "gradient": null, + "shadows": null, + "shape": { + "type": "circle", + "side": "none", + "eccentricity": 0.0 + } + }, + "shapeDecorationFull": { + "color": "#2196F3", + "image": null, + "gradient": null, + "shadows": [ + { + "color": "#55000000", + "offset": { + "x": 1.0, + "y": 2.0 + }, + "blurRadius": 3.0, + "spreadRadius": 0.0, + "blurStyle": "normal" + } + ], + "shape": { + "type": "roundedRectangle", + "side": "none", + "borderRadius": 8.0 + } + }, + "shapeDecorationImage": { + "color": null, + "image": { + "image": { + "type": "network", + "url": "https://example.com/image.png", + "scale": 1.0, + "headers": null, + "webHtmlElementStrategy": "never" + }, + "fit": "cover", + "alignment": "center", + "centerSlice": null, + "repeat": "noRepeat", + "matchTextDirection": false, + "scale": 1.0, + "opacity": 1.0, + "filterQuality": "medium", + "invertColors": false, + "isAntiAlias": false + }, + "gradient": null, + "shadows": null, + "shape": { + "type": "circle", + "side": "none", + "eccentricity": 0.0 + } + }, + "decorationUnionBox": { + "type": "box", + "color": "#2196F3", + "image": null, + "border": null, + "borderRadius": null, + "boxShadow": null, + "gradient": null, + "backgroundBlendMode": null, + "shape": "rectangle" + }, + "decorationUnionShape": { + "type": "shape", + "color": null, + "image": null, + "gradient": null, + "shadows": null, + "shape": { + "type": "circle", + "side": "none", + "eccentricity": 0.0 + } + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/enums.json b/packages/flutter_codec/test/golden/fixtures/enums.json new file mode 100644 index 00000000..f02327e4 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/enums.json @@ -0,0 +1,272 @@ +{ + "Axis": [ + "horizontal", + "vertical" + ], + "AxisDirection": [ + "up", + "right", + "down", + "left" + ], + "BlendMode": [ + "clear", + "src", + "dst", + "srcOver", + "dstOver", + "srcIn", + "dstIn", + "srcOut", + "dstOut", + "srcATop", + "dstATop", + "xor", + "plus", + "modulate", + "screen", + "overlay", + "darken", + "lighten", + "colorDodge", + "colorBurn", + "hardLight", + "softLight", + "difference", + "exclusion", + "multiply", + "hue", + "saturation", + "color", + "luminosity" + ], + "BlurStyle": [ + "normal", + "solid", + "outer", + "inner" + ], + "BorderStyle": [ + "none", + "solid" + ], + "BoxFit": [ + "fill", + "contain", + "cover", + "fitWidth", + "fitHeight", + "none", + "scaleDown" + ], + "BoxHeightStyle": [ + "tight", + "max", + "includeLineSpacingMiddle", + "includeLineSpacingTop", + "includeLineSpacingBottom", + "strut" + ], + "BoxShape": [ + "rectangle", + "circle" + ], + "BoxWidthStyle": [ + "tight", + "max" + ], + "Brightness": [ + "dark", + "light" + ], + "Clip": [ + "none", + "hardEdge", + "antiAlias", + "antiAliasWithSaveLayer" + ], + "CrossAxisAlignment": [ + "start", + "end", + "center", + "stretch", + "baseline" + ], + "DecorationPosition": [ + "background", + "foreground" + ], + "DragStartBehavior": [ + "down", + "start" + ], + "FilterQuality": [ + "none", + "low", + "medium", + "high" + ], + "FlexFit": [ + "tight", + "loose" + ], + "FontStyle": [ + "normal", + "italic" + ], + "GrowthDirection": [ + "forward", + "reverse" + ], + "HitTestBehavior": [ + "deferToChild", + "opaque", + "translucent" + ], + "ImageRepeat": [ + "repeat", + "repeatX", + "repeatY", + "noRepeat" + ], + "WebHtmlElementStrategy": [ + "never", + "fallback", + "prefer" + ], + "MainAxisAlignment": [ + "start", + "end", + "center", + "spaceBetween", + "spaceAround", + "spaceEvenly" + ], + "MainAxisSize": [ + "min", + "max" + ], + "MaterialTapTargetSize": [ + "padded", + "shrinkWrap" + ], + "PaintingStyle": [ + "fill", + "stroke" + ], + "PathFillType": [ + "nonZero", + "evenOdd" + ], + "PlaceholderAlignment": [ + "baseline", + "aboveBaseline", + "belowBaseline", + "top", + "bottom", + "middle" + ], + "ScrollDirection": [ + "idle", + "forward", + "reverse" + ], + "ScrollViewKeyboardDismissBehavior": [ + "manual", + "onDrag" + ], + "StackFit": [ + "loose", + "expand", + "passthrough" + ], + "StrokeCap": [ + "butt", + "round", + "square" + ], + "StrokeJoin": [ + "miter", + "round", + "bevel" + ], + "TargetPlatform": [ + "android", + "fuchsia", + "iOS", + "linux", + "macOS", + "windows" + ], + "TextAlign": [ + "left", + "right", + "center", + "justify", + "start", + "end" + ], + "TextBaseline": [ + "alphabetic", + "ideographic" + ], + "TextCapitalization": [ + "words", + "sentences", + "characters", + "none" + ], + "TextDecorationStyle": [ + "solid", + "double", + "dotted", + "dashed", + "wavy" + ], + "TextDirection": [ + "rtl", + "ltr" + ], + "TextLeadingDistribution": [ + "proportional", + "even" + ], + "TextOverflow": [ + "clip", + "fade", + "ellipsis", + "visible" + ], + "TextWidthBasis": [ + "parent", + "longestLine" + ], + "ThemeMode": [ + "system", + "light", + "dark" + ], + "TileMode": [ + "clamp", + "repeated", + "mirror", + "decal" + ], + "VerticalDirection": [ + "up", + "down" + ], + "WrapAlignment": [ + "start", + "end", + "center", + "spaceBetween", + "spaceAround", + "spaceEvenly" + ], + "WrapCrossAlignment": [ + "start", + "end", + "center" + ] +} diff --git a/packages/flutter_codec/test/golden/fixtures/gradients.json b/packages/flutter_codec/test/golden/fixtures/gradients.json new file mode 100644 index 00000000..3d7f654d --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/gradients.json @@ -0,0 +1,76 @@ +{ + "linearGradient": { + "type": "linear", + "begin": "centerLeft", + "end": "centerRight", + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": null, + "tileMode": "clamp" + }, + "linearGradientFull": { + "type": "linear", + "begin": "topLeft", + "end": "bottomRight", + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": [ + 0.0, + 1.0 + ], + "tileMode": "mirror" + }, + "radialGradient": { + "type": "radial", + "center": "center", + "radius": 0.5, + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": null, + "tileMode": "clamp", + "focal": null, + "focalRadius": 0.0 + }, + "radialGradientFocal": { + "type": "radial", + "center": "center", + "radius": 0.5, + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": null, + "tileMode": "clamp", + "focal": "topLeft", + "focalRadius": 0.25 + }, + "sweepGradient": { + "type": "sweep", + "center": "center", + "startAngle": 0.0, + "endAngle": 6.283185307179586, + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": null, + "tileMode": "clamp" + }, + "gradientUnionLinear": { + "type": "linear", + "begin": "centerLeft", + "end": "centerRight", + "colors": [ + "#FF0000", + "#0000FF" + ], + "stops": null, + "tileMode": "clamp" + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/image_providers.json b/packages/flutter_codec/test/golden/fixtures/image_providers.json new file mode 100644 index 00000000..de6794ca --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/image_providers.json @@ -0,0 +1,36 @@ +{ + "networkImageMinimal": { + "url": "https://example.com/image.png", + "scale": 1.0, + "headers": null, + "webHtmlElementStrategy": "never" + }, + "networkImage": { + "url": "https://example.com/image.png", + "scale": 2.0, + "headers": { + "Authorization": "Bearer token" + }, + "webHtmlElementStrategy": "fallback" + }, + "assetImageMinimal": { + "assetName": "assets/image.png", + "package": null + }, + "assetImage": { + "assetName": "assets/image.png", + "package": "design_system" + }, + "imageProviderNetwork": { + "type": "network", + "url": "https://example.com/image.png", + "scale": 1.0, + "headers": null, + "webHtmlElementStrategy": "never" + }, + "imageProviderAsset": { + "type": "asset", + "assetName": "assets/image.png", + "package": null + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/json_schema.json b/packages/flutter_codec/test/golden/fixtures/json_schema.json new file mode 100644 index 00000000..7a0fed6e --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/json_schema.json @@ -0,0 +1,104 @@ +{ + "alignmentCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false}]}, + "alignmentDirectionalCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]}, + "alignmentGeometryCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]}, + "assetImageCodec": {"type":"object","properties":{"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["assetName"],"additionalProperties":false,"x-transformed":true}, + "axisCodec": {"type":"string","enum":["horizontal","vertical"],"x-transformed":true}, + "axisDirectionCodec": {"type":"string","enum":["up","right","down","left"],"x-transformed":true}, + "beveledRectangleBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"additionalProperties":false,"x-transformed":true}, + "blendModeCodec": {"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true}, + "blurStyleCodec": {"type":"string","enum":["normal","solid","outer","inner"],"x-transformed":true}, + "borderCodec": {"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]}, + "borderDirectionalCodec": {"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}, + "borderRadiusCodec": {"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]}, + "borderRadiusDirectionalCodec": {"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}, + "borderRadiusGeometryCodec": {"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}, + "borderSideCodec": {"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}, + "borderStyleCodec": {"type":"string","enum":["none","solid"],"x-transformed":true}, + "boxBorderCodec": {"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}, + "boxConstraintsCodec": {"type":"object","properties":{"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true}, + "boxDecorationCodec": {"type":"object","properties":{"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"additionalProperties":false,"x-transformed":true}, + "boxFitCodec": {"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true}, + "boxHeightStyleCodec": {"type":"string","enum":["tight","max","includeLineSpacingMiddle","includeLineSpacingTop","includeLineSpacingBottom","strut"],"x-transformed":true}, + "boxShadowCodec": {"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}, + "boxShapeCodec": {"type":"string","enum":["rectangle","circle"],"x-transformed":true}, + "boxWidthStyleCodec": {"type":"string","enum":["tight","max"],"x-transformed":true}, + "brightnessCodec": {"type":"string","enum":["dark","light"],"x-transformed":true}, + "circleBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true}, + "clipCodec": {"type":"string","enum":["none","hardEdge","antiAlias","antiAliasWithSaveLayer"],"x-transformed":true}, + "colorCodec": {"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]}, + "constraintsCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}, + "containerWidgetCodec": {"type":"object","properties":{"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"alignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"padding":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"isAntiAlias":{"type":"boolean","default":true},"decoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"foregroundDecoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"width":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"constraints":{"anyOf":[{"type":"object","properties":{"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"margin":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"transform":{"anyOf":[{"type":"array","items":{"type":"number"},"minItems":16,"maxItems":16,"x-transformed":true},{"type":"null"}]},"transformAlignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"clipBehavior":{"type":"string","enum":["none","hardEdge","antiAlias","antiAliasWithSaveLayer"],"default":"none","x-transformed":true},"child":{"anyOf":[{"$ref":"#/definitions/widgetCodec"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true,"definitions":{"widgetCodec":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"container"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"alignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"padding":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"isAntiAlias":{"type":"boolean","default":true},"decoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"foregroundDecoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"width":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"constraints":{"anyOf":[{"type":"object","properties":{"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"margin":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"transform":{"anyOf":[{"type":"array","items":{"type":"number"},"minItems":16,"maxItems":16,"x-transformed":true},{"type":"null"}]},"transformAlignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"clipBehavior":{"type":"string","enum":["none","hardEdge","antiAlias","antiAliasWithSaveLayer"],"default":"none","x-transformed":true},"child":{"anyOf":[{"$ref":"#/definitions/widgetCodec"},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"text"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"data":{"type":"string"},"style":{"anyOf":[{"type":"object","properties":{"inherit":{"type":"boolean","default":true},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"backgroundColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"letterSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"wordSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"textBaseline":{"anyOf":[{"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"decoration":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]},{"type":"null"}]},"decorationColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"decorationStyle":{"anyOf":[{"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true},{"type":"null"}]},"decorationThickness":{"anyOf":[{"type":"number"},{"type":"null"}]},"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"fontFeatures":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"fontVariations":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"strutStyle":{"anyOf":[{"type":"object","properties":{"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"leading":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"forceStrutHeight":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"textAlign":{"anyOf":[{"type":"string","enum":["left","right","center","justify","start","end"],"x-transformed":true},{"type":"null"}]},"textDirection":{"anyOf":[{"type":"string","enum":["rtl","ltr"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"softWrap":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"maxLines":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}]},"semanticsLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"semanticsIdentifier":{"anyOf":[{"type":"string"},{"type":"null"}]},"textWidthBasis":{"anyOf":[{"type":"string","enum":["parent","longestLine"],"x-transformed":true},{"type":"null"}]},"textHeightBehavior":{"anyOf":[{"type":"object","properties":{"applyHeightToFirstAscent":{"type":"boolean","default":true},"applyHeightToLastDescent":{"type":"boolean","default":true},"leadingDistribution":{"type":"string","enum":["proportional","even"],"default":"proportional","x-transformed":true}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"selectionColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]}},"required":["type","data"],"additionalProperties":false,"x-transformed":true}]}}}, + "continuousRectangleBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"additionalProperties":false,"x-transformed":true}, + "crossAxisAlignmentCodec": {"type":"string","enum":["start","end","center","stretch","baseline"],"x-transformed":true}, + "decorationCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]}, + "decorationImageCodec": {"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true}, + "decorationPositionCodec": {"type":"string","enum":["background","foreground"],"x-transformed":true}, + "dragStartBehaviorCodec": {"type":"string","enum":["down","start"],"x-transformed":true}, + "edgeInsetsCodec": {"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]}, + "edgeInsetsDirectionalCodec": {"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}, + "edgeInsetsGeometryCodec": {"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]}, + "filterQualityCodec": {"type":"string","enum":["none","low","medium","high"],"x-transformed":true}, + "flexFitCodec": {"type":"string","enum":["tight","loose"],"x-transformed":true}, + "fontFeatureCodec": {"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}, + "fontStyleCodec": {"type":"string","enum":["normal","italic"],"x-transformed":true}, + "fontVariationCodec": {"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}, + "fontWeightCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]}, + "gradientCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]}, + "growthDirectionCodec": {"type":"string","enum":["forward","reverse"],"x-transformed":true}, + "hitTestBehaviorCodec": {"type":"string","enum":["deferToChild","opaque","translucent"],"x-transformed":true}, + "imageProviderCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]}, + "imageRepeatCodec": {"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"x-transformed":true}, + "keyCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]}, + "linearBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true}, + "linearBorderEdgeCodec": {"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true}, + "linearGradientCodec": {"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}, + "localeCodec": {"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true}, + "mainAxisAlignmentCodec": {"type":"string","enum":["start","end","center","spaceBetween","spaceAround","spaceEvenly"],"x-transformed":true}, + "mainAxisSizeCodec": {"type":"string","enum":["min","max"],"x-transformed":true}, + "materialTapTargetSizeCodec": {"type":"string","enum":["padded","shrinkWrap"],"x-transformed":true}, + "matrix4Codec": {"type":"array","items":{"type":"number"},"minItems":16,"maxItems":16,"x-transformed":true}, + "networkImageCodec": {"type":"object","properties":{"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["url"],"additionalProperties":false,"x-transformed":true}, + "offsetCodec": {"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"x-transformed":true}, + "paintingStyleCodec": {"type":"string","enum":["fill","stroke"],"x-transformed":true}, + "pathFillTypeCodec": {"type":"string","enum":["nonZero","evenOdd"],"x-transformed":true}, + "placeholderAlignmentCodec": {"type":"string","enum":["baseline","aboveBaseline","belowBaseline","top","bottom","middle"],"x-transformed":true}, + "radialGradientCodec": {"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}, + "radiusCodec": {"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}, + "rectCodec": {"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true}, + "roundedRectangleBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"additionalProperties":false,"x-transformed":true}, + "roundedSuperellipseBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"additionalProperties":false,"x-transformed":true}, + "scrollDirectionCodec": {"type":"string","enum":["idle","forward","reverse"],"x-transformed":true}, + "scrollViewKeyboardDismissBehaviorCodec": {"type":"string","enum":["manual","onDrag"],"x-transformed":true}, + "shadowCodec": {"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}, + "shapeBorderCodec": {"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}, + "shapeDecorationCodec": {"type":"object","properties":{"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["shape"],"additionalProperties":false,"x-transformed":true}, + "stackFitCodec": {"type":"string","enum":["loose","expand","passthrough"],"x-transformed":true}, + "stadiumBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}, + "starBorderCodec": {"type":"object","properties":{"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true}, + "strokeAlignCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}, + "strokeCapCodec": {"type":"string","enum":["butt","round","square"],"x-transformed":true}, + "strokeJoinCodec": {"type":"string","enum":["miter","round","bevel"],"x-transformed":true}, + "strutStyleCodec": {"type":"object","properties":{"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"leading":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"forceStrutHeight":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true}, + "sweepGradientCodec": {"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}, + "targetPlatformCodec": {"type":"string","enum":["android","fuchsia","iOS","linux","macOS","windows"],"x-transformed":true}, + "textAlignCodec": {"type":"string","enum":["left","right","center","justify","start","end"],"x-transformed":true}, + "textBaselineCodec": {"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true}, + "textCapitalizationCodec": {"type":"string","enum":["words","sentences","characters","none"],"x-transformed":true}, + "textDecorationCodec": {"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]}, + "textDecorationStyleCodec": {"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true}, + "textDirectionCodec": {"type":"string","enum":["rtl","ltr"],"x-transformed":true}, + "textHeightBehaviorCodec": {"type":"object","properties":{"applyHeightToFirstAscent":{"type":"boolean","default":true},"applyHeightToLastDescent":{"type":"boolean","default":true},"leadingDistribution":{"type":"string","enum":["proportional","even"],"default":"proportional","x-transformed":true}},"additionalProperties":false,"x-transformed":true}, + "textLeadingDistributionCodec": {"type":"string","enum":["proportional","even"],"x-transformed":true}, + "textOverflowCodec": {"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true}, + "textStyleCodec": {"type":"object","properties":{"inherit":{"type":"boolean","default":true},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"backgroundColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"letterSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"wordSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"textBaseline":{"anyOf":[{"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"decoration":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]},{"type":"null"}]},"decorationColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"decorationStyle":{"anyOf":[{"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true},{"type":"null"}]},"decorationThickness":{"anyOf":[{"type":"number"},{"type":"null"}]},"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"fontFeatures":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"fontVariations":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true}, + "textWidgetCodec": {"type":"object","properties":{"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"data":{"type":"string"},"style":{"anyOf":[{"type":"object","properties":{"inherit":{"type":"boolean","default":true},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"backgroundColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"letterSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"wordSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"textBaseline":{"anyOf":[{"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"decoration":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]},{"type":"null"}]},"decorationColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"decorationStyle":{"anyOf":[{"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true},{"type":"null"}]},"decorationThickness":{"anyOf":[{"type":"number"},{"type":"null"}]},"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"fontFeatures":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"fontVariations":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"strutStyle":{"anyOf":[{"type":"object","properties":{"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"leading":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"forceStrutHeight":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"textAlign":{"anyOf":[{"type":"string","enum":["left","right","center","justify","start","end"],"x-transformed":true},{"type":"null"}]},"textDirection":{"anyOf":[{"type":"string","enum":["rtl","ltr"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"softWrap":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"maxLines":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}]},"semanticsLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"semanticsIdentifier":{"anyOf":[{"type":"string"},{"type":"null"}]},"textWidthBasis":{"anyOf":[{"type":"string","enum":["parent","longestLine"],"x-transformed":true},{"type":"null"}]},"textHeightBehavior":{"anyOf":[{"type":"object","properties":{"applyHeightToFirstAscent":{"type":"boolean","default":true},"applyHeightToLastDescent":{"type":"boolean","default":true},"leadingDistribution":{"type":"string","enum":["proportional","even"],"default":"proportional","x-transformed":true}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"selectionColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]}},"required":["data"],"additionalProperties":false,"x-transformed":true}, + "textWidthBasisCodec": {"type":"string","enum":["parent","longestLine"],"x-transformed":true}, + "themeModeCodec": {"type":"string","enum":["system","light","dark"],"x-transformed":true}, + "tileModeCodec": {"type":"string","enum":["clamp","repeated","mirror","decal"],"x-transformed":true}, + "verticalDirectionCodec": {"type":"string","enum":["up","down"],"x-transformed":true}, + "webHtmlElementStrategyCodec": {"type":"string","enum":["never","fallback","prefer"],"x-transformed":true}, + "widgetCodec": {"definitions":{"widgetCodec":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"container"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"alignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"padding":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"isAntiAlias":{"type":"boolean","default":true},"decoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"foregroundDecoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"width":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"constraints":{"anyOf":[{"type":"object","properties":{"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"margin":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"transform":{"anyOf":[{"type":"array","items":{"type":"number"},"minItems":16,"maxItems":16,"x-transformed":true},{"type":"null"}]},"transformAlignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"clipBehavior":{"type":"string","enum":["none","hardEdge","antiAlias","antiAliasWithSaveLayer"],"default":"none","x-transformed":true},"child":{"anyOf":[{"$ref":"#/definitions/widgetCodec"},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"text"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"data":{"type":"string"},"style":{"anyOf":[{"type":"object","properties":{"inherit":{"type":"boolean","default":true},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"backgroundColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"letterSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"wordSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"textBaseline":{"anyOf":[{"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"decoration":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]},{"type":"null"}]},"decorationColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"decorationStyle":{"anyOf":[{"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true},{"type":"null"}]},"decorationThickness":{"anyOf":[{"type":"number"},{"type":"null"}]},"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"fontFeatures":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"fontVariations":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"strutStyle":{"anyOf":[{"type":"object","properties":{"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"leading":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"forceStrutHeight":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"textAlign":{"anyOf":[{"type":"string","enum":["left","right","center","justify","start","end"],"x-transformed":true},{"type":"null"}]},"textDirection":{"anyOf":[{"type":"string","enum":["rtl","ltr"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"softWrap":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"maxLines":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}]},"semanticsLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"semanticsIdentifier":{"anyOf":[{"type":"string"},{"type":"null"}]},"textWidthBasis":{"anyOf":[{"type":"string","enum":["parent","longestLine"],"x-transformed":true},{"type":"null"}]},"textHeightBehavior":{"anyOf":[{"type":"object","properties":{"applyHeightToFirstAscent":{"type":"boolean","default":true},"applyHeightToLastDescent":{"type":"boolean","default":true},"leadingDistribution":{"type":"string","enum":["proportional","even"],"default":"proportional","x-transformed":true}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"selectionColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]}},"required":["type","data"],"additionalProperties":false,"x-transformed":true}]}},"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"container"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"alignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"padding":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"isAntiAlias":{"type":"boolean","default":true},"decoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"foregroundDecoration":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"border":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"right":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"left":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"top":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"end":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"bottom":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"borderRadius":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"boxShadow":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"backgroundBlendMode":{"anyOf":[{"type":"string","enum":["clear","src","dst","srcOver","dstOver","srcIn","dstIn","srcOut","dstOut","srcATop","dstATop","xor","plus","modulate","screen","overlay","darken","lighten","colorDodge","colorBurn","hardLight","softLight","difference","exclusion","multiply","hue","saturation","color","luminosity"],"x-transformed":true},{"type":"null"}]},"shape":{"type":"string","enum":["rectangle","circle"],"default":"rectangle","x-transformed":true}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"shape"},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"image":{"anyOf":[{"type":"object","properties":{"image":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"network"},"url":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0,"default":1.0},"headers":{"anyOf":[{"type":"object","additionalProperties":true,"x-transformed":true},{"type":"null"}]},"webHtmlElementStrategy":{"type":"string","enum":["never","fallback","prefer"],"default":"never","x-transformed":true}},"required":["type","url"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"asset"},"assetName":{"type":"string","minLength":1},"package":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","assetName"],"additionalProperties":false,"x-transformed":true}]},"fit":{"anyOf":[{"type":"string","enum":["fill","contain","cover","fitWidth","fitHeight","none","scaleDown"],"x-transformed":true},{"type":"null"}]},"alignment":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"centerSlice":{"anyOf":[{"type":"object","properties":{"left":{"type":"number"},"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"}},"required":["left","top","right","bottom"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"repeat":{"type":"string","enum":["repeat","repeatX","repeatY","noRepeat"],"default":"noRepeat","x-transformed":true},"matchTextDirection":{"type":"boolean","default":false},"scale":{"type":"number","default":1.0},"opacity":{"type":"number","minimum":0,"maximum":1,"default":1.0},"filterQuality":{"type":"string","enum":["none","low","medium","high"],"default":"medium","x-transformed":true},"invertColors":{"type":"boolean","default":false},"isAntiAlias":{"type":"boolean","default":false}},"required":["image"],"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"gradient":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"linear"},"begin":{"default":"centerLeft","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"end":{"default":"centerRight","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"radial"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"radius":{"type":"number","minimum":0,"default":0.5},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true},"focal":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"focalRadius":{"type":"number","minimum":0,"default":0.0}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"sweep"},"center":{"default":"center","x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},"startAngle":{"type":"number","default":0.0},"endAngle":{"type":"number","default":6.283185307179586},"colors":{"type":"array","items":{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"minItems":2},"stops":{"anyOf":[{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},{"type":"null"}]},"tileMode":{"type":"string","enum":["clamp","repeated","mirror","decal"],"default":"clamp","x-transformed":true}},"required":["type","colors"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0},"spreadRadius":{"type":"number","default":0.0},"blurStyle":{"type":"string","enum":["normal","solid","outer","inner"],"default":"normal","x-transformed":true}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"shape":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"eccentricity":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"stadium"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"beveledRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"continuousRectangle"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"roundedSuperellipse"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"borderRadius":{"default":0.0,"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},{"type":"object","properties":{"topLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomLeft":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomRight":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false}]},{"type":"object","properties":{"topStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"topEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomStart":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]},"bottomEnd":{"default":0.0,"x-transformed":true,"anyOf":[{"type":"number","minimum":0},{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0}},"required":["x","y"],"additionalProperties":false}]}},"additionalProperties":false,"x-transformed":true}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"star"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"points":{"type":"number","minimum":2,"default":5},"innerRadiusRatio":{"type":"number","minimum":0,"maximum":1,"default":0.4},"pointRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"valleyRounding":{"type":"number","minimum":0,"maximum":1,"default":0.0},"rotation":{"type":"number","default":0.0},"squash":{"type":"number","minimum":0,"maximum":1,"default":0.0}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"linear"},"side":{"default":"none","x-transformed":true,"anyOf":[{"type":"string","const":"none"},{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"width":{"type":"number","minimum":0,"default":1.0},"style":{"type":"string","enum":["none","solid"],"default":"solid","x-transformed":true},"strokeAlign":{"default":"inside","x-transformed":true,"anyOf":[{"type":"string","enum":["inside","center","outside"],"x-transformed":true},{"type":"number"}]}},"additionalProperties":false}]},"start":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"end":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"top":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"bottom":{"anyOf":[{"type":"object","properties":{"size":{"type":"number","minimum":0,"maximum":1,"default":1.0},"alignment":{"type":"number","minimum":-1,"maximum":1,"default":0.0}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true}]}},"required":["type","shape"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"width":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"constraints":{"anyOf":[{"type":"object","properties":{"minWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxWidth":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"minHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"maxHeight":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"margin":{"anyOf":[{"x-transformed":true,"anyOf":[{"x-transformed":true,"anyOf":[{"type":"number"},{"type":"object","properties":{"left":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"right":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false}]},{"type":"object","properties":{"start":{"type":"number","default":0.0},"top":{"type":"number","default":0.0},"end":{"type":"number","default":0.0},"bottom":{"type":"number","default":0.0}},"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"transform":{"anyOf":[{"type":"array","items":{"type":"number"},"minItems":16,"maxItems":16,"x-transformed":true},{"type":"null"}]},"transformAlignment":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"],"x-transformed":true},{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false},{"type":"string","enum":["topStart","topCenter","topEnd","centerStart","center","centerEnd","bottomStart","bottomCenter","bottomEnd"],"x-transformed":true},{"type":"object","properties":{"start":{"type":"number"},"y":{"type":"number"}},"required":["start","y"],"additionalProperties":false}]},{"type":"null"}]},"clipBehavior":{"type":"string","enum":["none","hardEdge","antiAlias","antiAliasWithSaveLayer"],"default":"none","x-transformed":true},"child":{"anyOf":[{"$ref":"#/definitions/widgetCodec"},{"type":"null"}]}},"required":["type"],"additionalProperties":false,"x-transformed":true},{"type":"object","properties":{"type":{"type":"string","const":"text"},"key":{"anyOf":[{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"value"},"valueType":{"type":"string","enum":["string","int","double","bool"],"x-transformed":true},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"}]}},"required":["type","valueType","value"],"additionalProperties":false,"x-transformed":true}]},{"type":"null"}]},"data":{"type":"string"},"style":{"anyOf":[{"type":"object","properties":{"inherit":{"type":"boolean","default":true},"color":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"backgroundColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"letterSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"wordSpacing":{"anyOf":[{"type":"number"},{"type":"null"}]},"textBaseline":{"anyOf":[{"type":"string","enum":["alphabetic","ideographic"],"x-transformed":true},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"shadows":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"default":"#000000","x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},"offset":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"additionalProperties":false,"default":{"x":0.0,"y":0.0},"x-transformed":true},"blurRadius":{"type":"number","minimum":0,"default":0.0}},"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"decoration":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true},{"type":"array","items":{"type":"string","enum":["none","underline","overline","lineThrough"],"x-transformed":true}}]},{"type":"null"}]},"decorationColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]},"decorationStyle":{"anyOf":[{"type":"string","enum":["solid","double","dotted","dashed","wavy"],"x-transformed":true},{"type":"null"}]},"decorationThickness":{"anyOf":[{"type":"number"},{"type":"null"}]},"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"fontFeatures":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"feature":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"integer","minimum":0,"default":1}},"required":["feature"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]},"fontVariations":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"axis":{"type":"string","pattern":"^[\\x20-\\x7E]{4}$"},"value":{"type":"number","minimum":-32768,"exclusiveMaximum":32768}},"required":["axis","value"],"additionalProperties":false,"x-transformed":true}},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"strutStyle":{"anyOf":[{"type":"object","properties":{"fontFamily":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontFamilyFallback":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"fontSize":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"leadingDistribution":{"anyOf":[{"type":"string","enum":["proportional","even"],"x-transformed":true},{"type":"null"}]},"leading":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"fontWeight":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","enum":["w100","w200","w300","w400","w500","w600","w700","w800","w900","normal","bold"],"x-transformed":true},{"type":"integer","minimum":1,"maximum":1000}]},{"type":"null"}]},"fontStyle":{"anyOf":[{"type":"string","enum":["normal","italic"],"x-transformed":true},{"type":"null"}]},"forceStrutHeight":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"textAlign":{"anyOf":[{"type":"string","enum":["left","right","center","justify","start","end"],"x-transformed":true},{"type":"null"}]},"textDirection":{"anyOf":[{"type":"string","enum":["rtl","ltr"],"x-transformed":true},{"type":"null"}]},"locale":{"anyOf":[{"type":"string","pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$","x-transformed":true},{"type":"null"}]},"softWrap":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overflow":{"anyOf":[{"type":"string","enum":["clip","fade","ellipsis","visible"],"x-transformed":true},{"type":"null"}]},"maxLines":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}]},"semanticsLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"semanticsIdentifier":{"anyOf":[{"type":"string"},{"type":"null"}]},"textWidthBasis":{"anyOf":[{"type":"string","enum":["parent","longestLine"],"x-transformed":true},{"type":"null"}]},"textHeightBehavior":{"anyOf":[{"type":"object","properties":{"applyHeightToFirstAscent":{"type":"boolean","default":true},"applyHeightToLastDescent":{"type":"boolean","default":true},"leadingDistribution":{"type":"string","enum":["proportional","even"],"default":"proportional","x-transformed":true}},"additionalProperties":false,"x-transformed":true},{"type":"null"}]},"selectionColor":{"anyOf":[{"x-transformed":true,"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"string","pattern":"^#[0-9A-Fa-f]{8}$"},{"type":"string","pattern":"^rgb\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*\\)$"},{"type":"string","pattern":"^rgba\\(\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\s*,\\s*(?:0|1|0?\\.\\d+|1\\.0+)\\s*\\)$"}]},{"type":"null"}]}},"required":["type","data"],"additionalProperties":false,"x-transformed":true}]}, + "wrapAlignmentCodec": {"type":"string","enum":["start","end","center","spaceBetween","spaceAround","spaceEvenly"],"x-transformed":true}, + "wrapCrossAlignmentCodec": {"type":"string","enum":["start","end","center"],"x-transformed":true} +} diff --git a/packages/flutter_codec/test/golden/fixtures/primitives.json b/packages/flutter_codec/test/golden/fixtures/primitives.json new file mode 100644 index 00000000..c6de071a --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/primitives.json @@ -0,0 +1,128 @@ +{ + "color": "#2196F3", + "colorTranslucent": "#802196F3", + "offset": { + "x": 12.0, + "y": 4.5 + }, + "radiusCircular": 8.0, + "radiusElliptical": { + "x": 8.0, + "y": 12.5 + }, + "rect": { + "left": 1.0, + "top": 2.0, + "right": 30.0, + "bottom": 40.0 + }, + "alignmentNamed": "topLeft", + "alignmentXY": { + "x": 0.25, + "y": -0.5 + }, + "alignmentDirectional": { + "start": 0.25, + "y": -0.5 + }, + "alignmentGeometryDirectional": { + "start": 0.25, + "y": -0.5 + }, + "borderRadiusCircular": 8.0, + "borderRadiusPerCorner": { + "topLeft": 8.0, + "topRight": 0.0, + "bottomLeft": 0.0, + "bottomRight": 0.0 + }, + "borderRadiusDirectional": { + "topStart": 8.0, + "topEnd": 0.0, + "bottomStart": 0.0, + "bottomEnd": 0.0 + }, + "borderRadiusGeometryDirectional": { + "topStart": 8.0, + "topEnd": 8.0, + "bottomStart": 8.0, + "bottomEnd": 8.0 + }, + "edgeInsetsAll": 16.0, + "edgeInsetsOnly": { + "left": 8.0, + "top": 4.0, + "right": 0.0, + "bottom": 0.0 + }, + "edgeInsetsDirectional": { + "start": 8.0, + "top": 0.0, + "end": 0.0, + "bottom": 0.0 + }, + "edgeInsetsGeometryDirectional": { + "start": 8.0, + "top": 0.0, + "end": 0.0, + "bottom": 0.0 + }, + "matrix4Identity": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "matrix4Transformed": [ + 2.0, + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 10.0, + 20.0, + 30.0, + 1.0 + ], + "locale": "en-US", + "localeWithScript": "zh-Hans-CN", + "fontFeature": { + "feature": "smcp", + "value": 1 + }, + "fontVariation": { + "axis": "wght", + "value": 600.0 + }, + "fontWeightNamed": "w600", + "fontWeightVariable": 550, + "textDecorationAtomic": "underline", + "textDecorationCombined": [ + "underline", + "lineThrough" + ], + "textHeightBehavior": { + "applyHeightToFirstAscent": false, + "applyHeightToLastDescent": true, + "leadingDistribution": "even" + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/shadows.json b/packages/flutter_codec/test/golden/fixtures/shadows.json new file mode 100644 index 00000000..beb075cd --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/shadows.json @@ -0,0 +1,38 @@ +{ + "shadowDefault": { + "color": "#000000", + "offset": { + "x": 0.0, + "y": 0.0 + }, + "blurRadius": 0.0 + }, + "shadow": { + "color": "#FF0000", + "offset": { + "x": 2.0, + "y": 4.0 + }, + "blurRadius": 6.0 + }, + "boxShadowDefault": { + "color": "#000000", + "offset": { + "x": 0.0, + "y": 0.0 + }, + "blurRadius": 0.0, + "spreadRadius": 0.0, + "blurStyle": "normal" + }, + "boxShadow": { + "color": "#FF0000", + "offset": { + "x": 2.0, + "y": 4.0 + }, + "blurRadius": 6.0, + "spreadRadius": 1.0, + "blurStyle": "outer" + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/shape_borders.json b/packages/flutter_codec/test/golden/fixtures/shape_borders.json new file mode 100644 index 00000000..9fb8172d --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/shape_borders.json @@ -0,0 +1,95 @@ +{ + "circleBorder": { + "side": "none", + "eccentricity": 0.0 + }, + "circleBorderSided": { + "side": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "eccentricity": 0.5 + }, + "stadiumBorder": { + "side": { + "color": "#FF0000", + "width": 3.0, + "style": "solid", + "strokeAlign": "inside" + } + }, + "roundedRectangleBorder": { + "side": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "borderRadius": 12.0 + }, + "beveledRectangleBorder": { + "side": "none", + "borderRadius": 4.0 + }, + "continuousRectangleBorder": { + "side": "none", + "borderRadius": 4.0 + }, + "roundedSuperellipseBorder": { + "side": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "borderRadius": 8.0 + }, + "starBorder": { + "side": "none", + "points": 7.0, + "innerRadiusRatio": 0.3, + "pointRounding": 0.0, + "valleyRounding": 0.0, + "rotation": 0.0, + "squash": 0.0 + }, + "linearBorderEdge": { + "size": 0.5, + "alignment": -0.25 + }, + "linearBorder": { + "side": { + "color": "#FF0000", + "width": 2.0, + "style": "solid", + "strokeAlign": "inside" + }, + "start": { + "size": 0.5, + "alignment": 0.0 + }, + "end": null, + "top": { + "size": 1.0, + "alignment": -1.0 + }, + "bottom": null + }, + "shapeBorderStar": { + "type": "star", + "side": "none", + "points": 5.0, + "innerRadiusRatio": 0.4, + "pointRounding": 0.0, + "valleyRounding": 0.0, + "rotation": 0.0, + "squash": 0.0 + }, + "shapeBorderOval": { + "type": "circle", + "side": "none", + "eccentricity": 1.0 + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/text.json b/packages/flutter_codec/test/golden/fixtures/text.json new file mode 100644 index 00000000..e7925000 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/text.json @@ -0,0 +1,118 @@ +{ + "textStyleDefault": { + "inherit": true, + "color": null, + "backgroundColor": null, + "fontSize": null, + "fontWeight": null, + "fontStyle": null, + "letterSpacing": null, + "wordSpacing": null, + "textBaseline": null, + "height": null, + "leadingDistribution": null, + "locale": null, + "shadows": null, + "decoration": null, + "decorationColor": null, + "decorationStyle": null, + "decorationThickness": null, + "fontFamily": null, + "fontFamilyFallback": null, + "package": null, + "overflow": null, + "fontFeatures": null, + "fontVariations": null + }, + "textStyleFull": { + "inherit": false, + "color": "#2196F3", + "backgroundColor": "#FFFDE7", + "fontSize": 18.0, + "fontWeight": "w700", + "fontStyle": "italic", + "letterSpacing": 0.25, + "wordSpacing": 1.5, + "textBaseline": "alphabetic", + "height": 1.3, + "leadingDistribution": "even", + "locale": "zh-CN", + "shadows": [ + { + "color": "#55000000", + "offset": { + "x": 1.0, + "y": 2.0 + }, + "blurRadius": 3.0 + } + ], + "decoration": null, + "decorationColor": "#FF0000", + "decorationStyle": "dashed", + "decorationThickness": 2.0, + "fontFamily": "Inter", + "fontFamilyFallback": [ + "Roboto", + "Arial" + ], + "package": "my_package", + "overflow": "ellipsis", + "fontFeatures": [ + { + "feature": "smcp", + "value": 1 + }, + { + "feature": "cv01", + "value": 3 + } + ], + "fontVariations": [ + { + "axis": "wght", + "value": 500.0 + }, + { + "axis": "slnt", + "value": -10.0 + } + ] + }, + "strutStyleDefault": { + "fontFamily": null, + "fontFamilyFallback": null, + "package": null, + "fontSize": null, + "height": null, + "leadingDistribution": null, + "leading": null, + "fontWeight": null, + "fontStyle": null, + "forceStrutHeight": null + }, + "strutStyleFull": { + "fontFamily": "Roboto", + "fontFamilyFallback": null, + "package": null, + "fontSize": 16.0, + "height": 1.5, + "leadingDistribution": null, + "leading": null, + "fontWeight": "w700", + "fontStyle": null, + "forceStrutHeight": false + }, + "strutStylePackage": { + "fontFamily": "Roboto", + "fontFamilyFallback": null, + "package": "my_pkg", + "fontSize": null, + "height": null, + "leadingDistribution": null, + "leading": null, + "fontWeight": null, + "fontStyle": null, + "forceStrutHeight": null + } +} diff --git a/packages/flutter_codec/test/golden/fixtures/widgets.json b/packages/flutter_codec/test/golden/fixtures/widgets.json new file mode 100644 index 00000000..088f8f33 --- /dev/null +++ b/packages/flutter_codec/test/golden/fixtures/widgets.json @@ -0,0 +1,241 @@ +{ + "containerDefault": { + "key": null, + "alignment": null, + "padding": null, + "color": null, + "isAntiAlias": true, + "decoration": null, + "foregroundDecoration": null, + "width": null, + "height": null, + "constraints": null, + "margin": null, + "transform": null, + "transformAlignment": null, + "clipBehavior": "none", + "child": null + }, + "containerFull": { + "key": { + "type": "value", + "valueType": "string", + "value": "shell" + }, + "alignment": "centerRight", + "padding": 8.0, + "color": null, + "isAntiAlias": false, + "decoration": { + "type": "box", + "color": "#E0F2F1", + "image": null, + "border": null, + "borderRadius": 6.0, + "boxShadow": null, + "gradient": null, + "backgroundBlendMode": null, + "shape": "rectangle" + }, + "foregroundDecoration": { + "type": "box", + "color": null, + "image": null, + "border": { + "color": "#004D40", + "width": 1.0, + "style": "solid", + "strokeAlign": "inside" + }, + "borderRadius": null, + "boxShadow": null, + "gradient": null, + "backgroundBlendMode": null, + "shape": "rectangle" + }, + "width": null, + "height": null, + "constraints": { + "minWidth": 10.0, + "maxWidth": 100.0, + "minHeight": 20.0, + "maxHeight": 200.0 + }, + "margin": { + "start": 2.0, + "top": 0.0, + "end": 4.0, + "bottom": 0.0 + }, + "transform": [ + 2.0, + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 10.0, + 20.0, + 30.0, + 1.0 + ], + "transformAlignment": "bottomLeft", + "clipBehavior": "antiAlias", + "child": { + "type": "container", + "key": null, + "alignment": null, + "padding": null, + "color": "#FF0000", + "isAntiAlias": true, + "decoration": null, + "foregroundDecoration": null, + "width": null, + "height": null, + "constraints": null, + "margin": null, + "transform": null, + "transformAlignment": null, + "clipBehavior": "none", + "child": null + } + }, + "textWidgetDefault": { + "key": null, + "data": "hello", + "style": null, + "strutStyle": null, + "textAlign": null, + "textDirection": null, + "locale": null, + "softWrap": null, + "overflow": null, + "maxLines": null, + "semanticsLabel": null, + "semanticsIdentifier": null, + "textWidthBasis": null, + "textHeightBehavior": null, + "selectionColor": null + }, + "textWidgetFull": { + "key": { + "type": "value", + "valueType": "string", + "value": "copy" + }, + "data": "hello", + "style": { + "inherit": true, + "color": "#102030", + "backgroundColor": null, + "fontSize": 18.0, + "fontWeight": "w600", + "fontStyle": null, + "letterSpacing": null, + "wordSpacing": null, + "textBaseline": null, + "height": null, + "leadingDistribution": null, + "locale": null, + "shadows": null, + "decoration": null, + "decorationColor": null, + "decorationStyle": null, + "decorationThickness": null, + "fontFamily": null, + "fontFamilyFallback": null, + "package": null, + "overflow": null, + "fontFeatures": null, + "fontVariations": null + }, + "strutStyle": { + "fontFamily": null, + "fontFamilyFallback": null, + "package": null, + "fontSize": 18.0, + "height": 1.25, + "leadingDistribution": null, + "leading": null, + "fontWeight": null, + "fontStyle": null, + "forceStrutHeight": null + }, + "textAlign": "center", + "textDirection": "rtl", + "locale": "en-US", + "softWrap": false, + "overflow": "ellipsis", + "maxLines": 2, + "semanticsLabel": "label", + "semanticsIdentifier": "copy-id", + "textWidthBasis": "longestLine", + "textHeightBehavior": { + "applyHeightToFirstAscent": false, + "applyHeightToLastDescent": true, + "leadingDistribution": "proportional" + }, + "selectionColor": "#330000FF" + }, + "widgetUnionContainerWithText": { + "type": "container", + "key": null, + "alignment": null, + "padding": 8.0, + "color": null, + "isAntiAlias": true, + "decoration": null, + "foregroundDecoration": null, + "width": null, + "height": null, + "constraints": null, + "margin": null, + "transform": null, + "transformAlignment": null, + "clipBehavior": "none", + "child": { + "type": "text", + "key": null, + "data": "hi", + "style": null, + "strutStyle": null, + "textAlign": "center", + "textDirection": null, + "locale": null, + "softWrap": null, + "overflow": null, + "maxLines": null, + "semanticsLabel": null, + "semanticsIdentifier": null, + "textWidthBasis": null, + "textHeightBehavior": null, + "selectionColor": null + } + }, + "keyString": { + "type": "value", + "valueType": "string", + "value": "foo" + }, + "keyInt": { + "type": "value", + "valueType": "int", + "value": 1 + }, + "keyDouble": { + "type": "value", + "valueType": "double", + "value": 1.5 + }, + "keyBool": { + "type": "value", + "valueType": "bool", + "value": true + } +} diff --git a/packages/flutter_codec/test/golden/golden_test.dart b/packages/flutter_codec/test/golden/golden_test.dart new file mode 100644 index 00000000..63e4a169 --- /dev/null +++ b/packages/flutter_codec/test/golden/golden_test.dart @@ -0,0 +1,1426 @@ +// Golden / fixture coverage for every public codec. +// +// For each codec this test: +// 1. Encodes a representative typed value and records the canonical JSON it +// produces in a per-family fixture under `test/golden/fixtures/*.json`. +// Those files are committed so the exact wire shape of every type is +// reviewable in one place and regressions surface as a golden diff. +// 2. Reads that JSON back, parses it, and asserts the round-trip: +// - value-equality (`==`) for the painting/rendering value types, +// - JSON stability (`encode(parse(json)) == json`) for the widget types +// that intentionally have no value equality, and +// - the documented narrowing for the few lossy types. +// +// To regenerate the fixtures after an intentional change: +// UPDATE_GOLDENS=true flutter test test/golden/golden_test.dart +import 'dart:convert'; +import 'dart:io'; +import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, Shadow; + +import 'package:ack/ack.dart' show CodecSchema; +import 'package:flutter/gestures.dart' show DragStartBehavior; +import 'package:flutter/material.dart' show MaterialTapTargetSize, ThemeMode; +import 'package:flutter/rendering.dart' + show + CrossAxisAlignment, + DecorationPosition, + FlexFit, + GrowthDirection, + HitTestBehavior, + MainAxisAlignment, + MainAxisSize, + ScrollDirection, + StackFit, + WrapAlignment, + WrapCrossAlignment; +import 'package:flutter/services.dart' show TextCapitalization; +import 'package:flutter/widgets.dart'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +typedef _Json = Object?; + +const _fixturesDir = 'test/golden/fixtures'; +const _encoder = JsonEncoder.withIndent(' '); +final _update = Platform.environment['UPDATE_GOLDENS'] == 'true'; + +const _redBlue = [Color(0xFFFF0000), Color(0xFF0000FF)]; + +void main() { + for (final family in _families) { + group('golden/${family.file}', () { + final path = '$_fixturesDir/${family.file}.json'; + + test('encodes every type to the recorded fixture', () { + final actual = {}; + for (final fixture in family.cases) { + final encoded = fixture.encode(); + expect( + jsonSafetyViolation(encoded), + isNull, + reason: '${fixture.name} produced non-JSON-safe output', + ); + actual[fixture.name] = encoded; + } + + final actualText = _encoder.convert(actual); + final file = File(path); + if (_update) { + file.parent.createSync(recursive: true); + file.writeAsStringSync('$actualText\n'); + return; + } + + expect( + file.existsSync(), + isTrue, + reason: + 'Missing golden $path. Generate it with ' + 'UPDATE_GOLDENS=true flutter test test/golden/golden_test.dart', + ); + expect( + actualText, + file.readAsStringSync().trimRight(), + reason: + 'Golden drift in ${family.file}.json. If this change is ' + 'intentional, regenerate with UPDATE_GOLDENS=true.', + ); + }); + + for (final fixture in family.cases) { + test('${fixture.name} parses back from its JSON', () { + if (_update) return; + final golden = + jsonDecode(File(path).readAsStringSync()) as Map; + expect( + golden.containsKey(fixture.name), + isTrue, + reason: 'No golden entry for ${fixture.name}', + ); + final json = golden[fixture.name]; + expectJsonSafe(json); + fixture.verify(json); + }); + } + }); + } +} + +/// A single codec fixture: a representative value to [encode] and a [verify] +/// callback that checks the parsed-back result against the recorded JSON. +final class _Case { + _Case(this.name, this.encode, this.verify); + + final String name; + final _Json Function() encode; + final void Function(_Json json) verify; +} + +final class _Family { + _Family(this.file, this.cases); + + final String file; + final List<_Case> cases; +} + +/// Builds a fixture for an enum codec: the recorded JSON is the full, ordered +/// list of wire names the codec accepts/emits, and every name round-trips. +_Case _enumCase( + String name, + CodecSchema codec, + List values, +) { + return _Case(name, () => [for (final value in values) codec.encode(value)], ( + json, + ) { + final names = (json! as List).cast(); + expect( + names, + [for (final value in values) value.name], + reason: '$name wire vocabulary drifted from its enum declaration order', + ); + for (final wireName in names) { + expect(codec.parse(wireName)!.name, wireName); + } + }); +} + +final _families = <_Family>[ + _Family('primitives', _primitives), + _Family('borders', _borders), + _Family('shape_borders', _shapeBorders), + _Family('gradients', _gradients), + _Family('shadows', _shadows), + _Family('image_providers', _imageProviders), + _Family('decorations', _decorations), + _Family('decoration_image', _decorationImage), + _Family('constraints', _constraints), + _Family('text', _text), + _Family('widgets', _widgets), + _Family('enums', _enums), +]; + +// --- primitives ------------------------------------------------------------- + +final _primitives = <_Case>[ + _Case( + 'color', + () => colorCodec.encode(const Color(0xFF2196F3)), + (j) => expect(colorCodec.parse(j), const Color(0xFF2196F3)), + ), + _Case( + 'colorTranslucent', + () => colorCodec.encode(const Color(0x802196F3)), + (j) => expect(colorCodec.parse(j), const Color(0x802196F3)), + ), + _Case( + 'offset', + () => offsetCodec.encode(const Offset(12, 4.5)), + (j) => expect(offsetCodec.parse(j), const Offset(12, 4.5)), + ), + _Case( + 'radiusCircular', + () => radiusCodec.encode(const Radius.circular(8)), + (j) => expect(radiusCodec.parse(j), const Radius.circular(8)), + ), + _Case( + 'radiusElliptical', + () => radiusCodec.encode(const Radius.elliptical(8, 12.5)), + (j) => expect(radiusCodec.parse(j), const Radius.elliptical(8, 12.5)), + ), + _Case( + 'rect', + () => rectCodec.encode(const Rect.fromLTRB(1, 2, 30, 40)), + (j) => expect(rectCodec.parse(j), const Rect.fromLTRB(1, 2, 30, 40)), + ), + _Case( + 'alignmentNamed', + () => alignmentCodec.encode(Alignment.topLeft), + (j) => expect(alignmentCodec.parse(j), Alignment.topLeft), + ), + _Case( + 'alignmentXY', + () => alignmentCodec.encode(const Alignment(0.25, -0.5)), + (j) => expect(alignmentCodec.parse(j), const Alignment(0.25, -0.5)), + ), + _Case( + 'alignmentDirectional', + () => alignmentDirectionalCodec.encode( + const AlignmentDirectional(0.25, -0.5), + ), + (j) => expect( + alignmentDirectionalCodec.parse(j), + const AlignmentDirectional(0.25, -0.5), + ), + ), + _Case( + 'alignmentGeometryDirectional', + () => alignmentGeometryCodec.encode(const AlignmentDirectional(0.25, -0.5)), + (j) { + final parsed = alignmentGeometryCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const AlignmentDirectional(0.25, -0.5)); + }, + ), + _Case( + 'borderRadiusCircular', + () => borderRadiusCodec.encode(BorderRadius.circular(8)), + (j) => expect(borderRadiusCodec.parse(j), BorderRadius.circular(8)), + ), + _Case( + 'borderRadiusPerCorner', + () => borderRadiusCodec.encode( + const BorderRadius.only(topLeft: Radius.circular(8)), + ), + (j) => expect( + borderRadiusCodec.parse(j), + const BorderRadius.only(topLeft: Radius.circular(8)), + ), + ), + _Case( + 'borderRadiusDirectional', + () => borderRadiusDirectionalCodec.encode( + const BorderRadiusDirectional.only(topStart: Radius.circular(8)), + ), + (j) => expect( + borderRadiusDirectionalCodec.parse(j), + const BorderRadiusDirectional.only(topStart: Radius.circular(8)), + ), + ), + _Case( + 'borderRadiusGeometryDirectional', + () => borderRadiusGeometryCodec.encode( + BorderRadiusDirectional.all(const Radius.circular(8)), + ), + (j) { + final parsed = borderRadiusGeometryCodec.parse(j); + expect(parsed, isA()); + expect(parsed, BorderRadiusDirectional.all(const Radius.circular(8))); + }, + ), + _Case( + 'edgeInsetsAll', + () => edgeInsetsCodec.encode(const EdgeInsets.all(16)), + (j) => expect(edgeInsetsCodec.parse(j), const EdgeInsets.all(16)), + ), + _Case( + 'edgeInsetsOnly', + () => edgeInsetsCodec.encode(const EdgeInsets.only(left: 8, top: 4)), + (j) => expect( + edgeInsetsCodec.parse(j), + const EdgeInsets.only(left: 8, top: 4), + ), + ), + _Case( + 'edgeInsetsDirectional', + () => edgeInsetsDirectionalCodec.encode( + const EdgeInsetsDirectional.only(start: 8), + ), + (j) => expect( + edgeInsetsDirectionalCodec.parse(j), + const EdgeInsetsDirectional.only(start: 8), + ), + ), + _Case( + 'edgeInsetsGeometryDirectional', + () => edgeInsetsGeometryCodec.encode( + const EdgeInsetsDirectional.only(start: 8), + ), + (j) { + final parsed = edgeInsetsGeometryCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const EdgeInsetsDirectional.only(start: 8)); + }, + ), + _Case( + 'matrix4Identity', + () => matrix4Codec.encode(Matrix4.identity()), + (j) => expect(matrix4Codec.parse(j), Matrix4.identity()), + ), + _Case( + 'matrix4Transformed', + () => matrix4Codec.encode(_transformedMatrix()), + (j) => expect(matrix4Codec.parse(j), _transformedMatrix()), + ), + _Case( + 'locale', + () => localeCodec.encode(const Locale('en', 'US')), + (j) => expect(localeCodec.parse(j), const Locale('en', 'US')), + ), + _Case( + 'localeWithScript', + () => localeCodec.encode( + const Locale.fromSubtags( + languageCode: 'zh', + scriptCode: 'Hans', + countryCode: 'CN', + ), + ), + (j) => expect( + localeCodec.parse(j), + const Locale.fromSubtags( + languageCode: 'zh', + scriptCode: 'Hans', + countryCode: 'CN', + ), + ), + ), + _Case( + 'fontFeature', + () => fontFeatureCodec.encode(const FontFeature('smcp', 1)), + (j) => expect(fontFeatureCodec.parse(j), const FontFeature('smcp', 1)), + ), + _Case( + 'fontVariation', + () => fontVariationCodec.encode(const FontVariation('wght', 600)), + (j) => + expect(fontVariationCodec.parse(j), const FontVariation('wght', 600)), + ), + _Case( + 'fontWeightNamed', + () => fontWeightCodec.encode(FontWeight.w600), + (j) => expect(fontWeightCodec.parse(j), FontWeight.w600), + ), + _Case( + 'fontWeightVariable', + () => fontWeightCodec.encode(const FontWeight(550)), + (j) => expect(fontWeightCodec.parse(j), const FontWeight(550)), + ), + _Case( + 'textDecorationAtomic', + () => textDecorationCodec.encode(TextDecoration.underline), + (j) => expect(textDecorationCodec.parse(j), TextDecoration.underline), + ), + _Case( + 'textDecorationCombined', + () => textDecorationCodec.encode( + TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.lineThrough, + ]), + ), + (j) => expect( + textDecorationCodec.parse(j), + TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.lineThrough, + ]), + ), + ), + _Case( + 'textHeightBehavior', + () => textHeightBehaviorCodec.encode( + const TextHeightBehavior( + applyHeightToFirstAscent: false, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + (j) => expect( + textHeightBehaviorCodec.parse(j), + const TextHeightBehavior( + applyHeightToFirstAscent: false, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ), +]; + +// --- borders ---------------------------------------------------------------- + +final _borders = <_Case>[ + _Case( + 'strokeAlignNamed', + () => strokeAlignCodec.encode(BorderSide.strokeAlignOutside), + (j) => expect(strokeAlignCodec.parse(j), BorderSide.strokeAlignOutside), + ), + _Case( + 'strokeAlignNumeric', + () => strokeAlignCodec.encode(0.5), + (j) => expect(strokeAlignCodec.parse(j), 0.5), + ), + _Case( + 'borderSideNone', + () => borderSideCodec.encode(BorderSide.none), + (j) => expect(borderSideCodec.parse(j), BorderSide.none), + ), + _Case( + 'borderSideFull', + () => borderSideCodec.encode( + const BorderSide( + color: Color(0xFFFF0000), + width: 2, + style: BorderStyle.none, + strokeAlign: BorderSide.strokeAlignCenter, + ), + ), + (j) => expect( + borderSideCodec.parse(j), + const BorderSide( + color: Color(0xFFFF0000), + width: 2, + style: BorderStyle.none, + strokeAlign: BorderSide.strokeAlignCenter, + ), + ), + ), + _Case( + 'borderNone', + () => borderCodec.encode(const Border()), + (j) => expect(borderCodec.parse(j), const Border()), + ), + _Case( + 'borderUniform', + () => borderCodec.encode( + Border.all(color: const Color(0xFFFF0000), width: 2), + ), + (j) => expect( + borderCodec.parse(j), + Border.all(color: const Color(0xFFFF0000), width: 2), + ), + ), + _Case( + 'borderMixed', + () => borderCodec.encode( + const Border( + top: BorderSide(color: Color(0xFFFF0000), width: 2), + bottom: BorderSide(color: Color(0xFF0000FF), width: 3), + ), + ), + (j) => expect( + borderCodec.parse(j), + const Border( + top: BorderSide(color: Color(0xFFFF0000), width: 2), + bottom: BorderSide(color: Color(0xFF0000FF), width: 3), + ), + ), + ), + _Case( + 'borderDirectional', + () => borderDirectionalCodec.encode( + const BorderDirectional( + start: BorderSide(color: Color(0xFFFF0000), width: 2), + ), + ), + (j) => expect( + borderDirectionalCodec.parse(j), + const BorderDirectional( + start: BorderSide(color: Color(0xFFFF0000), width: 2), + ), + ), + ), + _Case( + 'boxBorderDirectional', + () => boxBorderCodec.encode( + const BorderDirectional(start: BorderSide(color: Color(0xFFFF0000))), + ), + (j) { + final parsed = boxBorderCodec.parse(j); + expect(parsed, isA()); + expect( + parsed, + const BorderDirectional(start: BorderSide(color: Color(0xFFFF0000))), + ); + }, + ), +]; + +// --- shape borders ---------------------------------------------------------- + +final _shapeBorders = <_Case>[ + _Case( + 'circleBorder', + () => circleBorderCodec.encode(const CircleBorder()), + (j) => expect(circleBorderCodec.parse(j), const CircleBorder()), + ), + _Case( + 'circleBorderSided', + () => circleBorderCodec.encode( + const CircleBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + eccentricity: 0.5, + ), + ), + (j) => expect( + circleBorderCodec.parse(j), + const CircleBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + eccentricity: 0.5, + ), + ), + ), + _Case( + 'stadiumBorder', + () => stadiumBorderCodec.encode( + const StadiumBorder(side: BorderSide(color: Color(0xFFFF0000), width: 3)), + ), + (j) => expect( + stadiumBorderCodec.parse(j), + const StadiumBorder(side: BorderSide(color: Color(0xFFFF0000), width: 3)), + ), + ), + _Case( + 'roundedRectangleBorder', + () => roundedRectangleBorderCodec.encode( + RoundedRectangleBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(12), + ), + ), + (j) => expect( + roundedRectangleBorderCodec.parse(j), + RoundedRectangleBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(12), + ), + ), + ), + _Case( + 'beveledRectangleBorder', + () => beveledRectangleBorderCodec.encode( + BeveledRectangleBorder(borderRadius: BorderRadius.circular(4)), + ), + (j) => expect( + beveledRectangleBorderCodec.parse(j), + BeveledRectangleBorder(borderRadius: BorderRadius.circular(4)), + ), + ), + _Case( + 'continuousRectangleBorder', + () => continuousRectangleBorderCodec.encode( + ContinuousRectangleBorder(borderRadius: BorderRadius.circular(4)), + ), + (j) => expect( + continuousRectangleBorderCodec.parse(j), + ContinuousRectangleBorder(borderRadius: BorderRadius.circular(4)), + ), + ), + _Case( + 'roundedSuperellipseBorder', + () => roundedSuperellipseBorderCodec.encode( + RoundedSuperellipseBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + ), + ), + (j) => expect( + roundedSuperellipseBorderCodec.parse(j), + RoundedSuperellipseBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + ), + ), + ), + _Case( + 'starBorder', + () => starBorderCodec.encode( + const StarBorder(points: 7, innerRadiusRatio: 0.3), + ), + (j) => expect( + starBorderCodec.parse(j), + const StarBorder(points: 7, innerRadiusRatio: 0.3), + ), + ), + // StarBorder.polygon is intentionally not recorded as a golden: its encoded + // innerRadiusRatio is the polygon incircle (cos(pi / sides)), a libm-derived + // value that is not guaranteed bit-identical across platforms. Its narrowing + // round-trip is covered with a tolerance in shape_borders_test.dart. + _Case( + 'linearBorderEdge', + () => linearBorderEdgeCodec.encode( + const LinearBorderEdge(size: 0.5, alignment: -0.25), + ), + (j) => expect( + linearBorderEdgeCodec.parse(j), + const LinearBorderEdge(size: 0.5, alignment: -0.25), + ), + ), + _Case( + 'linearBorder', + () => linearBorderCodec.encode( + const LinearBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + start: LinearBorderEdge(size: 0.5), + top: LinearBorderEdge(alignment: -1), + ), + ), + (j) => expect( + linearBorderCodec.parse(j), + const LinearBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + start: LinearBorderEdge(size: 0.5), + top: LinearBorderEdge(alignment: -1), + ), + ), + ), + _Case('shapeBorderStar', () => shapeBorderCodec.encode(const StarBorder()), ( + j, + ) { + final parsed = shapeBorderCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const StarBorder()); + }), + // OvalBorder extends CircleBorder, so the union routes it through the + // "circle" branch and it round-trips as the painted-equivalent + // CircleBorder(eccentricity: 1.0). + _Case( + 'shapeBorderOval', + () => shapeBorderCodec.encode(const OvalBorder()), + (j) => + expect(shapeBorderCodec.parse(j), const CircleBorder(eccentricity: 1)), + ), +]; + +// --- gradients -------------------------------------------------------------- + +final _gradients = <_Case>[ + _Case( + 'linearGradient', + () => linearGradientCodec.encode(const LinearGradient(colors: _redBlue)), + (j) => expect( + linearGradientCodec.parse(j), + const LinearGradient(colors: _redBlue), + ), + ), + _Case( + 'linearGradientFull', + () => linearGradientCodec.encode( + const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0, 1], + tileMode: TileMode.mirror, + ), + ), + (j) => expect( + linearGradientCodec.parse(j), + const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0, 1], + tileMode: TileMode.mirror, + ), + ), + ), + _Case( + 'radialGradient', + () => radialGradientCodec.encode(const RadialGradient(colors: _redBlue)), + (j) => expect( + radialGradientCodec.parse(j), + const RadialGradient(colors: _redBlue), + ), + ), + _Case( + 'radialGradientFocal', + () => radialGradientCodec.encode( + const RadialGradient( + colors: _redBlue, + focal: Alignment.topLeft, + focalRadius: 0.25, + ), + ), + (j) => expect( + radialGradientCodec.parse(j), + const RadialGradient( + colors: _redBlue, + focal: Alignment.topLeft, + focalRadius: 0.25, + ), + ), + ), + _Case( + 'sweepGradient', + () => sweepGradientCodec.encode(const SweepGradient(colors: _redBlue)), + (j) => expect( + sweepGradientCodec.parse(j), + const SweepGradient(colors: _redBlue), + ), + ), + _Case( + 'gradientUnionLinear', + () => gradientCodec.encode(const LinearGradient(colors: _redBlue)), + (j) { + final parsed = gradientCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const LinearGradient(colors: _redBlue)); + }, + ), +]; + +// --- shadows ---------------------------------------------------------------- + +final _shadows = <_Case>[ + _Case( + 'shadowDefault', + () => shadowCodec.encode(const ui.Shadow()), + (j) => expect(shadowCodec.parse(j), const ui.Shadow()), + ), + _Case( + 'shadow', + () => shadowCodec.encode( + const ui.Shadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + ), + ), + (j) => expect( + shadowCodec.parse(j), + const ui.Shadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + ), + ), + ), + _Case( + 'boxShadowDefault', + () => boxShadowCodec.encode(const BoxShadow()), + (j) => expect(boxShadowCodec.parse(j), const BoxShadow()), + ), + _Case( + 'boxShadow', + () => boxShadowCodec.encode( + const BoxShadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + spreadRadius: 1, + blurStyle: BlurStyle.outer, + ), + ), + (j) => expect( + boxShadowCodec.parse(j), + const BoxShadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + spreadRadius: 1, + blurStyle: BlurStyle.outer, + ), + ), + ), +]; + +// --- image providers -------------------------------------------------------- + +final _imageProviders = <_Case>[ + _Case( + 'networkImageMinimal', + () => networkImageCodec.encode( + const NetworkImage('https://example.com/image.png'), + ), + (j) => expect( + networkImageCodec.parse(j), + const NetworkImage('https://example.com/image.png'), + ), + ), + _Case( + 'networkImage', + () => networkImageCodec.encode( + const NetworkImage( + 'https://example.com/image.png', + scale: 2, + headers: {'Authorization': 'Bearer token'}, + webHtmlElementStrategy: WebHtmlElementStrategy.fallback, + ), + ), + (j) => expect( + networkImageCodec.parse(j), + const NetworkImage( + 'https://example.com/image.png', + scale: 2, + headers: {'Authorization': 'Bearer token'}, + webHtmlElementStrategy: WebHtmlElementStrategy.fallback, + ), + ), + ), + _Case( + 'assetImageMinimal', + () => assetImageCodec.encode(const AssetImage('assets/image.png')), + (j) => + expect(assetImageCodec.parse(j), const AssetImage('assets/image.png')), + ), + _Case( + 'assetImage', + () => assetImageCodec.encode( + const AssetImage('assets/image.png', package: 'design_system'), + ), + (j) => expect( + assetImageCodec.parse(j), + const AssetImage('assets/image.png', package: 'design_system'), + ), + ), + _Case( + 'imageProviderNetwork', + () => imageProviderCodec.encode( + const NetworkImage('https://example.com/image.png'), + ), + (j) { + final parsed = imageProviderCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const NetworkImage('https://example.com/image.png')); + }, + ), + _Case( + 'imageProviderAsset', + () => imageProviderCodec.encode(const AssetImage('assets/image.png')), + (j) { + final parsed = imageProviderCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const AssetImage('assets/image.png')); + }, + ), +]; + +// --- decorations ------------------------------------------------------------ + +final _decorations = <_Case>[ + _Case( + 'boxDecorationDefault', + () => boxDecorationCodec.encode(const BoxDecoration()), + (j) => expect(boxDecorationCodec.parse(j), const BoxDecoration()), + ), + _Case( + 'boxDecorationFull', + () => boxDecorationCodec.encode(_fullBoxDecoration()), + (j) => expect(boxDecorationCodec.parse(j), _fullBoxDecoration()), + ), + _Case( + 'boxDecorationImage', + () => boxDecorationCodec.encode( + BoxDecoration( + image: DecorationImage( + image: const NetworkImage('https://example.com/foo.png'), + fit: BoxFit.cover, + alignment: Alignment.topLeft, + ), + ), + ), + (j) => expect( + boxDecorationCodec.parse(j), + BoxDecoration( + image: DecorationImage( + image: const NetworkImage('https://example.com/foo.png'), + fit: BoxFit.cover, + alignment: Alignment.topLeft, + ), + ), + ), + ), + _Case( + 'shapeDecorationCircle', + () => shapeDecorationCodec.encode( + const ShapeDecoration(shape: CircleBorder()), + ), + (j) => expect( + shapeDecorationCodec.parse(j), + const ShapeDecoration(shape: CircleBorder()), + ), + ), + _Case( + 'shapeDecorationFull', + () => shapeDecorationCodec.encode(_fullShapeDecoration()), + (j) => expect(shapeDecorationCodec.parse(j), _fullShapeDecoration()), + ), + _Case( + 'shapeDecorationImage', + () => shapeDecorationCodec.encode( + const ShapeDecoration( + shape: CircleBorder(), + image: DecorationImage( + image: NetworkImage('https://example.com/image.png'), + fit: BoxFit.cover, + ), + ), + ), + (j) => expect( + shapeDecorationCodec.parse(j), + const ShapeDecoration( + shape: CircleBorder(), + image: DecorationImage( + image: NetworkImage('https://example.com/image.png'), + fit: BoxFit.cover, + ), + ), + ), + ), + _Case( + 'decorationUnionBox', + () => decorationCodec.encode(const BoxDecoration(color: Color(0xFF2196F3))), + (j) { + final parsed = decorationCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const BoxDecoration(color: Color(0xFF2196F3))); + }, + ), + _Case( + 'decorationUnionShape', + () => decorationCodec.encode(const ShapeDecoration(shape: CircleBorder())), + (j) { + final parsed = decorationCodec.parse(j); + expect(parsed, isA()); + expect(parsed, const ShapeDecoration(shape: CircleBorder())); + }, + ), +]; + +// --- decoration image ------------------------------------------------------- + +final _decorationImage = <_Case>[ + _Case( + 'decorationImageMinimal', + () => decorationImageCodec.encode( + DecorationImage( + image: const NetworkImage('https://example.com/image.png'), + ), + ), + (j) => expect( + decorationImageCodec.parse(j), + DecorationImage( + image: const NetworkImage('https://example.com/image.png'), + ), + ), + ), + _Case( + 'decorationImageFull', + () => decorationImageCodec.encode(_fullDecorationImage()), + (j) => expect(decorationImageCodec.parse(j), _fullDecorationImage()), + ), +]; + +// --- constraints ------------------------------------------------------------ + +final _constraints = <_Case>[ + _Case( + 'boxConstraintsDefault', + () => boxConstraintsCodec.encode(const BoxConstraints()), + (j) => expect(boxConstraintsCodec.parse(j), const BoxConstraints()), + ), + _Case( + 'boxConstraintsFinite', + () => boxConstraintsCodec.encode( + const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ), + (j) => expect( + boxConstraintsCodec.parse(j), + const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ), + ), + _Case( + 'boxConstraintsExpand', + () => boxConstraintsCodec.encode(const BoxConstraints.expand()), + (j) => expect(boxConstraintsCodec.parse(j), const BoxConstraints.expand()), + ), + _Case( + 'constraintsUnionBox', + () => constraintsCodec.encode( + const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ), + (j) => expect( + constraintsCodec.parse(j), + const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ), + ), +]; + +// --- text + strut styles ---------------------------------------------------- + +final _text = <_Case>[ + _Case( + 'textStyleDefault', + () => textStyleCodec.encode(const TextStyle()), + (j) => expect(textStyleCodec.parse(j), const TextStyle()), + ), + _Case( + 'textStyleFull', + () => textStyleCodec.encode(_fullTextStyle()), + (j) => expect(textStyleCodec.parse(j), _fullTextStyle()), + ), + _Case( + 'strutStyleDefault', + () => strutStyleCodec.encode(const StrutStyle()), + (j) => expect(strutStyleCodec.parse(j), const StrutStyle()), + ), + _Case( + 'strutStyleFull', + () => strutStyleCodec.encode( + const StrutStyle( + fontFamily: 'Roboto', + fontSize: 16, + height: 1.5, + fontWeight: FontWeight.w700, + forceStrutHeight: false, + ), + ), + (j) => expect( + strutStyleCodec.parse(j), + const StrutStyle( + fontFamily: 'Roboto', + fontSize: 16, + height: 1.5, + fontWeight: FontWeight.w700, + forceStrutHeight: false, + ), + ), + ), + _Case( + 'strutStylePackage', + () => strutStyleCodec.encode( + const StrutStyle(fontFamily: 'Roboto', package: 'my_pkg'), + ), + (j) => expect( + strutStyleCodec.parse(j), + const StrutStyle(fontFamily: 'Roboto', package: 'my_pkg'), + ), + ), +]; + +// --- widgets ---------------------------------------------------------------- + +final _widgets = <_Case>[ + _Case('containerDefault', () => containerWidgetCodec.encode(Container()), ( + j, + ) { + expect(containerWidgetCodec.parse(j), isA()); + expect(containerWidgetCodec.encode(containerWidgetCodec.parse(j)), j); + }), + _Case('containerFull', () => containerWidgetCodec.encode(_fullContainer()), ( + j, + ) { + expect(containerWidgetCodec.parse(j), isA()); + expect(containerWidgetCodec.encode(containerWidgetCodec.parse(j)), j); + }), + _Case( + 'textWidgetDefault', + () => textWidgetCodec.encode(const Text('hello')), + (j) { + expect(textWidgetCodec.parse(j), isA()); + expect(textWidgetCodec.encode(textWidgetCodec.parse(j)), j); + }, + ), + _Case('textWidgetFull', () => textWidgetCodec.encode(_fullText()), (j) { + expect(textWidgetCodec.parse(j), isA()); + expect(textWidgetCodec.encode(textWidgetCodec.parse(j)), j); + }), + _Case( + 'widgetUnionContainerWithText', + () => widgetCodec.encode( + Container( + padding: const EdgeInsets.all(8), + child: const Text('hi', textAlign: TextAlign.center), + ), + ), + (j) { + final parsed = widgetCodec.parse(j); + expect(parsed, isA()); + expect((parsed! as Container).child, isA()); + expect(widgetCodec.encode(parsed), j); + }, + ), + _Case( + 'keyString', + () => keyCodec.encode(const ValueKey('foo')), + (j) => expect(keyCodec.parse(j), const ValueKey('foo')), + ), + _Case( + 'keyInt', + () => keyCodec.encode(const ValueKey(1)), + (j) => expect(keyCodec.parse(j), const ValueKey(1)), + ), + _Case( + 'keyDouble', + () => keyCodec.encode(const ValueKey(1.5)), + (j) => expect(keyCodec.parse(j), const ValueKey(1.5)), + ), + _Case( + 'keyBool', + () => keyCodec.encode(const ValueKey(true)), + (j) => expect(keyCodec.parse(j), const ValueKey(true)), + ), +]; + +// --- enums ------------------------------------------------------------------ + +final _enums = <_Case>[ + _enumCase('Axis', axisCodec, Axis.values), + _enumCase( + 'AxisDirection', + axisDirectionCodec, + AxisDirection.values, + ), + _enumCase('BlendMode', blendModeCodec, BlendMode.values), + _enumCase('BlurStyle', blurStyleCodec, BlurStyle.values), + _enumCase('BorderStyle', borderStyleCodec, BorderStyle.values), + _enumCase('BoxFit', boxFitCodec, BoxFit.values), + _enumCase( + 'BoxHeightStyle', + boxHeightStyleCodec, + ui.BoxHeightStyle.values, + ), + _enumCase('BoxShape', boxShapeCodec, BoxShape.values), + _enumCase( + 'BoxWidthStyle', + boxWidthStyleCodec, + ui.BoxWidthStyle.values, + ), + _enumCase('Brightness', brightnessCodec, Brightness.values), + _enumCase('Clip', clipCodec, Clip.values), + _enumCase( + 'CrossAxisAlignment', + crossAxisAlignmentCodec, + CrossAxisAlignment.values, + ), + _enumCase( + 'DecorationPosition', + decorationPositionCodec, + DecorationPosition.values, + ), + _enumCase( + 'DragStartBehavior', + dragStartBehaviorCodec, + DragStartBehavior.values, + ), + _enumCase( + 'FilterQuality', + filterQualityCodec, + FilterQuality.values, + ), + _enumCase('FlexFit', flexFitCodec, FlexFit.values), + _enumCase('FontStyle', fontStyleCodec, FontStyle.values), + _enumCase( + 'GrowthDirection', + growthDirectionCodec, + GrowthDirection.values, + ), + _enumCase( + 'HitTestBehavior', + hitTestBehaviorCodec, + HitTestBehavior.values, + ), + _enumCase('ImageRepeat', imageRepeatCodec, ImageRepeat.values), + _enumCase( + 'WebHtmlElementStrategy', + webHtmlElementStrategyCodec, + WebHtmlElementStrategy.values, + ), + _enumCase( + 'MainAxisAlignment', + mainAxisAlignmentCodec, + MainAxisAlignment.values, + ), + _enumCase( + 'MainAxisSize', + mainAxisSizeCodec, + MainAxisSize.values, + ), + _enumCase( + 'MaterialTapTargetSize', + materialTapTargetSizeCodec, + MaterialTapTargetSize.values, + ), + _enumCase( + 'PaintingStyle', + paintingStyleCodec, + PaintingStyle.values, + ), + _enumCase( + 'PathFillType', + pathFillTypeCodec, + PathFillType.values, + ), + _enumCase( + 'PlaceholderAlignment', + placeholderAlignmentCodec, + PlaceholderAlignment.values, + ), + _enumCase( + 'ScrollDirection', + scrollDirectionCodec, + ScrollDirection.values, + ), + _enumCase( + 'ScrollViewKeyboardDismissBehavior', + scrollViewKeyboardDismissBehaviorCodec, + ScrollViewKeyboardDismissBehavior.values, + ), + _enumCase('StackFit', stackFitCodec, StackFit.values), + _enumCase('StrokeCap', strokeCapCodec, StrokeCap.values), + _enumCase('StrokeJoin', strokeJoinCodec, StrokeJoin.values), + _enumCase( + 'TargetPlatform', + targetPlatformCodec, + TargetPlatform.values, + ), + _enumCase('TextAlign', textAlignCodec, TextAlign.values), + _enumCase( + 'TextBaseline', + textBaselineCodec, + TextBaseline.values, + ), + _enumCase( + 'TextCapitalization', + textCapitalizationCodec, + TextCapitalization.values, + ), + _enumCase( + 'TextDecorationStyle', + textDecorationStyleCodec, + TextDecorationStyle.values, + ), + _enumCase( + 'TextDirection', + textDirectionCodec, + TextDirection.values, + ), + _enumCase( + 'TextLeadingDistribution', + textLeadingDistributionCodec, + TextLeadingDistribution.values, + ), + _enumCase( + 'TextOverflow', + textOverflowCodec, + TextOverflow.values, + ), + _enumCase( + 'TextWidthBasis', + textWidthBasisCodec, + TextWidthBasis.values, + ), + _enumCase('ThemeMode', themeModeCodec, ThemeMode.values), + _enumCase('TileMode', tileModeCodec, TileMode.values), + _enumCase( + 'VerticalDirection', + verticalDirectionCodec, + VerticalDirection.values, + ), + _enumCase( + 'WrapAlignment', + wrapAlignmentCodec, + WrapAlignment.values, + ), + _enumCase( + 'WrapCrossAlignment', + wrapCrossAlignmentCodec, + WrapCrossAlignment.values, + ), +]; + +// --- representative composite values --------------------------------------- + +// A non-identity matrix built from translate + scale only. Trigonometric +// helpers (rotateZ, etc.) can differ in the last ULP across platforms, which +// would make the recorded golden machine-dependent; translate/scale are exact. +Matrix4 _transformedMatrix() { + final matrix = Matrix4.identity()..translateByDouble(10, 20, 30, 1); + matrix.setEntry(0, 0, 2); + matrix.setEntry(1, 1, 3); + return matrix; +} + +Container _fullContainer() => Container( + key: const ValueKey('shell'), + alignment: Alignment.centerRight, + padding: const EdgeInsets.all(8), + isAntiAlias: false, + decoration: BoxDecoration( + color: const Color(0xFFE0F2F1), + borderRadius: BorderRadius.circular(6), + ), + foregroundDecoration: BoxDecoration( + border: Border.all(color: const Color(0xFF004D40)), + ), + constraints: const BoxConstraints( + minWidth: 10, + maxWidth: 100, + minHeight: 20, + maxHeight: 200, + ), + margin: const EdgeInsetsDirectional.only(start: 2, end: 4), + transform: _transformedMatrix(), + transformAlignment: Alignment.bottomLeft, + clipBehavior: Clip.antiAlias, + child: Container(color: const Color(0xFFFF0000)), +); + +BoxDecoration _fullBoxDecoration() => BoxDecoration( + color: const Color(0xFF2196F3), + border: Border.all(color: const Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + boxShadow: const [ + BoxShadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + spreadRadius: 4, + blurStyle: BlurStyle.outer, + ), + ], + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0, 1], + tileMode: TileMode.mirror, + ), + backgroundBlendMode: BlendMode.multiply, +); + +ShapeDecoration _fullShapeDecoration() => ShapeDecoration( + color: const Color(0xFF2196F3), + shadows: const [ + BoxShadow(color: Color(0x55000000), offset: Offset(1, 2), blurRadius: 3), + ], + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), +); + +DecorationImage _fullDecorationImage() => DecorationImage( + image: const AssetImage('icons/foo.png', package: 'my_pkg'), + fit: BoxFit.cover, + alignment: Alignment.bottomRight, + centerSlice: const Rect.fromLTRB(1, 2, 3, 4), + repeat: ImageRepeat.repeatX, + matchTextDirection: true, + scale: 1.5, + opacity: 0.75, + filterQuality: FilterQuality.low, + invertColors: true, + isAntiAlias: true, +); + +TextStyle _fullTextStyle() => const TextStyle( + inherit: false, + color: Color(0xFF2196F3), + backgroundColor: Color(0xFFFFFDE7), + fontSize: 18, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + letterSpacing: 0.25, + wordSpacing: 1.5, + textBaseline: TextBaseline.alphabetic, + height: 1.3, + leadingDistribution: TextLeadingDistribution.even, + locale: Locale('zh', 'CN'), + shadows: [ + ui.Shadow(color: Color(0x55000000), offset: Offset(1, 2), blurRadius: 3), + ], + decorationColor: Color(0xFFFF0000), + decorationStyle: TextDecorationStyle.dashed, + decorationThickness: 2, + fontFamily: 'Inter', + fontFamilyFallback: ['Roboto', 'Arial'], + package: 'my_package', + overflow: TextOverflow.ellipsis, + fontFeatures: [FontFeature('smcp'), FontFeature('cv01', 3)], + fontVariations: [FontVariation('wght', 500), FontVariation('slnt', -10)], +); + +Text _fullText() => const Text( + 'hello', + key: ValueKey('copy'), + style: TextStyle( + color: Color(0xFF102030), + fontSize: 18, + fontWeight: FontWeight.w600, + ), + strutStyle: StrutStyle(fontSize: 18, height: 1.25), + textAlign: TextAlign.center, + textDirection: TextDirection.rtl, + locale: Locale('en', 'US'), + softWrap: false, + overflow: TextOverflow.ellipsis, + maxLines: 2, + semanticsLabel: 'label', + semanticsIdentifier: 'copy-id', + textWidthBasis: TextWidthBasis.longestLine, + textHeightBehavior: TextHeightBehavior( + applyHeightToFirstAscent: false, + applyHeightToLastDescent: true, + ), + selectionColor: Color(0x330000FF), +); diff --git a/packages/flutter_codec/test/golden/schema_golden_test.dart b/packages/flutter_codec/test/golden/schema_golden_test.dart new file mode 100644 index 00000000..6916812b --- /dev/null +++ b/packages/flutter_codec/test/golden/schema_golden_test.dart @@ -0,0 +1,180 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +const _fixturePath = 'test/golden/fixtures/json_schema.json'; +final _update = Platform.environment['UPDATE_GOLDENS'] == 'true'; + +typedef _SchemaExporter = Map Function(); + +void main() { + test('schema inventory covers every public codec declaration', () { + expect(_schemaExporters.keys, unorderedEquals(_declaredPublicCodecNames())); + }); + + test('every public codec exports its recorded JSON Schema', () { + final schemas = { + for (final entry in _schemaExporters.entries) entry.key: entry.value(), + }; + final actualText = _renderSchemas(schemas); + final fixture = File(_fixturePath); + + if (_update) { + fixture.parent.createSync(recursive: true); + fixture.writeAsStringSync('$actualText\n'); + return; + } + + expect( + fixture.existsSync(), + isTrue, + reason: + 'Missing schema golden $_fixturePath. Generate it with ' + 'UPDATE_GOLDENS=true flutter test test/golden/schema_golden_test.dart', + ); + expect( + actualText, + fixture.readAsStringSync().trimRight(), + reason: + 'JSON Schema drifted. If the change is intentional, regenerate with ' + 'UPDATE_GOLDENS=true flutter test test/golden/schema_golden_test.dart.', + ); + }); +} + +String _renderSchemas(Map> schemas) { + final entries = schemas.entries.toList(growable: false); + final buffer = StringBuffer('{\n'); + + for (var index = 0; index < entries.length; index += 1) { + final entry = entries[index]; + buffer + ..write(' ${jsonEncode(entry.key)}: ${jsonEncode(entry.value)}') + ..writeln(index == entries.length - 1 ? '' : ','); + } + + return '${buffer.toString()}}'; +} + +Set _declaredPublicCodecNames() { + final declaration = RegExp(r'\b([a-z][A-Za-z0-9_]*Codec)\s*='); + + return Directory('lib') + .listSync(recursive: true) + .whereType() + .where((file) => file.path.endsWith('.dart')) + .expand( + (file) => declaration + .allMatches(file.readAsStringSync()) + .map((match) => match.group(1)!), + ) + .toSet(); +} + +final Map _schemaExporters = { + 'alignmentCodec': alignmentCodec.toJsonSchema, + 'alignmentDirectionalCodec': alignmentDirectionalCodec.toJsonSchema, + 'alignmentGeometryCodec': alignmentGeometryCodec.toJsonSchema, + 'assetImageCodec': assetImageCodec.toJsonSchema, + 'axisCodec': axisCodec.toJsonSchema, + 'axisDirectionCodec': axisDirectionCodec.toJsonSchema, + 'beveledRectangleBorderCodec': beveledRectangleBorderCodec.toJsonSchema, + 'blendModeCodec': blendModeCodec.toJsonSchema, + 'blurStyleCodec': blurStyleCodec.toJsonSchema, + 'borderCodec': borderCodec.toJsonSchema, + 'borderDirectionalCodec': borderDirectionalCodec.toJsonSchema, + 'borderRadiusCodec': borderRadiusCodec.toJsonSchema, + 'borderRadiusDirectionalCodec': borderRadiusDirectionalCodec.toJsonSchema, + 'borderRadiusGeometryCodec': borderRadiusGeometryCodec.toJsonSchema, + 'borderSideCodec': borderSideCodec.toJsonSchema, + 'borderStyleCodec': borderStyleCodec.toJsonSchema, + 'boxBorderCodec': boxBorderCodec.toJsonSchema, + 'boxConstraintsCodec': boxConstraintsCodec.toJsonSchema, + 'boxDecorationCodec': boxDecorationCodec.toJsonSchema, + 'boxFitCodec': boxFitCodec.toJsonSchema, + 'boxHeightStyleCodec': boxHeightStyleCodec.toJsonSchema, + 'boxShadowCodec': boxShadowCodec.toJsonSchema, + 'boxShapeCodec': boxShapeCodec.toJsonSchema, + 'boxWidthStyleCodec': boxWidthStyleCodec.toJsonSchema, + 'brightnessCodec': brightnessCodec.toJsonSchema, + 'circleBorderCodec': circleBorderCodec.toJsonSchema, + 'clipCodec': clipCodec.toJsonSchema, + 'colorCodec': colorCodec.toJsonSchema, + 'constraintsCodec': constraintsCodec.toJsonSchema, + 'containerWidgetCodec': containerWidgetCodec.toJsonSchema, + 'continuousRectangleBorderCodec': continuousRectangleBorderCodec.toJsonSchema, + 'crossAxisAlignmentCodec': crossAxisAlignmentCodec.toJsonSchema, + 'decorationCodec': decorationCodec.toJsonSchema, + 'decorationImageCodec': decorationImageCodec.toJsonSchema, + 'decorationPositionCodec': decorationPositionCodec.toJsonSchema, + 'dragStartBehaviorCodec': dragStartBehaviorCodec.toJsonSchema, + 'edgeInsetsCodec': edgeInsetsCodec.toJsonSchema, + 'edgeInsetsDirectionalCodec': edgeInsetsDirectionalCodec.toJsonSchema, + 'edgeInsetsGeometryCodec': edgeInsetsGeometryCodec.toJsonSchema, + 'filterQualityCodec': filterQualityCodec.toJsonSchema, + 'flexFitCodec': flexFitCodec.toJsonSchema, + 'fontFeatureCodec': fontFeatureCodec.toJsonSchema, + 'fontStyleCodec': fontStyleCodec.toJsonSchema, + 'fontVariationCodec': fontVariationCodec.toJsonSchema, + 'fontWeightCodec': fontWeightCodec.toJsonSchema, + 'gradientCodec': gradientCodec.toJsonSchema, + 'growthDirectionCodec': growthDirectionCodec.toJsonSchema, + 'hitTestBehaviorCodec': hitTestBehaviorCodec.toJsonSchema, + 'imageProviderCodec': imageProviderCodec.toJsonSchema, + 'imageRepeatCodec': imageRepeatCodec.toJsonSchema, + 'keyCodec': keyCodec.toJsonSchema, + 'linearBorderCodec': linearBorderCodec.toJsonSchema, + 'linearBorderEdgeCodec': linearBorderEdgeCodec.toJsonSchema, + 'linearGradientCodec': linearGradientCodec.toJsonSchema, + 'localeCodec': localeCodec.toJsonSchema, + 'mainAxisAlignmentCodec': mainAxisAlignmentCodec.toJsonSchema, + 'mainAxisSizeCodec': mainAxisSizeCodec.toJsonSchema, + 'materialTapTargetSizeCodec': materialTapTargetSizeCodec.toJsonSchema, + 'matrix4Codec': matrix4Codec.toJsonSchema, + 'networkImageCodec': networkImageCodec.toJsonSchema, + 'offsetCodec': offsetCodec.toJsonSchema, + 'paintingStyleCodec': paintingStyleCodec.toJsonSchema, + 'pathFillTypeCodec': pathFillTypeCodec.toJsonSchema, + 'placeholderAlignmentCodec': placeholderAlignmentCodec.toJsonSchema, + 'radialGradientCodec': radialGradientCodec.toJsonSchema, + 'radiusCodec': radiusCodec.toJsonSchema, + 'rectCodec': rectCodec.toJsonSchema, + 'roundedRectangleBorderCodec': roundedRectangleBorderCodec.toJsonSchema, + 'roundedSuperellipseBorderCodec': roundedSuperellipseBorderCodec.toJsonSchema, + 'scrollDirectionCodec': scrollDirectionCodec.toJsonSchema, + 'scrollViewKeyboardDismissBehaviorCodec': + scrollViewKeyboardDismissBehaviorCodec.toJsonSchema, + 'shadowCodec': shadowCodec.toJsonSchema, + 'shapeBorderCodec': shapeBorderCodec.toJsonSchema, + 'shapeDecorationCodec': shapeDecorationCodec.toJsonSchema, + 'stackFitCodec': stackFitCodec.toJsonSchema, + 'stadiumBorderCodec': stadiumBorderCodec.toJsonSchema, + 'starBorderCodec': starBorderCodec.toJsonSchema, + 'strokeAlignCodec': strokeAlignCodec.toJsonSchema, + 'strokeCapCodec': strokeCapCodec.toJsonSchema, + 'strokeJoinCodec': strokeJoinCodec.toJsonSchema, + 'strutStyleCodec': strutStyleCodec.toJsonSchema, + 'sweepGradientCodec': sweepGradientCodec.toJsonSchema, + 'targetPlatformCodec': targetPlatformCodec.toJsonSchema, + 'textAlignCodec': textAlignCodec.toJsonSchema, + 'textBaselineCodec': textBaselineCodec.toJsonSchema, + 'textCapitalizationCodec': textCapitalizationCodec.toJsonSchema, + 'textDecorationCodec': textDecorationCodec.toJsonSchema, + 'textDecorationStyleCodec': textDecorationStyleCodec.toJsonSchema, + 'textDirectionCodec': textDirectionCodec.toJsonSchema, + 'textHeightBehaviorCodec': textHeightBehaviorCodec.toJsonSchema, + 'textLeadingDistributionCodec': textLeadingDistributionCodec.toJsonSchema, + 'textOverflowCodec': textOverflowCodec.toJsonSchema, + 'textStyleCodec': textStyleCodec.toJsonSchema, + 'textWidgetCodec': textWidgetCodec.toJsonSchema, + 'textWidthBasisCodec': textWidthBasisCodec.toJsonSchema, + 'themeModeCodec': themeModeCodec.toJsonSchema, + 'tileModeCodec': tileModeCodec.toJsonSchema, + 'verticalDirectionCodec': verticalDirectionCodec.toJsonSchema, + 'webHtmlElementStrategyCodec': webHtmlElementStrategyCodec.toJsonSchema, + 'widgetCodec': widgetCodec.toJsonSchema, + 'wrapAlignmentCodec': wrapAlignmentCodec.toJsonSchema, + 'wrapCrossAlignmentCodec': wrapCrossAlignmentCodec.toJsonSchema, +}; diff --git a/packages/flutter_codec/test/gradients/gradients_test.dart b/packages/flutter_codec/test/gradients/gradients_test.dart new file mode 100644 index 00000000..a2fb4bef --- /dev/null +++ b/packages/flutter_codec/test/gradients/gradients_test.dart @@ -0,0 +1,452 @@ +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +const _redBlue = [Color(0xFFFF0000), Color(0xFF0000FF)]; +const _redBlueHex = ['#FF0000', '#0000FF']; + +void main() { + group('linearGradientCodec decode', () { + test('parses a minimal input with defaults', () { + expect( + linearGradientCodec.parse({'type': 'linear', 'colors': _redBlueHex}), + const LinearGradient(colors: _redBlue), + ); + }); + + test('parses a full input', () { + expect( + linearGradientCodec.parse({ + 'type': 'linear', + 'begin': 'topLeft', + 'end': 'bottomRight', + 'colors': _redBlueHex, + 'stops': [0.0, 1.0], + 'tileMode': 'mirror', + }), + const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: _redBlue, + stops: [0.0, 1.0], + tileMode: TileMode.mirror, + ), + ); + }); + }); + + group('linearGradientCodec encode', () { + test('emits a full canonical object with discriminator', () { + final encoded = linearGradientCodec.encode( + const LinearGradient(colors: _redBlue), + ); + expect(encoded, { + 'type': 'linear', + 'begin': 'centerLeft', + 'end': 'centerRight', + 'colors': _redBlueHex, + 'stops': null, + 'tileMode': 'clamp', + }); + expectJsonSafe(encoded); + }); + + test('encodes stops when provided', () { + final encoded = + linearGradientCodec.encode( + const LinearGradient(colors: _redBlue, stops: [0.0, 1.0]), + ) + as Map; + expect(encoded['stops'], [0.0, 1.0]); + expectJsonSafe(encoded); + }); + }); + + group('linearGradientCodec rejects invalid input', () { + const invalidCases = { + 'wrong discriminator': {'type': 'radial', 'colors': _redBlueHex}, + 'single-color list': { + 'type': 'linear', + 'colors': ['#FF0000'], + }, + 'missing colors': {'type': 'linear'}, + 'extra property': {'type': 'linear', 'colors': _redBlueHex, 'foo': 1}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(linearGradientCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('radialGradientCodec decode', () { + test('parses a minimal input with defaults', () { + expect( + radialGradientCodec.parse({'type': 'radial', 'colors': _redBlueHex}), + const RadialGradient(colors: _redBlue), + ); + }); + + test('parses focal and focalRadius', () { + expect( + radialGradientCodec.parse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'focal': 'topLeft', + 'focalRadius': 0.25, + }), + const RadialGradient( + colors: _redBlue, + focal: Alignment.topLeft, + focalRadius: 0.25, + ), + ); + }); + }); + + group('radialGradientCodec encode', () { + test('emits null optional fields (stops, focal) explicitly', () { + final encoded = radialGradientCodec.encode( + const RadialGradient(colors: _redBlue), + ); + expect(encoded, { + 'type': 'radial', + 'center': 'center', + 'radius': 0.5, + 'colors': _redBlueHex, + 'stops': null, + 'tileMode': 'clamp', + 'focal': null, + 'focalRadius': 0.0, + }); + expectJsonSafe(encoded); + }); + + test('round-trips focal when present', () { + const original = RadialGradient( + colors: _redBlue, + focal: Alignment.topLeft, + focalRadius: 0.25, + ); + final encoded = radialGradientCodec.encode(original) as Map; + expect(encoded['focal'], 'topLeft'); + expect(radialGradientCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + }); + + group('radialGradientCodec rejects invalid input', () { + test('rejects negative radius', () { + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'radius': -1, + }).isFail, + isTrue, + ); + }); + + test('rejects negative focalRadius', () { + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'focalRadius': -0.1, + }).isFail, + isTrue, + ); + }); + }); + + group('sweepGradientCodec decode', () { + test('parses a minimal input with defaults', () { + expect( + sweepGradientCodec.parse({'type': 'sweep', 'colors': _redBlueHex}), + const SweepGradient(colors: _redBlue), + ); + }); + + test('parses startAngle/endAngle', () { + expect( + sweepGradientCodec.parse({ + 'type': 'sweep', + 'colors': _redBlueHex, + 'startAngle': 1.0, + 'endAngle': 2.0, + }), + const SweepGradient(colors: _redBlue, startAngle: 1, endAngle: 2), + ); + }); + }); + + group('sweepGradientCodec encode', () { + test('default endAngle is math.pi * 2', () { + final encoded = + sweepGradientCodec.encode(const SweepGradient(colors: _redBlue)) + as Map; + expect(encoded['startAngle'], 0.0); + expect(encoded['endAngle'], closeTo(math.pi * 2, 1e-9)); + expect(encoded['type'], 'sweep'); + expectJsonSafe(encoded); + }); + }); + + group('gradientCodec', () { + test('parses {type: linear, ...} as a LinearGradient', () { + final parsed = gradientCodec.parse({ + 'type': 'linear', + 'colors': _redBlueHex, + }); + expect(parsed, isA()); + expect(parsed, const LinearGradient(colors: _redBlue)); + }); + + test('parses {type: radial, ...} as a RadialGradient', () { + final parsed = gradientCodec.parse({ + 'type': 'radial', + 'colors': _redBlueHex, + }); + expect(parsed, isA()); + expect(parsed, const RadialGradient(colors: _redBlue)); + }); + + test('parses {type: sweep, ...} as a SweepGradient', () { + final parsed = gradientCodec.parse({ + 'type': 'sweep', + 'colors': _redBlueHex, + }); + expect(parsed, isA()); + expect(parsed, const SweepGradient(colors: _redBlue)); + }); + + test('rejects an unknown discriminator', () { + expect( + gradientCodec.safeParse({ + 'type': 'spiral', + 'colors': _redBlueHex, + }).isFail, + isTrue, + ); + }); + + test('rejects a missing discriminator', () { + expect(gradientCodec.safeParse({'colors': _redBlueHex}).isFail, isTrue); + }); + + test('encode dispatches by runtime type', () { + final linear = + gradientCodec.encode(const LinearGradient(colors: _redBlue)) as Map; + expect(linear['type'], 'linear'); + + final radial = + gradientCodec.encode(const RadialGradient(colors: _redBlue)) as Map; + expect(radial['type'], 'radial'); + + final sweep = + gradientCodec.encode(const SweepGradient(colors: _redBlue)) as Map; + expect(sweep['type'], 'sweep'); + + expectJsonSafe(linear); + expectJsonSafe(radial); + expectJsonSafe(sweep); + }); + }); + + group('gradientCodec JSON Schema', () { + test('discriminator branches and numeric constraints flow through', () { + final schema = jsonEncode(gradientCodec.toJsonSchema()); + // Each branch's Ack.literal still emits "const":"" in the inner + // object schema. + expect(schema, contains('"const":"linear"')); + expect(schema, contains('"const":"radial"')); + expect(schema, contains('"const":"sweep"')); + // radius / focalRadius non-negativity propagates from Ack.number().min(0). + expect(schema, contains('"minimum":0')); + }); + }); + + group('gradient transform is rejected on encode', () { + final transform = GradientRotation(math.pi / 4); + + test('linearGradientCodec fails on a transformed gradient', () { + final gradient = LinearGradient(colors: _redBlue, transform: transform); + expect(linearGradientCodec.safeEncode(gradient).isFail, isTrue); + }); + + test('radialGradientCodec fails on a transformed gradient', () { + final gradient = RadialGradient(colors: _redBlue, transform: transform); + expect(radialGradientCodec.safeEncode(gradient).isFail, isTrue); + }); + + test('sweepGradientCodec fails on a transformed gradient', () { + final gradient = SweepGradient(colors: _redBlue, transform: transform); + expect(sweepGradientCodec.safeEncode(gradient).isFail, isTrue); + }); + + test('gradientCodec fails on a transformed gradient', () { + final gradient = LinearGradient(colors: _redBlue, transform: transform); + expect(gradientCodec.safeEncode(gradient).isFail, isTrue); + }); + }); + + group('gradient rejects invalid stops', () { + test('linearGradientCodec rejects fewer stops than colors on decode', () { + expect( + linearGradientCodec.safeParse({ + 'type': 'linear', + 'colors': _redBlueHex, + 'stops': [0.0], + }).isFail, + isTrue, + ); + }); + + test('radialGradientCodec rejects fewer stops than colors on decode', () { + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'stops': [0.0], + }).isFail, + isTrue, + ); + }); + + test('sweepGradientCodec rejects fewer stops than colors on decode', () { + expect( + sweepGradientCodec.safeParse({ + 'type': 'sweep', + 'colors': _redBlueHex, + 'stops': [0.0], + }).isFail, + isTrue, + ); + }); + + test('rejects stops outside [0, 1] on decode', () { + expect( + linearGradientCodec.safeParse({ + 'type': 'linear', + 'colors': _redBlueHex, + 'stops': [-1, 2], + }).isFail, + isTrue, + ); + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'stops': [-1, 2], + }).isFail, + isTrue, + ); + expect( + sweepGradientCodec.safeParse({ + 'type': 'sweep', + 'colors': _redBlueHex, + 'stops': [-1, 2], + }).isFail, + isTrue, + ); + }); + + test('rejects descending stops on decode', () { + expect( + linearGradientCodec.safeParse({ + 'type': 'linear', + 'colors': _redBlueHex, + 'stops': [1.0, 0.0], + }).isFail, + isTrue, + ); + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'stops': [1.0, 0.0], + }).isFail, + isTrue, + ); + expect( + sweepGradientCodec.safeParse({ + 'type': 'sweep', + 'colors': _redBlueHex, + 'stops': [1.0, 0.0], + }).isFail, + isTrue, + ); + }); + + test('accepts ascending stops at the bounds', () { + expect( + linearGradientCodec.safeParse({ + 'type': 'linear', + 'colors': _redBlueHex, + 'stops': [0.0, 1.0], + }).isOk, + isTrue, + ); + expect( + radialGradientCodec.safeParse({ + 'type': 'radial', + 'colors': _redBlueHex, + 'stops': [0.0, 1.0], + }).isOk, + isTrue, + ); + expect( + sweepGradientCodec.safeParse({ + 'type': 'sweep', + 'colors': _redBlueHex, + 'stops': [0.0, 1.0], + }).isOk, + isTrue, + ); + }); + + test('fails to encode a gradient with mismatched stops', () { + expect( + linearGradientCodec + .safeEncode(const LinearGradient(colors: _redBlue, stops: [0.0])) + .isFail, + isTrue, + ); + }); + + test('fails to encode descending stops', () { + // The ascending-order invariant is enforced on encode too, not only on + // decode: an in-range but out-of-order [1.0, 0.0] must be rejected. + expect( + linearGradientCodec + .safeEncode( + const LinearGradient(colors: _redBlue, stops: [1.0, 0.0]), + ) + .isFail, + isTrue, + ); + expect( + radialGradientCodec + .safeEncode( + const RadialGradient(colors: _redBlue, stops: [1.0, 0.0]), + ) + .isFail, + isTrue, + ); + expect( + sweepGradientCodec + .safeEncode( + const SweepGradient(colors: _redBlue, stops: [1.0, 0.0]), + ) + .isFail, + isTrue, + ); + }); + }); +} diff --git a/packages/flutter_codec/test/image_providers/image_providers_test.dart b/packages/flutter_codec/test/image_providers/image_providers_test.dart new file mode 100644 index 00000000..0f044934 --- /dev/null +++ b/packages/flutter_codec/test/image_providers/image_providers_test.dart @@ -0,0 +1,244 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('networkImageCodec', () { + test('decodes minimal input with defaults', () { + final value = networkImageCodec.parse({ + 'url': 'https://example.com/image.png', + })!; + + expect(value.url, 'https://example.com/image.png'); + expect(value.scale, 1.0); + expect(value.headers, isNull); + expect(value.webHtmlElementStrategy, WebHtmlElementStrategy.never); + }); + + test('decodes full input', () { + final value = networkImageCodec.parse({ + 'url': 'https://example.com/image.png', + 'scale': 2, + 'headers': {'Authorization': 'Bearer token'}, + 'webHtmlElementStrategy': 'prefer', + })!; + + expect(value.url, 'https://example.com/image.png'); + expect(value.scale, 2.0); + expect(value.headers, {'Authorization': 'Bearer token'}); + expect(value.webHtmlElementStrategy, WebHtmlElementStrategy.prefer); + }); + + test('encodes canonical full map', () { + final encoded = networkImageCodec.encode( + const NetworkImage( + 'https://example.com/image.png', + scale: 2, + headers: {'Authorization': 'Bearer token'}, + webHtmlElementStrategy: WebHtmlElementStrategy.fallback, + ), + ); + + expect(encoded, { + 'url': 'https://example.com/image.png', + 'scale': 2.0, + 'headers': {'Authorization': 'Bearer token'}, + 'webHtmlElementStrategy': 'fallback', + }); + expectJsonSafe(encoded); + }); + + test('encodes explicit null headers', () { + expect( + networkImageCodec.encode( + const NetworkImage('https://example.com/image.png'), + ), + { + 'url': 'https://example.com/image.png', + 'scale': 1.0, + 'headers': null, + 'webHtmlElementStrategy': 'never', + }, + ); + }); + + test('rejects invalid input', () { + final cases = { + 'bad URL type': {'url': 3}, + 'negative scale': {'url': 'https://example.com/image.png', 'scale': -1}, + 'non-finite scale': { + 'url': 'https://example.com/image.png', + 'scale': double.infinity, + }, + 'non-string headers': { + 'url': 'https://example.com/image.png', + 'headers': {'Authorization': 1}, + }, + 'unknown key': {'url': 'https://example.com/image.png', 'extra': true}, + }; + + for (final MapEntry(key: label, value: input) in cases.entries) { + expect( + networkImageCodec.safeParse(input).isFail, + isTrue, + reason: label, + ); + } + }); + }); + + group('assetImageCodec', () { + test('decodes minimal input', () { + final value = assetImageCodec.parse({'assetName': 'assets/image.png'})!; + + expect(value.assetName, 'assets/image.png'); + expect(value.package, isNull); + expect(value.bundle, isNull); + }); + + test('decodes package-qualified assets', () { + final value = assetImageCodec.parse({ + 'assetName': 'assets/image.png', + 'package': 'design_system', + })!; + + expect(value.assetName, 'assets/image.png'); + expect(value.package, 'design_system'); + expect(value.bundle, isNull); + }); + + test('encodes canonical map', () { + final encoded = assetImageCodec.encode( + const AssetImage('assets/image.png'), + ); + + expect(encoded, {'assetName': 'assets/image.png', 'package': null}); + expectJsonSafe(encoded); + }); + + test('encodes package-qualified assets', () { + expect( + assetImageCodec.encode( + const AssetImage('assets/image.png', package: 'design_system'), + ), + {'assetName': 'assets/image.png', 'package': 'design_system'}, + ); + }); + + test('rejects invalid input', () { + final cases = { + 'empty asset name': {'assetName': ''}, + 'non-string asset name': {'assetName': 3}, + 'unknown key': {'assetName': 'assets/image.png', 'extra': true}, + }; + + for (final MapEntry(key: label, value: input) in cases.entries) { + expect(assetImageCodec.safeParse(input).isFail, isTrue, reason: label); + } + }); + + test('rejects encode for AssetImage with custom bundle', () { + final value = AssetImage( + 'assets/image.png', + bundle: NetworkAssetBundle(Uri.parse('https://example.com/')), + ); + + final result = assetImageCodec.safeEncode(value); + + expect(result.isFail, isTrue); + expect( + result.getError().toString(), + contains('AssetImage.bundle is not supported by assetImageCodec.'), + ); + }); + }); + + group('imageProviderCodec', () { + test('dispatches network input', () { + final value = imageProviderCodec.parse({ + 'type': 'network', + 'url': 'https://example.com/image.png', + })!; + + expect(value, isA()); + expect((value as NetworkImage).url, 'https://example.com/image.png'); + }); + + test('dispatches asset input', () { + final value = imageProviderCodec.parse({ + 'type': 'asset', + 'assetName': 'assets/image.png', + })!; + + expect(value, isA()); + expect((value as AssetImage).assetName, 'assets/image.png'); + }); + + test('rejects missing and unknown discriminator', () { + expect( + imageProviderCodec.safeParse({ + 'url': 'https://example.com/image.png', + }).isFail, + isTrue, + ); + expect( + imageProviderCodec.safeParse({ + 'type': 'file', + 'path': '/tmp/a.png', + }).isFail, + isTrue, + ); + }); + + test('encodes by runtime type', () { + final network = imageProviderCodec.encode( + const NetworkImage('https://example.com/image.png'), + ); + final asset = imageProviderCodec.encode( + const AssetImage('assets/image.png'), + ); + + expect(network, { + 'type': 'network', + 'url': 'https://example.com/image.png', + 'scale': 1.0, + 'headers': null, + 'webHtmlElementStrategy': 'never', + }); + expect(asset, { + 'type': 'asset', + 'assetName': 'assets/image.png', + 'package': null, + }); + expectJsonSafe(network); + expectJsonSafe(asset); + }); + + test('rejects unsupported runtime providers', () { + final unsupported = >[ + ResizeImage(const AssetImage('assets/image.png'), width: 16), + const ExactAssetImage('assets/image.png'), + ]; + + for (final value in unsupported) { + expect( + imageProviderCodec.safeEncode(value).isFail, + isTrue, + reason: value.runtimeType.toString(), + ); + } + }); + + test('JSON Schema includes branch const markers', () { + final schemaJson = jsonEncode(imageProviderCodec.toJsonSchema()); + + expect(schemaJson, contains('"const":"network"')); + expect(schemaJson, contains('"const":"asset"')); + }); + }); +} diff --git a/packages/flutter_codec/test/json_readers_test.dart b/packages/flutter_codec/test/json_readers_test.dart new file mode 100644 index 00000000..ddb72dcf --- /dev/null +++ b/packages/flutter_codec/test/json_readers_test.dart @@ -0,0 +1,106 @@ +import 'package:flutter_codec/src/json_readers.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('readValue', () { + test('reads required typed fields', () { + final map = {'value': 'text'}; + + expect(readValue(map, 'value'), 'text'); + }); + }); + + group('readNullableValue', () { + test('returns null for missing or explicit null fields', () { + final map = {'explicitNull': null}; + + expect(readNullableValue(map, 'missing'), isNull); + expect(readNullableValue(map, 'explicitNull'), isNull); + }); + + test('reads present typed fields', () { + final map = {'value': 'text'}; + + expect(readNullableValue(map, 'value'), 'text'); + }); + }); + + group('readDouble', () { + test('reads numeric fields as doubles', () { + final map = {'integer': 2, 'double': 2.5}; + + expect(readDouble(map, 'integer'), 2.0); + expect(readDouble(map, 'double'), 2.5); + }); + }); + + group('readNullableDouble', () { + test('returns null for missing or explicit null fields', () { + final map = {'explicitNull': null}; + + expect(readNullableDouble(map, 'missing'), isNull); + expect(readNullableDouble(map, 'explicitNull'), isNull); + }); + + test('reads present numeric fields as doubles', () { + final map = {'integer': 3, 'double': 3.5}; + + expect(readNullableDouble(map, 'integer'), 3.0); + expect(readNullableDouble(map, 'double'), 3.5); + }); + }); + + group('readList', () { + test('reads typed list fields', () { + final map = { + 'values': ['a', 'b'], + }; + + expect(readList(map, 'values'), ['a', 'b']); + }); + }); + + group('readNullableList', () { + test('returns null for missing or explicit null fields', () { + final map = {'explicitNull': null}; + + expect(readNullableList(map, 'missing'), isNull); + expect(readNullableList(map, 'explicitNull'), isNull); + }); + + test('reads typed list fields', () { + final map = { + 'values': ['a', 'b'], + }; + + expect(readNullableList(map, 'values'), ['a', 'b']); + }); + }); + + group('readNullableDoubleList', () { + test('returns null for missing or explicit null fields', () { + final map = {'explicitNull': null}; + + expect(readNullableDoubleList(map, 'missing'), isNull); + expect(readNullableDoubleList(map, 'explicitNull'), isNull); + }); + + test('reads numeric list fields as doubles', () { + final map = { + 'values': [1, 2.5], + }; + + expect(readNullableDoubleList(map, 'values'), [1.0, 2.5]); + }); + }); + + group('readDoubleList', () { + test('coerces JSON ints to doubles', () { + final map = { + 'values': [1, 2.5, 3], + }; + + expect(readDoubleList(map, 'values'), [1.0, 2.5, 3.0]); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/alignment_test.dart b/packages/flutter_codec/test/primitives/alignment_test.dart new file mode 100644 index 00000000..57efc95d --- /dev/null +++ b/packages/flutter_codec/test/primitives/alignment_test.dart @@ -0,0 +1,237 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('alignmentCodec', () { + const named = { + 'topLeft': Alignment.topLeft, + 'topCenter': Alignment.topCenter, + 'topRight': Alignment.topRight, + 'centerLeft': Alignment.centerLeft, + 'center': Alignment.center, + 'centerRight': Alignment.centerRight, + 'bottomLeft': Alignment.bottomLeft, + 'bottomCenter': Alignment.bottomCenter, + 'bottomRight': Alignment.bottomRight, + }; + + named.forEach((name, value) { + test('decodes/encodes named "$name"', () { + expect(alignmentCodec.parse(name), value); + final encoded = alignmentCodec.encode(value); + expect(encoded, name); + expectJsonSafe(encoded); + }); + }); + + test('decodes an arbitrary {x, y} object', () { + expect( + alignmentCodec.parse({'x': 0.25, 'y': -0.5}), + const Alignment(0.25, -0.5), + ); + }); + + test('encodes an arbitrary Alignment as {x, y}', () { + final encoded = alignmentCodec.encode(const Alignment(0.25, -0.5)); + expect(encoded, {'x': 0.25, 'y': -0.5}); + expectJsonSafe(encoded); + }); + + test('decodes an integer object coordinate as a double', () { + expect(alignmentCodec.parse({'x': 1, 'y': 0}), const Alignment(1, 0)); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'unknown name': 'middle', + 'missing y': {'x': 0.0}, + 'extra key': {'x': 0.0, 'y': 0.0, 'z': 1.0}, + 'directional shape': {'start': 0.0, 'y': 0.0}, + 'non-finite x': {'x': double.infinity, 'y': 0.0}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(alignmentCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); + + group('alignmentDirectionalCodec', () { + const named = { + 'topStart': AlignmentDirectional.topStart, + 'topCenter': AlignmentDirectional.topCenter, + 'topEnd': AlignmentDirectional.topEnd, + 'centerStart': AlignmentDirectional.centerStart, + 'center': AlignmentDirectional.center, + 'centerEnd': AlignmentDirectional.centerEnd, + 'bottomStart': AlignmentDirectional.bottomStart, + 'bottomCenter': AlignmentDirectional.bottomCenter, + 'bottomEnd': AlignmentDirectional.bottomEnd, + }; + + named.forEach((name, value) { + test('decodes/encodes named "$name"', () { + expect(alignmentDirectionalCodec.parse(name), value); + final encoded = alignmentDirectionalCodec.encode(value); + expect(encoded, name); + expectJsonSafe(encoded); + }); + }); + + test('decodes an arbitrary {start, y} object', () { + expect( + alignmentDirectionalCodec.parse({'start': 0.25, 'y': -0.5}), + const AlignmentDirectional(0.25, -0.5), + ); + }); + + test('encodes an arbitrary AlignmentDirectional as {start, y}', () { + final encoded = alignmentDirectionalCodec.encode( + const AlignmentDirectional(0.25, -0.5), + ); + expect(encoded, {'start': 0.25, 'y': -0.5}); + expectJsonSafe(encoded); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'unknown name': 'middle', + 'missing y': {'start': 0.0}, + 'extra key': {'start': 0.0, 'y': 0.0, 'z': 1.0}, + 'non-directional shape': {'x': 0.0, 'y': 0.0}, + 'non-finite start': {'start': double.infinity, 'y': 0.0}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(alignmentDirectionalCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); + + group('alignmentGeometryCodec', () { + test('decodes regular names and {x, y} to Alignment', () { + expect(alignmentGeometryCodec.parse('topLeft'), Alignment.topLeft); + expect(alignmentGeometryCodec.parse('topLeft'), isA()); + + final fromObject = alignmentGeometryCodec.parse({'x': 0.25, 'y': -0.5}); + expect(fromObject, const Alignment(0.25, -0.5)); + expect(fromObject, isA()); + }); + + test( + 'decodes directional names and {start, y} to AlignmentDirectional', + () { + expect( + alignmentGeometryCodec.parse('topStart'), + AlignmentDirectional.topStart, + ); + expect( + alignmentGeometryCodec.parse('topStart'), + isA(), + ); + + final fromObject = alignmentGeometryCodec.parse({ + 'start': -1.0, + 'y': 0.0, + }); + expect(fromObject, const AlignmentDirectional(-1, 0)); + expect(fromObject, isA()); + }, + ); + + test('resolves the shared "center" name to Alignment, not directional', () { + // Alignment.center == AlignmentDirectional.center, so assert the type. + expect(alignmentGeometryCodec.parse('center'), isA()); + expect( + alignmentGeometryCodec.parse('center'), + isNot(isA()), + ); + }); + + test('round-trips preserve the runtime type', () { + final alignment = alignmentGeometryCodec.parse({'x': 0.25, 'y': -0.5})!; + expect(alignment, isA()); + expect(alignmentGeometryCodec.encode(alignment), {'x': 0.25, 'y': -0.5}); + + final directional = alignmentGeometryCodec.parse({ + 'start': 0.25, + 'y': -0.5, + })!; + expect(directional, isA()); + expect(alignmentGeometryCodec.encode(directional), { + 'start': 0.25, + 'y': -0.5, + }); + }); + + test('encodes Alignment back to named/object', () { + expect(alignmentGeometryCodec.encode(Alignment.center), 'center'); + final encoded = alignmentGeometryCodec.encode( + const Alignment(0.25, -0.5), + ); + expect(encoded, {'x': 0.25, 'y': -0.5}); + expectJsonSafe(encoded); + }); + + test('encodes AlignmentDirectional back to named/object', () { + expect( + alignmentGeometryCodec.encode(AlignmentDirectional.topStart), + 'topStart', + ); + final encoded = alignmentGeometryCodec.encode( + const AlignmentDirectional(0.25, -0.5), + ); + expect(encoded, {'start': 0.25, 'y': -0.5}); + expectJsonSafe(encoded); + }); + + test('encodes center-column AlignmentDirectional as {start, y}', () { + // topCenter/center/bottomCenter share a spelling with Alignment names and + // would decode back as Alignment if emitted as names, so the union emits + // the object form to keep them directional on round-trip. + const directionals = [ + AlignmentDirectional.topCenter, + AlignmentDirectional.center, + AlignmentDirectional.bottomCenter, + ]; + + for (final value in directionals) { + final encoded = alignmentGeometryCodec.encode(value); + expect(encoded, {'start': value.start, 'y': value.y}); + expectJsonSafe(encoded); + + final parsed = alignmentGeometryCodec.parse(encoded); + expect(parsed, value); + expect(parsed, isA()); + } + }); + + test('rejects encoding a mixed geometry', () { + // Combining Alignment with AlignmentDirectional yields a private + // _MixedAlignment that matches neither branch, so encode fails loudly + // rather than coercing it. + final mixed = Alignment.center.add(AlignmentDirectional.centerStart); + expect(alignmentGeometryCodec.safeEncode(mixed).isFail, isTrue); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'unknown name': 'middle', + 'mixed keys': {'x': 0.0, 'y': 0.0, 'start': 0.0}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(alignmentGeometryCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/border_radius_test.dart b/packages/flutter_codec/test/primitives/border_radius_test.dart new file mode 100644 index 00000000..f97418ab --- /dev/null +++ b/packages/flutter_codec/test/primitives/border_radius_test.dart @@ -0,0 +1,236 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('borderRadiusCodec decode', () { + test('decodes a number as all circular corners', () { + expect(borderRadiusCodec.parse(8), BorderRadius.circular(8)); + }); + + test('decodes {x, y} as all elliptical corners', () { + expect( + borderRadiusCodec.parse({'x': 8, 'y': 4}), + BorderRadius.all(const Radius.elliptical(8, 4)), + ); + }); + + test('decodes a full per-corner object', () { + expect( + borderRadiusCodec.parse({ + 'topLeft': 1, + 'topRight': 2, + 'bottomLeft': 3, + 'bottomRight': 4, + }), + const BorderRadius.only( + topLeft: Radius.circular(1), + topRight: Radius.circular(2), + bottomLeft: Radius.circular(3), + bottomRight: Radius.circular(4), + ), + ); + }); + + test('applies per-corner defaults to a partial object', () { + expect( + borderRadiusCodec.parse({'topLeft': 8}), + const BorderRadius.only(topLeft: Radius.circular(8)), + ); + }); + + test('decodes an empty object as BorderRadius.zero', () { + expect(borderRadiusCodec.parse({}), BorderRadius.zero); + }); + }); + + group('borderRadiusCodec encode', () { + test('collapses uniform circular corners to a number', () { + final encoded = borderRadiusCodec.encode(BorderRadius.circular(8)); + expect(encoded, 8.0); + expectJsonSafe(encoded); + }); + + test('collapses uniform elliptical corners to {x, y}', () { + final encoded = borderRadiusCodec.encode( + BorderRadius.all(const Radius.elliptical(8, 4)), + ); + expect(encoded, {'x': 8.0, 'y': 4.0}); + expectJsonSafe(encoded); + }); + + test('emits the full corner object when corners differ', () { + final encoded = borderRadiusCodec.encode( + const BorderRadius.only(topLeft: Radius.circular(8)), + ); + expect(encoded, { + 'topLeft': 8.0, + 'topRight': 0.0, + 'bottomLeft': 0.0, + 'bottomRight': 0.0, + }); + expectJsonSafe(encoded); + }); + }); + + group('borderRadiusCodec rejects invalid input', () { + const invalidCases = { + 'directional shape': { + 'topStart': 8, + 'topEnd': 0, + 'bottomStart': 0, + 'bottomEnd': 0, + }, + 'unknown key': {'topLeft': 8, 'z': 1}, + 'negative corner': {'topLeft': -1}, + 'non-finite corner': {'topLeft': double.infinity}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(borderRadiusCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('borderRadiusDirectionalCodec', () { + test('decodes a full per-corner object', () { + expect( + borderRadiusDirectionalCodec.parse({ + 'topStart': 1, + 'topEnd': 2, + 'bottomStart': 3, + 'bottomEnd': 4, + }), + const BorderRadiusDirectional.only( + topStart: Radius.circular(1), + topEnd: Radius.circular(2), + bottomStart: Radius.circular(3), + bottomEnd: Radius.circular(4), + ), + ); + }); + + test('applies per-corner defaults to a partial object', () { + expect( + borderRadiusDirectionalCodec.parse({'topStart': 8}), + const BorderRadiusDirectional.only(topStart: Radius.circular(8)), + ); + }); + + test('decodes an empty object as BorderRadiusDirectional.zero', () { + expect( + borderRadiusDirectionalCodec.parse({}), + BorderRadiusDirectional.zero, + ); + }); + + test('always encodes to the full object, even when uniform', () { + final encoded = borderRadiusDirectionalCodec.encode( + BorderRadiusDirectional.all(const Radius.circular(8)), + ); + expect(encoded, { + 'topStart': 8.0, + 'topEnd': 8.0, + 'bottomStart': 8.0, + 'bottomEnd': 8.0, + }); + expectJsonSafe(encoded); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'a scalar': 8, + 'non-directional shape': { + 'topLeft': 8, + 'topRight': 0, + 'bottomLeft': 0, + 'bottomRight': 0, + }, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(borderRadiusDirectionalCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); + + group('borderRadiusGeometryCodec', () { + test('decodes shorthand / {topLeft,...} / {} to BorderRadius', () { + expect(borderRadiusGeometryCodec.parse(8), isA()); + expect(borderRadiusGeometryCodec.parse(8), BorderRadius.circular(8)); + + final fromObject = borderRadiusGeometryCodec.parse({'topLeft': 8}); + expect(fromObject, isA()); + expect(fromObject, const BorderRadius.only(topLeft: Radius.circular(8))); + + expect(borderRadiusGeometryCodec.parse({}), isA()); + }); + + test('decodes {topStart,...} to BorderRadiusDirectional', () { + final value = borderRadiusGeometryCodec.parse({'topStart': 8}); + expect(value, isA()); + expect( + value, + const BorderRadiusDirectional.only(topStart: Radius.circular(8)), + ); + }); + + test('encodes BorderRadius back to shorthand/object', () { + expect(borderRadiusGeometryCodec.encode(BorderRadius.circular(8)), 8.0); + final encoded = borderRadiusGeometryCodec.encode( + const BorderRadius.only(topLeft: Radius.circular(8)), + ); + expect(encoded, { + 'topLeft': 8.0, + 'topRight': 0.0, + 'bottomLeft': 0.0, + 'bottomRight': 0.0, + }); + expectJsonSafe(encoded); + }); + + test('directional round-trips as BorderRadiusDirectional', () { + final encoded = borderRadiusGeometryCodec.encode( + BorderRadiusDirectional.all(const Radius.circular(8)), + ); + expect(encoded, { + 'topStart': 8.0, + 'topEnd': 8.0, + 'bottomStart': 8.0, + 'bottomEnd': 8.0, + }); + expect( + borderRadiusGeometryCodec.parse(encoded), + isA(), + ); + }); + + test('rejects encoding a mixed geometry', () { + // Combining BorderRadius with BorderRadiusDirectional yields a private + // _MixedBorderRadius that matches neither branch, so encode fails loudly + // rather than coercing it. + final mixed = BorderRadius.circular( + 1, + ).add(BorderRadiusDirectional.circular(2)); + expect(borderRadiusGeometryCodec.safeEncode(mixed).isFail, isTrue); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'mixed keys': {'topLeft': 8, 'topStart': 8}, + 'unknown key': {'z': 1}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(borderRadiusGeometryCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/color_test.dart b/packages/flutter_codec/test/primitives/color_test.dart new file mode 100644 index 00000000..cf56ccce --- /dev/null +++ b/packages/flutter_codec/test/primitives/color_test.dart @@ -0,0 +1,93 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('colorCodec decode', () { + const cases = [ + ('#2196F3', Color(0xFF2196F3)), + ('#802196F3', Color(0x802196F3)), + ('rgb(33, 150, 243)', Color(0xFF2196F3)), + ('rgba(33, 150, 243, 0.5)', Color(0x802196F3)), + ]; + + for (final (input, expected) in cases) { + test(input, () { + expect(colorCodec.parse(input), expected); + }); + } + }); + + group('colorCodec encode', () { + test('canonicalizes opaque colors to #RRGGBB', () { + final encoded = colorCodec.encode(const Color(0xFF2196F3)); + expect(encoded, '#2196F3'); + expectJsonSafe(encoded); + }); + + test('canonicalizes translucent colors to #AARRGGBB', () { + final encoded = colorCodec.encode(const Color(0x802196F3)); + expect(encoded, '#802196F3'); + expectJsonSafe(encoded); + }); + }); + + group('colorCodec rejects invalid input', () { + for (final input in [ + '#2196F', + '#GG96F3', + 'rgb(256, 150, 243)', + 'rgba(33, 150, 243, 1.5)', + 'hsl(207, 90%, 54%)', + ]) { + test(input, () { + expect(colorCodec.safeParse(input).isFail, isTrue); + }); + } + }); + + // Characterization tests: the wire format is 8-bit sRGB hex, so float-channel + // precision and non-sRGB color spaces are intentionally not preserved. These + // pin the documented loss so it stays deliberate. + group('colorCodec is 8-bit sRGB (documented lossy)', () { + test('an integer-constructed sRGB color round-trips exactly', () { + const color = Color(0xFF2196F3); + expect(colorCodec.parse(colorCodec.encode(color)), color); + }); + + test('a float-channel color is quantized to 8 bits, not preserved', () { + final color = const Color(0xFF000000).withValues(alpha: 0.3); + final roundTripped = colorCodec.parse(colorCodec.encode(color))!; + // The float alpha 0.3 cannot survive an 8-bit round-trip exactly... + expect(roundTripped, isNot(color)); + // ...but the quantized value stays within one 8-bit step of 0.3. + expect(roundTripped.a, closeTo(0.3, 1 / 255)); + }); + + test('a wide-gamut color round-trips as sRGB', () { + const wideGamut = Color.from( + alpha: 1, + red: 1, + green: 0, + blue: 0, + colorSpace: ColorSpace.displayP3, + ); + final roundTripped = colorCodec.parse(colorCodec.encode(wideGamut))!; + expect(roundTripped.colorSpace, ColorSpace.sRGB); + }); + }); + + group('colorCodec JSON Schema', () { + test('rgb/rgba channel patterns admit 0-255 only, not 256+', () { + final schema = jsonEncode(colorCodec.toJsonSchema()); + // The tightened 0-255 channel alternation replaces the loose `\d{1,3}` + // so the generated schema does not admit out-of-range channels. + expect(schema, contains('25[0-5]')); + expect(schema, isNot(contains(r'\\d{1,3}'))); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/edge_insets_test.dart b/packages/flutter_codec/test/primitives/edge_insets_test.dart new file mode 100644 index 00000000..83ff5063 --- /dev/null +++ b/packages/flutter_codec/test/primitives/edge_insets_test.dart @@ -0,0 +1,186 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('edgeInsetsCodec decode', () { + test('decodes a number as all sides', () { + expect(edgeInsetsCodec.parse(16), const EdgeInsets.all(16)); + }); + + test('decodes a full {left, top, right, bottom} object', () { + expect( + edgeInsetsCodec.parse({'left': 1, 'top': 2, 'right': 3, 'bottom': 4}), + const EdgeInsets.fromLTRB(1, 2, 3, 4), + ); + }); + + test('applies per-side defaults to a partial object', () { + expect( + edgeInsetsCodec.parse({'left': 8}), + const EdgeInsets.only(left: 8), + ); + }); + + test('decodes an empty object as EdgeInsets.zero', () { + expect(edgeInsetsCodec.parse({}), EdgeInsets.zero); + }); + }); + + group('edgeInsetsCodec encode', () { + test('collapses a uniform inset to a scalar', () { + final encoded = edgeInsetsCodec.encode(const EdgeInsets.all(16)); + expect(encoded, 16.0); + expectJsonSafe(encoded); + }); + + test('encodes EdgeInsets.zero as 0', () { + final encoded = edgeInsetsCodec.encode(EdgeInsets.zero); + expect(encoded, 0.0); + expectJsonSafe(encoded); + }); + + test('emits the full object when sides differ', () { + final encoded = edgeInsetsCodec.encode( + const EdgeInsets.only(left: 8, top: 4), + ); + expect(encoded, {'left': 8.0, 'top': 4.0, 'right': 0.0, 'bottom': 0.0}); + expectJsonSafe(encoded); + }); + }); + + group('edgeInsetsCodec rejects invalid input', () { + const invalidCases = { + 'directional shape': {'start': 8, 'top': 0, 'end': 0, 'bottom': 0}, + 'unknown key': {'left': 8, 'z': 1}, + 'non-finite scalar': double.infinity, + 'non-finite side': {'left': double.infinity}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(edgeInsetsCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('edgeInsetsDirectionalCodec', () { + test('decodes a full {start, top, end, bottom} object', () { + expect( + edgeInsetsDirectionalCodec.parse({ + 'start': 1, + 'top': 2, + 'end': 3, + 'bottom': 4, + }), + const EdgeInsetsDirectional.fromSTEB(1, 2, 3, 4), + ); + }); + + test('applies per-side defaults to a partial object', () { + expect( + edgeInsetsDirectionalCodec.parse({'start': 8}), + const EdgeInsetsDirectional.only(start: 8), + ); + }); + + test('decodes an empty object as EdgeInsetsDirectional.zero', () { + expect(edgeInsetsDirectionalCodec.parse({}), EdgeInsetsDirectional.zero); + }); + + test('always encodes to the full object, even when uniform', () { + final encoded = edgeInsetsDirectionalCodec.encode( + const EdgeInsetsDirectional.all(8), + ); + expect(encoded, {'start': 8.0, 'top': 8.0, 'end': 8.0, 'bottom': 8.0}); + expectJsonSafe(encoded); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'a scalar': 8, + 'non-directional shape': {'left': 8, 'top': 0, 'right': 0, 'bottom': 0}, + 'non-finite side': {'start': double.infinity}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(edgeInsetsDirectionalCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); + + group('edgeInsetsGeometryCodec', () { + test('decodes scalar / {left,...} / {} to EdgeInsets', () { + expect(edgeInsetsGeometryCodec.parse(16), isA()); + expect(edgeInsetsGeometryCodec.parse(16), const EdgeInsets.all(16)); + + final fromObject = edgeInsetsGeometryCodec.parse({'left': 8}); + expect(fromObject, isA()); + expect(fromObject, const EdgeInsets.only(left: 8)); + + expect(edgeInsetsGeometryCodec.parse({}), isA()); + }); + + test('decodes {start,...} to EdgeInsetsDirectional', () { + final value = edgeInsetsGeometryCodec.parse({'start': 8}); + expect(value, isA()); + expect(value, const EdgeInsetsDirectional.only(start: 8)); + }); + + test('encodes EdgeInsets back to scalar/object', () { + expect(edgeInsetsGeometryCodec.encode(const EdgeInsets.all(16)), 16.0); + final encoded = edgeInsetsGeometryCodec.encode( + const EdgeInsets.only(left: 8, top: 4), + ); + expect(encoded, {'left': 8.0, 'top': 4.0, 'right': 0.0, 'bottom': 0.0}); + expectJsonSafe(encoded); + }); + + test('encodes EdgeInsetsDirectional back to its object', () { + final encoded = edgeInsetsGeometryCodec.encode( + const EdgeInsetsDirectional.only(start: 8), + ); + expect(encoded, {'start': 8.0, 'top': 0.0, 'end': 0.0, 'bottom': 0.0}); + expectJsonSafe(encoded); + }); + + test('directional zero round-trips as EdgeInsetsDirectional', () { + // EdgeInsets.zero == EdgeInsetsDirectional.zero, so assert the type. + final encoded = edgeInsetsGeometryCodec.encode( + EdgeInsetsDirectional.zero, + ); + expect(encoded, {'start': 0.0, 'top': 0.0, 'end': 0.0, 'bottom': 0.0}); + expect( + edgeInsetsGeometryCodec.parse(encoded), + isA(), + ); + }); + + test('rejects encoding a mixed geometry', () { + // Combining EdgeInsets with EdgeInsetsDirectional yields a private + // _MixedEdgeInsets that matches neither branch, so encode fails loudly + // rather than coercing it. + final mixed = const EdgeInsets.only( + left: 8, + ).add(const EdgeInsetsDirectional.only(start: 4)); + expect(edgeInsetsGeometryCodec.safeEncode(mixed).isFail, isTrue); + }); + + group('rejects invalid input', () { + const invalidCases = { + 'mixed keys': {'left': 8, 'start': 8}, + 'unknown key': {'z': 1}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(edgeInsetsGeometryCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/font_feature_test.dart b/packages/flutter_codec/test/primitives/font_feature_test.dart new file mode 100644 index 00000000..d3c7832d --- /dev/null +++ b/packages/flutter_codec/test/primitives/font_feature_test.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('fontFeatureCodec decode', () { + test('decodes a feature tag with an explicit value', () { + expect( + fontFeatureCodec.parse({'feature': 'smcp', 'value': 1}), + const FontFeature('smcp', 1), + ); + }); + + test('defaults missing value to 1 (the enable convention)', () { + expect( + fontFeatureCodec.parse({'feature': 'liga'}), + const FontFeature('liga'), + ); + }); + + test('accepts non-default integer values', () { + expect( + fontFeatureCodec.parse({'feature': 'cv01', 'value': 3}), + const FontFeature('cv01', 3), + ); + }); + }); + + group('fontFeatureCodec encode', () { + test('emits the feature tag and value', () { + final encoded = fontFeatureCodec.encode(const FontFeature('smcp', 1)); + expect(encoded, {'feature': 'smcp', 'value': 1}); + expectJsonSafe(encoded); + }); + + test('round-trips named convenience constructors as (feature, value)', () { + final encoded = fontFeatureCodec.encode(FontFeature.alternative(2)); + expect(fontFeatureCodec.parse(encoded), FontFeature.alternative(2)); + }); + }); + + group('fontFeatureCodec rejects invalid input', () { + test('rejects a feature tag shorter than four characters', () { + expect( + fontFeatureCodec.safeParse({'feature': 'lig', 'value': 1}).isFail, + isTrue, + ); + }); + + test('rejects a feature tag longer than four characters', () { + expect( + fontFeatureCodec.safeParse({'feature': 'ligas', 'value': 1}).isFail, + isTrue, + ); + }); + + test('rejects negative values', () { + expect( + fontFeatureCodec.safeParse({'feature': 'smcp', 'value': -1}).isFail, + isTrue, + ); + }); + + test('rejects unknown keys', () { + expect( + fontFeatureCodec.safeParse({ + 'feature': 'smcp', + 'value': 1, + 'extra': true, + }).isFail, + isTrue, + ); + }); + }); + + group('fontFeatureCodec JSON Schema', () { + test('reflects the 4-character pattern and default value', () { + final schema = jsonEncode(fontFeatureCodec.toJsonSchema()); + expect(schema, contains(r'[\\x20-\\x7E]{4}')); + expect(schema, contains('"default":1')); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/font_variation_test.dart b/packages/flutter_codec/test/primitives/font_variation_test.dart new file mode 100644 index 00000000..83a06945 --- /dev/null +++ b/packages/flutter_codec/test/primitives/font_variation_test.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('fontVariationCodec decode', () { + test('decodes an axis tag and value', () { + expect( + fontVariationCodec.parse({'axis': 'wght', 'value': 600}), + const FontVariation('wght', 600), + ); + }); + + test('coerces integer JSON values to double on the value field', () { + // JSON sources emit `100` as int; FontVariation.value is double, and + // the codec must round-trip through the double constructor. + expect( + fontVariationCodec.parse({'axis': 'wdth', 'value': 100}), + const FontVariation('wdth', 100.0), + ); + }); + }); + + group('fontVariationCodec encode', () { + test('emits the axis tag and value', () { + final encoded = fontVariationCodec.encode( + const FontVariation('wght', 600), + ); + expect(encoded, {'axis': 'wght', 'value': 600.0}); + expectJsonSafe(encoded); + }); + + test('round-trips named convenience constructors as (axis, value)', () { + final encoded = fontVariationCodec.encode(FontVariation.weight(500)); + expect(fontVariationCodec.parse(encoded), FontVariation.weight(500)); + }); + }); + + group('fontVariationCodec rejects invalid input', () { + test('rejects an axis tag shorter than four characters', () { + expect( + fontVariationCodec.safeParse({'axis': 'wgt', 'value': 600}).isFail, + isTrue, + ); + }); + + test('rejects an axis tag longer than four characters', () { + expect( + fontVariationCodec.safeParse({'axis': 'wghtx', 'value': 600}).isFail, + isTrue, + ); + }); + + test('rejects unknown keys', () { + expect( + fontVariationCodec.safeParse({ + 'axis': 'wght', + 'value': 600, + 'extra': true, + }).isFail, + isTrue, + ); + }); + + test('rejects a missing value', () { + expect(fontVariationCodec.safeParse({'axis': 'wght'}).isFail, isTrue); + }); + }); + + group('fontVariationCodec value range', () { + test('accepts the inclusive lower bound -32768', () { + expect( + fontVariationCodec.parse({'axis': 'wght', 'value': -32768}), + const FontVariation('wght', -32768), + ); + }); + + test('accepts a value just below the exclusive upper bound', () { + expect( + fontVariationCodec.parse({'axis': 'wght', 'value': 32767}), + const FontVariation('wght', 32767), + ); + }); + + test('rejects a value below -32768', () { + expect( + fontVariationCodec.safeParse({'axis': 'wght', 'value': -32769}).isFail, + isTrue, + ); + }); + + test('rejects the exclusive upper bound 32768', () { + expect( + fontVariationCodec.safeParse({'axis': 'wght', 'value': 32768}).isFail, + isTrue, + ); + }); + }); + + group('fontVariationCodec JSON Schema', () { + test('reflects the 4-character pattern on axis', () { + final schema = jsonEncode(fontVariationCodec.toJsonSchema()); + expect(schema, contains(r'[\\x20-\\x7E]{4}')); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/font_weight_test.dart b/packages/flutter_codec/test/primitives/font_weight_test.dart new file mode 100644 index 00000000..cc359649 --- /dev/null +++ b/packages/flutter_codec/test/primitives/font_weight_test.dart @@ -0,0 +1,90 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('fontWeightCodec decode', () { + const weights = { + 'w100': FontWeight.w100, + 'w200': FontWeight.w200, + 'w300': FontWeight.w300, + 'w400': FontWeight.w400, + 'w500': FontWeight.w500, + 'w600': FontWeight.w600, + 'w700': FontWeight.w700, + 'w800': FontWeight.w800, + 'w900': FontWeight.w900, + }; + + weights.forEach((name, value) { + test('decodes "$name"', () { + expect(fontWeightCodec.parse(name), value); + }); + }); + + test('decodes conventional aliases', () { + expect(fontWeightCodec.parse('normal'), FontWeight.normal); + expect(fontWeightCodec.parse('bold'), FontWeight.bold); + }); + + test('decodes an integer variable-font weight', () { + expect(fontWeightCodec.parse(550), const FontWeight(550)); + expect(fontWeightCodec.parse(1), const FontWeight(1)); + expect(fontWeightCodec.parse(1000), const FontWeight(1000)); + }); + + test('decodes a canonical integer weight to the standard instance', () { + expect(fontWeightCodec.parse(400), FontWeight.w400); + }); + }); + + group('fontWeightCodec encode', () { + const weights = [ + (FontWeight.w100, 'w100'), + (FontWeight.w200, 'w200'), + (FontWeight.w300, 'w300'), + (FontWeight.w400, 'w400'), + (FontWeight.w500, 'w500'), + (FontWeight.w600, 'w600'), + (FontWeight.w700, 'w700'), + (FontWeight.w800, 'w800'), + (FontWeight.w900, 'w900'), + ]; + + for (final (value, name) in weights) { + test('encodes $value as "$name"', () { + final encoded = fontWeightCodec.encode(value); + expect(encoded, name); + expectJsonSafe(encoded); + }); + } + + test('canonicalizes conventional aliases', () { + expect(fontWeightCodec.encode(FontWeight.normal), 'w400'); + expect(fontWeightCodec.encode(FontWeight.bold), 'w700'); + }); + + test('encodes a non-canonical variable-font weight as an integer', () { + final encoded = fontWeightCodec.encode(const FontWeight(550)); + expect(encoded, 550); + expectJsonSafe(encoded); + }); + + test('round-trips a variable-font weight', () { + const weight = FontWeight(550); + expect(fontWeightCodec.parse(fontWeightCodec.encode(weight)), weight); + }); + }); + + group('fontWeightCodec rejects invalid input', () { + // Out-of-range integers (the constructor asserts [1, 1000]) and + // non-weight values are rejected; in-range integers are now accepted. + for (final input in ['heavy', 0, 1001, null]) { + test('rejects $input', () { + expect(fontWeightCodec.safeParse(input).isFail, isTrue); + }); + } + }); +} diff --git a/packages/flutter_codec/test/primitives/locale_test.dart b/packages/flutter_codec/test/primitives/locale_test.dart new file mode 100644 index 00000000..3e89befc --- /dev/null +++ b/packages/flutter_codec/test/primitives/locale_test.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('localeCodec', () { + const cases = { + 'en': Locale('en'), + 'en-US': Locale('en', 'US'), + 'zh-Hans-CN': Locale.fromSubtags( + languageCode: 'zh', + scriptCode: 'Hans', + countryCode: 'CN', + ), + 'pt-BR': Locale('pt', 'BR'), + }; + + cases.forEach((tag, locale) { + test('round-trips "$tag"', () { + expect(localeCodec.parse(tag), locale); + + final encoded = localeCodec.encode(locale); + expect(encoded, tag); + expectJsonSafe(encoded); + }); + }); + }); + + group('localeCodec rejects invalid input', () { + for (final input in ['EN', 'en-us', '']) { + test('rejects "$input"', () { + expect(localeCodec.safeParse(input).isFail, isTrue); + }); + } + }); + + group('localeCodec JSON Schema', () { + test('BCP-47 subset pattern is reflected', () { + expect( + jsonEncode(localeCodec.toJsonSchema()), + contains( + r'"pattern":"^([a-z]{2,3})(?:-([A-Z][a-z]{3}))?(?:-([A-Z]{2}|\\d{3}))?$"', + ), + ); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/matrix4_test.dart b/packages/flutter_codec/test/primitives/matrix4_test.dart new file mode 100644 index 00000000..a99b359d --- /dev/null +++ b/packages/flutter_codec/test/primitives/matrix4_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/widgets.dart' show Matrix4; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('matrix4Codec', () { + test('round-trips the identity matrix', () { + final matrix = Matrix4.identity(); + final encoded = matrix4Codec.encode(matrix); + + expect(matrix4Codec.parse(encoded), matrix); + expectJsonSafe(encoded); + }); + + test('round-trips a transformed matrix in column-major storage order', () { + final matrix = Matrix4.identity() + ..translateByDouble(10.0, 20.0, 30.0, 1.0) + ..rotateZ(0.5); + + final encoded = matrix4Codec.encode(matrix); + + expect(encoded, matrix.storage.toList()); + expect(matrix4Codec.parse(encoded), matrix); + expectJsonSafe(encoded); + }); + + test('defensively copies parsed storage', () { + final storage = Matrix4.identity().storage.toList(); + final parsed = matrix4Codec.parse(storage)!; + + storage[0] = 10; + + expect(parsed, Matrix4.identity()); + }); + + test('rejects lists that are not exactly 16 items long', () { + expect(matrix4Codec.safeParse(List.filled(15, 0)).isFail, isTrue); + expect(matrix4Codec.safeParse(List.filled(17, 0)).isFail, isTrue); + }); + + test('rejects non-finite entries (JSON has no NaN/Infinity literal)', () { + final withNaN = List.filled(16, 0.0)..[0] = double.nan; + final withInfinity = List.filled(16, 0.0)..[5] = double.infinity; + + expect(matrix4Codec.safeParse(withNaN).isFail, isTrue); + expect(matrix4Codec.safeParse(withInfinity).isFail, isTrue); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/offset_test.dart b/packages/flutter_codec/test/primitives/offset_test.dart new file mode 100644 index 00000000..bbd57957 --- /dev/null +++ b/packages/flutter_codec/test/primitives/offset_test.dart @@ -0,0 +1,30 @@ +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('offsetCodec', () { + test('decodes x and y into an Offset', () { + expect(offsetCodec.parse({'x': 12, 'y': 4.5}), const Offset(12, 4.5)); + }); + + test('encodes Offset as x and y', () { + final encoded = offsetCodec.encode(const Offset(12, 4.5)); + expect(encoded, {'x': 12.0, 'y': 4.5}); + expectJsonSafe(encoded); + }); + + test('rejects missing coordinates', () { + expect(offsetCodec.safeParse({'x': 12}).isFail, isTrue); + }); + + test('rejects non-finite coordinates', () { + expect( + offsetCodec.safeParse({'x': double.infinity, 'y': 0}).isFail, + isTrue, + ); + expect(offsetCodec.safeParse({'x': 0, 'y': double.nan}).isFail, isTrue); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/radius_test.dart b/packages/flutter_codec/test/primitives/radius_test.dart new file mode 100644 index 00000000..fa92cc0b --- /dev/null +++ b/packages/flutter_codec/test/primitives/radius_test.dart @@ -0,0 +1,62 @@ +import 'dart:convert'; +import 'dart:ui'; + +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('radiusCodec decode', () { + test('decodes a number as a circular radius', () { + expect(radiusCodec.parse(8), const Radius.circular(8)); + }); + + test('decodes x and y as an elliptical radius', () { + expect( + radiusCodec.parse({'x': 8, 'y': 12.5}), + const Radius.elliptical(8, 12.5), + ); + }); + }); + + group('radiusCodec encode', () { + test('canonicalizes circular radii to a number', () { + final encoded = radiusCodec.encode(const Radius.circular(8)); + expect(encoded, 8.0); + expectJsonSafe(encoded); + }); + + test('encodes elliptical radii as x and y', () { + final encoded = radiusCodec.encode(const Radius.elliptical(8, 12.5)); + expect(encoded, {'x': 8.0, 'y': 12.5}); + expectJsonSafe(encoded); + }); + }); + + group('radiusCodec rejects invalid input', () { + test('rejects negative circular radii', () { + expect(radiusCodec.safeParse(-1).isFail, isTrue); + }); + + test('rejects negative elliptical coordinates', () { + expect(radiusCodec.safeParse({'x': 1, 'y': -1}).isFail, isTrue); + }); + + test('rejects non-finite radii', () { + expect(radiusCodec.safeParse(double.infinity).isFail, isTrue); + expect( + radiusCodec.safeParse({'x': double.infinity, 'y': 1}).isFail, + isTrue, + ); + }); + }); + + group('radiusCodec JSON Schema', () { + test('non-negative constraint is reflected as "minimum": 0', () { + // Locks in the Ack.number().min(0) JSON-Schema reflection — refine + // would silently drop it, the public ComparisonConstraint does not. + expect(jsonEncode(radiusCodec.toJsonSchema()), contains('"minimum":0')); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/rect_test.dart b/packages/flutter_codec/test/primitives/rect_test.dart new file mode 100644 index 00000000..1a6da05b --- /dev/null +++ b/packages/flutter_codec/test/primitives/rect_test.dart @@ -0,0 +1,62 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('rectCodec decode', () { + test('decodes a {left, top, right, bottom} object', () { + expect( + rectCodec.parse({'left': 1, 'top': 2, 'right': 30, 'bottom': 40}), + const Rect.fromLTRB(1, 2, 30, 40), + ); + }); + + test('accepts integer coordinates as doubles', () { + expect( + rectCodec.parse({'left': 0, 'top': 0, 'right': 10, 'bottom': 10}), + const Rect.fromLTRB(0, 0, 10, 10), + ); + }); + }); + + group('rectCodec encode', () { + test('emits a canonical {left, top, right, bottom} map', () { + final encoded = rectCodec.encode(const Rect.fromLTRB(1, 2, 30, 40)); + expect(encoded, {'left': 1.0, 'top': 2.0, 'right': 30.0, 'bottom': 40.0}); + expectJsonSafe(encoded); + }); + + test('round-trips an arbitrary rect', () { + const rect = Rect.fromLTRB(-5.5, 12.25, 100, 0); + expect(rectCodec.parse(rectCodec.encode(rect)!), rect); + }); + }); + + group('rectCodec rejects invalid input', () { + const invalidCases = { + 'missing left': {'top': 0, 'right': 10, 'bottom': 10}, + 'missing bottom': {'left': 0, 'top': 0, 'right': 10}, + 'non-finite right': { + 'left': 0, + 'top': 0, + 'right': double.infinity, + 'bottom': 10, + }, + 'unknown key': { + 'left': 0, + 'top': 0, + 'right': 10, + 'bottom': 10, + 'width': 10, + }, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(rectCodec.safeParse(input).isFail, isTrue); + }); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/text_decoration_test.dart b/packages/flutter_codec/test/primitives/text_decoration_test.dart new file mode 100644 index 00000000..f6f0a9f9 --- /dev/null +++ b/packages/flutter_codec/test/primitives/text_decoration_test.dart @@ -0,0 +1,90 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('textDecorationCodec decode', () { + const atomic = { + 'none': TextDecoration.none, + 'underline': TextDecoration.underline, + 'overline': TextDecoration.overline, + 'lineThrough': TextDecoration.lineThrough, + }; + + atomic.forEach((name, value) { + test('decodes "$name"', () { + expect(textDecorationCodec.parse(name), value); + }); + }); + + test('decodes a combined list', () { + expect( + textDecorationCodec.parse(['underline', 'overline']), + TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.overline, + ]), + ); + }); + + test('decodes an empty list as none', () { + expect(textDecorationCodec.parse([]), TextDecoration.none); + }); + + test('filters none out of combined lists', () { + expect( + textDecorationCodec.parse(['none', 'underline']), + TextDecoration.underline, + ); + }); + }); + + group('textDecorationCodec encode', () { + const atomic = [ + (TextDecoration.none, 'none'), + (TextDecoration.underline, 'underline'), + (TextDecoration.overline, 'overline'), + (TextDecoration.lineThrough, 'lineThrough'), + ]; + + for (final (value, name) in atomic) { + test('encodes $value as "$name"', () { + final encoded = textDecorationCodec.encode(value); + expect(encoded, name); + expectJsonSafe(encoded); + }); + } + + test('encodes a combined decoration as participating aliases', () { + final encoded = textDecorationCodec.encode( + TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.overline, + ]), + ); + + expect(encoded, ['underline', 'overline']); + expectJsonSafe(encoded); + }); + + test('encodes atomic values as bare strings, not single-item lists', () { + expect(textDecorationCodec.encode(TextDecoration.underline), 'underline'); + expect(textDecorationCodec.encode(TextDecoration.none), 'none'); + }); + }); + + group('textDecorationCodec rejects invalid input', () { + test('rejects unknown strings', () { + expect(textDecorationCodec.safeParse('blink').isFail, isTrue); + }); + + test('rejects unknown list entries', () { + expect( + textDecorationCodec.safeParse(['underline', 'blink']).isFail, + isTrue, + ); + }); + }); +} diff --git a/packages/flutter_codec/test/primitives/text_height_behavior_test.dart b/packages/flutter_codec/test/primitives/text_height_behavior_test.dart new file mode 100644 index 00000000..d0bcbcb5 --- /dev/null +++ b/packages/flutter_codec/test/primitives/text_height_behavior_test.dart @@ -0,0 +1,74 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('textHeightBehaviorCodec decode', () { + test('decodes an empty object as the default TextHeightBehavior', () { + expect(textHeightBehaviorCodec.parse({}), const TextHeightBehavior()); + }); + + test('decodes a fully-specified object', () { + expect( + textHeightBehaviorCodec.parse({ + 'applyHeightToFirstAscent': false, + 'applyHeightToLastDescent': false, + 'leadingDistribution': 'even', + }), + const TextHeightBehavior( + applyHeightToFirstAscent: false, + applyHeightToLastDescent: false, + leadingDistribution: TextLeadingDistribution.even, + ), + ); + }); + }); + + group('textHeightBehaviorCodec encode', () { + test('emits the canonical map with all three fields', () { + final encoded = textHeightBehaviorCodec.encode( + const TextHeightBehavior(), + ); + expect(encoded, { + 'applyHeightToFirstAscent': true, + 'applyHeightToLastDescent': true, + 'leadingDistribution': 'proportional', + }); + expectJsonSafe(encoded); + }); + + test('round-trips a non-default behavior', () { + const original = TextHeightBehavior( + applyHeightToFirstAscent: false, + leadingDistribution: TextLeadingDistribution.even, + ); + expect( + textHeightBehaviorCodec.parse(textHeightBehaviorCodec.encode(original)), + original, + ); + }); + }); + + group('textHeightBehaviorCodec rejects invalid input', () { + test('rejects an unknown leadingDistribution', () { + expect( + textHeightBehaviorCodec.safeParse({ + 'leadingDistribution': 'centered', + }).isFail, + isTrue, + ); + }); + + test('rejects unknown keys', () { + expect( + textHeightBehaviorCodec.safeParse({ + 'applyHeightToFirstAscent': true, + 'extra': 1, + }).isFail, + isTrue, + ); + }); + }); +} diff --git a/packages/flutter_codec/test/public_api_contract_test.dart b/packages/flutter_codec/test/public_api_contract_test.dart new file mode 100644 index 00000000..4c1393ac --- /dev/null +++ b/packages/flutter_codec/test/public_api_contract_test.dart @@ -0,0 +1,27 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('README workflow works through the public package entry point', () { + final decoration = BoxDecoration( + color: const Color(0xFF2196F3), + border: Border.all(color: const Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + gradient: const LinearGradient( + colors: [Color(0xFFFF0000), Color(0xFF0000FF)], + ), + ); + + final encoded = boxDecorationCodec.safeEncode(decoration); + expect(encoded.isOk, isTrue); + + final json = jsonDecode(jsonEncode(encoded.getOrNull())); + final decoded = boxDecorationCodec.safeParse(json); + + expect(decoded.getOrNull(), decoration); + expect(jsonEncode(boxDecorationCodec.toJsonSchema()), isNotEmpty); + }); +} diff --git a/packages/flutter_codec/test/shadows/shadows_test.dart b/packages/flutter_codec/test/shadows/shadows_test.dart new file mode 100644 index 00000000..253c59d4 --- /dev/null +++ b/packages/flutter_codec/test/shadows/shadows_test.dart @@ -0,0 +1,160 @@ +import 'dart:ui' as ui show Shadow; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('shadowCodec decode', () { + test('parses {} as the default ui.Shadow', () { + expect(shadowCodec.parse({}), const ui.Shadow()); + }); + + test('applies defaults to a partial object', () { + expect( + shadowCodec.parse({'color': '#FF0000'}), + const ui.Shadow(color: Color(0xFFFF0000)), + ); + }); + + test('parses a full object', () { + expect( + shadowCodec.parse({ + 'color': '#FF0000', + 'offset': {'x': 2, 'y': 4}, + 'blurRadius': 6, + }), + const ui.Shadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + ), + ); + }); + }); + + group('shadowCodec encode', () { + test('emits a full canonical object including defaults', () { + final encoded = shadowCodec.encode(const ui.Shadow()); + expect(encoded, { + 'color': '#000000', + 'offset': {'x': 0.0, 'y': 0.0}, + 'blurRadius': 0.0, + }); + expectJsonSafe(encoded); + }); + + test('encodes a customized Shadow', () { + final encoded = shadowCodec.encode( + const ui.Shadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + ), + ); + expect(encoded, { + 'color': '#FF0000', + 'offset': {'x': 2.0, 'y': 4.0}, + 'blurRadius': 6.0, + }); + expectJsonSafe(encoded); + }); + }); + + group('shadowCodec rejects invalid input', () { + const invalidCases = { + 'negative blurRadius': {'blurRadius': -1}, + 'non-finite blurRadius': {'blurRadius': double.infinity}, + 'invalid color': {'color': 'not-a-color'}, + 'extra property': {'unexpected': true}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(shadowCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('boxShadowCodec decode', () { + test('parses {} as the default BoxShadow', () { + expect(boxShadowCodec.parse({}), const BoxShadow()); + }); + + test('parses a full object including spreadRadius + blurStyle', () { + expect( + boxShadowCodec.parse({ + 'color': '#FF0000', + 'offset': {'x': 2, 'y': 4}, + 'blurRadius': 6, + 'spreadRadius': 1, + 'blurStyle': 'outer', + }), + const BoxShadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + spreadRadius: 1, + blurStyle: BlurStyle.outer, + ), + ); + }); + + test('accepts negative spreadRadius (Flutter allows shrinking)', () { + expect( + boxShadowCodec.parse({'spreadRadius': -2}), + const BoxShadow(spreadRadius: -2), + ); + }); + }); + + group('boxShadowCodec encode', () { + test('emits a full canonical object including defaults', () { + final encoded = boxShadowCodec.encode(const BoxShadow()); + expect(encoded, { + 'color': '#000000', + 'offset': {'x': 0.0, 'y': 0.0}, + 'blurRadius': 0.0, + 'spreadRadius': 0.0, + 'blurStyle': 'normal', + }); + expectJsonSafe(encoded); + }); + + test('encodes a customized BoxShadow', () { + final encoded = boxShadowCodec.encode( + const BoxShadow( + color: Color(0xFFFF0000), + offset: Offset(2, 4), + blurRadius: 6, + spreadRadius: 1, + blurStyle: BlurStyle.outer, + ), + ); + expect(encoded, { + 'color': '#FF0000', + 'offset': {'x': 2.0, 'y': 4.0}, + 'blurRadius': 6.0, + 'spreadRadius': 1.0, + 'blurStyle': 'outer', + }); + expectJsonSafe(encoded); + }); + }); + + group('boxShadowCodec rejects invalid input', () { + const invalidCases = { + 'negative blurRadius': {'blurRadius': -1}, + 'invalid blurStyle': {'blurStyle': 'fuzzy'}, + 'extra property': {'unexpected': true}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(boxShadowCodec.safeParse(input).isFail, isTrue); + }); + }); + }); +} diff --git a/packages/flutter_codec/test/shape_borders/shape_borders_test.dart b/packages/flutter_codec/test/shape_borders/shape_borders_test.dart new file mode 100644 index 00000000..c84ccb89 --- /dev/null +++ b/packages/flutter_codec/test/shape_borders/shape_borders_test.dart @@ -0,0 +1,380 @@ +import 'dart:convert'; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('circleBorderCodec', () { + test('decodes an empty object as the default CircleBorder', () { + expect(circleBorderCodec.parse({}), const CircleBorder()); + }); + + test('decodes side and eccentricity', () { + expect( + circleBorderCodec.parse({ + 'side': {'color': '#FF0000', 'width': 2}, + 'eccentricity': 0.5, + }), + CircleBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + eccentricity: 0.5, + ), + ); + }); + + test('encode emits the canonical map with both fields', () { + final encoded = circleBorderCodec.encode(const CircleBorder()); + expect(encoded, {'side': 'none', 'eccentricity': 0.0}); + expectJsonSafe(encoded); + }); + + test('rejects eccentricity outside [0, 1]', () { + expect(circleBorderCodec.safeParse({'eccentricity': 1.5}).isFail, isTrue); + expect( + circleBorderCodec.safeParse({'eccentricity': -0.1}).isFail, + isTrue, + ); + }); + }); + + group('stadiumBorderCodec', () { + test('decodes an empty object as the default StadiumBorder', () { + expect(stadiumBorderCodec.parse({}), const StadiumBorder()); + }); + + test('round-trips a sided StadiumBorder', () { + final original = const StadiumBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 3), + ); + expect( + stadiumBorderCodec.parse(stadiumBorderCodec.encode(original)), + original, + ); + }); + }); + + group('roundedRectangleBorderCodec', () { + test('decodes an empty object as the default RoundedRectangleBorder', () { + expect( + roundedRectangleBorderCodec.parse({}), + const RoundedRectangleBorder(), + ); + }); + + test('round-trips side and borderRadius', () { + final original = RoundedRectangleBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(12), + ); + expect( + roundedRectangleBorderCodec.parse( + roundedRectangleBorderCodec.encode(original), + ), + original, + ); + }); + }); + + group('beveledRectangleBorderCodec / continuousRectangleBorderCodec / ' + 'roundedSuperellipseBorderCodec', () { + test('each decodes its empty default and round-trips', () { + expect( + beveledRectangleBorderCodec.parse({}), + const BeveledRectangleBorder(), + ); + expect( + continuousRectangleBorderCodec.parse({}), + const ContinuousRectangleBorder(), + ); + expect( + roundedSuperellipseBorderCodec.parse({}), + const RoundedSuperellipseBorder(), + ); + + final beveled = BeveledRectangleBorder( + borderRadius: BorderRadius.circular(4), + ); + expect( + beveledRectangleBorderCodec.parse( + beveledRectangleBorderCodec.encode(beveled), + ), + beveled, + ); + + final continuous = ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(4), + ); + expect( + continuousRectangleBorderCodec.parse( + continuousRectangleBorderCodec.encode(continuous), + ), + continuous, + ); + + final superellipse = RoundedSuperellipseBorder( + side: const BorderSide(color: Color(0xFFFF0000), width: 2), + borderRadius: BorderRadius.circular(8), + ); + expect( + roundedSuperellipseBorderCodec.parse( + roundedSuperellipseBorderCodec.encode(superellipse), + ), + superellipse, + ); + }); + }); + + group('starBorderCodec', () { + test('decodes an empty object as the default StarBorder', () { + expect(starBorderCodec.parse({}), const StarBorder()); + }); + + test('decodes a fully-specified star', () { + expect( + starBorderCodec.parse({ + 'side': {'color': '#FF0000', 'width': 2}, + 'points': 6, + 'innerRadiusRatio': 0.5, + 'pointRounding': 0.1, + 'valleyRounding': 0.2, + 'rotation': 45, + 'squash': 0.3, + }), + const StarBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + points: 6, + innerRadiusRatio: 0.5, + pointRounding: 0.1, + valleyRounding: 0.2, + rotation: 45, + squash: 0.3, + ), + ); + }); + + test('round-trips a populated StarBorder', () { + const original = StarBorder(points: 7, innerRadiusRatio: 0.3); + expect(starBorderCodec.parse(starBorderCodec.encode(original)), original); + }); + + test('encodes StarBorder.polygon as the equivalent regular StarBorder', () { + final polygon = StarBorder.polygon(sides: 6); + final encoded = starBorderCodec.encode(polygon)!; + expect(encoded['points'], 6); + expect(encoded['valleyRounding'], 0.0); + // innerRadiusRatio resolves to the polygon incircle (cos(pi/6)). + expect(encoded['innerRadiusRatio'], closeTo(0.866, 0.001)); + }); + + test('StarBorder.polygon narrows to a regular StarBorder (lossy ==)', () { + // .polygon stores a null innerRadiusRatio; the codec re-decodes through + // the regular constructor with the resolved value, so == does not hold, + // but the result is painted-equivalent and itself round-trips stably. + final polygon = StarBorder.polygon(sides: 6); + final roundTripped = starBorderCodec.parse( + starBorderCodec.encode(polygon), + )!; + expect(roundTripped, isNot(polygon)); + expect( + starBorderCodec.parse(starBorderCodec.encode(roundTripped)), + roundTripped, + ); + }); + + test('StarBorder.rotation is preserved to float precision (lossy ==)', () { + // rotation is stored internally as radians; degrees->radians->degrees is + // not bit-stable, so == may not hold, but the painted rotation survives. + const original = StarBorder(rotation: 12); + final roundTripped = starBorderCodec.parse( + starBorderCodec.encode(original), + )!; + expect(roundTripped.rotation, closeTo(12, 1e-9)); + }); + + test('rejects fewer than two points', () { + expect(starBorderCodec.safeParse({'points': 1}).isFail, isTrue); + }); + + test('rejects innerRadiusRatio outside [0, 1]', () { + expect( + starBorderCodec.safeParse({'innerRadiusRatio': 1.5}).isFail, + isTrue, + ); + }); + + test('rejects point and valley rounding sums above one', () { + expect( + starBorderCodec.safeParse({ + 'pointRounding': 0.7, + 'valleyRounding': 0.6, + }).isFail, + isTrue, + ); + }); + + test('accepts point and valley rounding sum at one', () { + final parsed = starBorderCodec.parse({ + 'pointRounding': 0.5, + 'valleyRounding': 0.5, + })!; + + expect(parsed.pointRounding, 0.5); + expect(parsed.valleyRounding, 0.5); + expect(starBorderCodec.parse(starBorderCodec.encode(parsed)), parsed); + }); + }); + + group('linearBorderEdgeCodec', () { + test('decodes an empty object as the default LinearBorderEdge', () { + expect(linearBorderEdgeCodec.parse({}), const LinearBorderEdge()); + }); + + test('round-trips a non-default edge', () { + const original = LinearBorderEdge(size: 0.5, alignment: -0.25); + expect( + linearBorderEdgeCodec.parse(linearBorderEdgeCodec.encode(original)), + original, + ); + }); + + test('rejects size outside [0, 1]', () { + expect(linearBorderEdgeCodec.safeParse({'size': 1.5}).isFail, isTrue); + }); + + test('rejects alignment outside [-1, 1]', () { + expect( + linearBorderEdgeCodec.safeParse({'alignment': 1.5}).isFail, + isTrue, + ); + }); + }); + + group('linearBorderCodec', () { + test('decodes an empty object as the default LinearBorder', () { + expect(linearBorderCodec.parse({}), const LinearBorder()); + }); + + test('decodes a bottom-edge LinearBorder', () { + expect( + linearBorderCodec.parse({ + 'bottom': {'size': 0.75, 'alignment': 0.5}, + }), + const LinearBorder( + bottom: LinearBorderEdge(size: 0.75, alignment: 0.5), + ), + ); + }); + + test('round-trips a populated LinearBorder', () { + const original = LinearBorder( + side: BorderSide(color: Color(0xFFFF0000), width: 2), + start: LinearBorderEdge(size: 0.5), + top: LinearBorderEdge(alignment: -1), + ); + expect( + linearBorderCodec.parse(linearBorderCodec.encode(original)), + original, + ); + }); + + test('LinearBorder.start round-trips through the regular constructor', () { + final original = LinearBorder.start(size: 0.5, alignment: 0.25); + expect( + linearBorderCodec.parse(linearBorderCodec.encode(original))!.start, + original.start, + ); + }); + }); + + group('shapeBorderCodec', () { + test('decodes each discriminator value to the matching ShapeBorder', () { + expect(shapeBorderCodec.parse({'type': 'circle'}), const CircleBorder()); + expect( + shapeBorderCodec.parse({'type': 'stadium'}), + const StadiumBorder(), + ); + expect( + shapeBorderCodec.parse({'type': 'roundedRectangle'}), + const RoundedRectangleBorder(), + ); + expect( + shapeBorderCodec.parse({'type': 'beveledRectangle'}), + const BeveledRectangleBorder(), + ); + expect( + shapeBorderCodec.parse({'type': 'continuousRectangle'}), + const ContinuousRectangleBorder(), + ); + expect( + shapeBorderCodec.parse({'type': 'roundedSuperellipse'}), + const RoundedSuperellipseBorder(), + ); + expect(shapeBorderCodec.parse({'type': 'star'}), const StarBorder()); + expect(shapeBorderCodec.parse({'type': 'linear'}), const LinearBorder()); + }); + + test('encode dispatches by runtime ShapeBorder subtype', () { + expect(shapeBorderCodec.encode(const CircleBorder()), { + 'type': 'circle', + 'side': 'none', + 'eccentricity': 0.0, + }); + expect(shapeBorderCodec.encode(const StadiumBorder()), { + 'type': 'stadium', + 'side': 'none', + }); + final rounded = shapeBorderCodec.encode(const RoundedRectangleBorder()); + expect(rounded, containsPair('type', 'roundedRectangle')); + expect(rounded, containsPair('side', 'none')); + final superellipse = shapeBorderCodec.encode( + const RoundedSuperellipseBorder(), + ); + expect(superellipse, containsPair('type', 'roundedSuperellipse')); + expect(superellipse, containsPair('side', 'none')); + final star = shapeBorderCodec.encode(const StarBorder()); + expect(star, containsPair('type', 'star')); + expect(star, containsPair('points', 5)); + final linear = shapeBorderCodec.encode(const LinearBorder()); + expect(linear, containsPair('type', 'linear')); + expect(linear, containsPair('start', null)); + }); + + test('rejects an unknown discriminator', () { + expect(shapeBorderCodec.safeParse({'type': 'oval'}).isFail, isTrue); + }); + + test('rejects a missing discriminator', () { + expect(shapeBorderCodec.safeParse({}).isFail, isTrue); + }); + + test('narrows OvalBorder to the circle branch (documented narrowing)', () { + // OvalBorder extends CircleBorder, so the union routes it to "circle" + // and it round-trips as the painted-equivalent CircleBorder(ecc: 1.0). + final encoded = shapeBorderCodec.encode(const OvalBorder())!; + expect(encoded, containsPair('type', 'circle')); + expect( + shapeBorderCodec.parse(encoded), + const CircleBorder(eccentricity: 1.0), + ); + }); + + test('JSON Schema surfaces all eight discriminator branches', () { + final schema = jsonEncode(shapeBorderCodec.toJsonSchema()); + for (final value in const [ + 'circle', + 'stadium', + 'roundedRectangle', + 'beveledRectangle', + 'continuousRectangle', + 'roundedSuperellipse', + 'star', + 'linear', + ]) { + expect(schema, contains('"$value"')); + } + }); + }); +} diff --git a/packages/flutter_codec/test/strut_style/strut_style_test.dart b/packages/flutter_codec/test/strut_style/strut_style_test.dart new file mode 100644 index 00000000..3c7d6f3f --- /dev/null +++ b/packages/flutter_codec/test/strut_style/strut_style_test.dart @@ -0,0 +1,152 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('strutStyleCodec decode', () { + test('decodes an empty object as the default StrutStyle', () { + expect(strutStyleCodec.parse({}), const StrutStyle()); + }); + + test('decodes a full real-world StrutStyle', () { + expect( + strutStyleCodec.parse({ + 'fontFamily': 'Roboto', + 'fontFamilyFallback': ['Arial', 'sans-serif'], + 'fontSize': 14.0, + 'height': 1.2, + 'leadingDistribution': 'even', + 'leading': 0.5, + 'fontWeight': 'w500', + 'fontStyle': 'italic', + 'forceStrutHeight': true, + }), + const StrutStyle( + fontFamily: 'Roboto', + fontFamilyFallback: ['Arial', 'sans-serif'], + fontSize: 14.0, + height: 1.2, + leadingDistribution: TextLeadingDistribution.even, + leading: 0.5, + fontWeight: FontWeight.w500, + fontStyle: FontStyle.italic, + forceStrutHeight: true, + ), + ); + }); + + test('decodes (fontFamily, package) and produces the folded form', () { + final decoded = strutStyleCodec.parse({ + 'fontFamily': 'Roboto', + 'package': 'my_pkg', + }); + // StrutStyle's constructor folds package into fontFamily. + expect(decoded!.fontFamily, 'packages/my_pkg/Roboto'); + }); + + test('decodes package with only fontFamilyFallback', () { + final decoded = strutStyleCodec.parse({ + 'package': 'my_pkg', + 'fontFamilyFallback': ['Roboto'], + }); + + expect(decoded!.fontFamilyFallback, ['packages/my_pkg/Roboto']); + }); + }); + + group('strutStyleCodec encode', () { + test('emits explicit nulls for unset fields', () { + final encoded = strutStyleCodec.encode(const StrutStyle()); + expect(encoded, { + 'fontFamily': null, + 'fontFamilyFallback': null, + 'package': null, + 'fontSize': null, + 'height': null, + 'leadingDistribution': null, + 'leading': null, + 'fontWeight': null, + 'fontStyle': null, + 'forceStrutHeight': null, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a populated StrutStyle', () { + const original = StrutStyle( + fontFamily: 'Roboto', + fontSize: 16.0, + height: 1.5, + fontWeight: FontWeight.w700, + forceStrutHeight: false, + ); + expect(strutStyleCodec.parse(strutStyleCodec.encode(original)), original); + }); + + test('unfolds packages// back to (fontFamily, package)', () { + const original = StrutStyle(fontFamily: 'Roboto', package: 'my_pkg'); + final encoded = strutStyleCodec.encode(original)!; + expect(encoded['fontFamily'], 'Roboto'); + expect(encoded['package'], 'my_pkg'); + }); + + test('round-trips a package-prefixed fallback with a null fontFamily', () { + // A package must not be inferred from the fallback alone: re-folding a + // null fontFamily with a package yields the literal 'packages//null'. + const original = StrutStyle( + fontFamilyFallback: ['packages/foo/Bar', 'packages/foo/Baz'], + ); + final roundTripped = strutStyleCodec.parse( + strutStyleCodec.encode(original), + ); + expect(roundTripped, original); + expect(roundTripped!.fontFamily, isNull); + }); + }); + + group('strutStyleCodec rejects invalid input', () { + test('rejects package without a font family', () { + final result = strutStyleCodec.safeParse({'package': 'my_pkg'}); + + expect(result.isFail, isTrue); + expect( + result.getError().toString(), + contains( + 'StrutStyle package requires fontFamily or fontFamilyFallback.', + ), + ); + }); + + test('rejects package with an empty fontFamilyFallback', () { + // Flutter treats an empty fallback list as omitted, and still interpolates + // a null fontFamily into the literal 'packages//null'. + final result = strutStyleCodec.safeParse({ + 'package': 'my_pkg', + 'fontFamilyFallback': [], + }); + + expect(result.isFail, isTrue); + expect( + result.getError().toString(), + contains( + 'StrutStyle package requires fontFamily or fontFamilyFallback.', + ), + ); + }); + + test('rejects a non-positive fontSize', () { + expect(strutStyleCodec.safeParse({'fontSize': 0}).isFail, isTrue); + expect(strutStyleCodec.safeParse({'fontSize': -1}).isFail, isTrue); + }); + + test('rejects a negative leading', () { + expect(strutStyleCodec.safeParse({'leading': -0.5}).isFail, isTrue); + }); + + test('rejects unknown keys', () { + expect(strutStyleCodec.safeParse({'extra': 1}).isFail, isTrue); + }); + }); +} diff --git a/packages/flutter_codec/test/support/json_safety.dart b/packages/flutter_codec/test/support/json_safety.dart new file mode 100644 index 00000000..f4c4bd70 --- /dev/null +++ b/packages/flutter_codec/test/support/json_safety.dart @@ -0,0 +1,45 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; + +/// Returns the path of the first non-JSON-safe value in [value], or null when +/// the whole structure is JSON-safe. Mirrors ack's `_jsonSafeOrNull` +/// (packages/ack/lib/src/schemas/schema.dart): JSON values are null, a finite +/// num, a bool, or a String; JSON collections are Lists of JSON values or +/// `Map`, recursively. +String? jsonSafetyViolation(Object? value, [String path = r'$']) { + if (value == null || value is bool || value is String) return null; + if (value is num) { + return value.isFinite ? null : '$path: non-finite number ($value)'; + } + if (value is List) { + for (var i = 0; i < value.length; i++) { + final violation = jsonSafetyViolation(value[i], '$path[$i]'); + if (violation != null) return violation; + } + return null; + } + if (value is Map) { + for (final entry in value.entries) { + if (entry.key is! String) { + return '$path: non-string key (${entry.key.runtimeType})'; + } + final violation = jsonSafetyViolation(entry.value, '$path.${entry.key}'); + if (violation != null) return violation; + } + return null; + } + + return '$path: non-JSON value of type ${value.runtimeType}'; +} + +/// Asserts [value] is composed solely of JSON values/collections and survives +/// a real `jsonEncode` round-trip. +void expectJsonSafe(Object? value) { + expect( + jsonSafetyViolation(value), + isNull, + reason: 'Encoded output is not JSON-safe', + ); + expect(() => jsonEncode(value), returnsNormally); +} diff --git a/packages/flutter_codec/test/support/json_safety_test.dart b/packages/flutter_codec/test/support/json_safety_test.dart new file mode 100644 index 00000000..dccae1c0 --- /dev/null +++ b/packages/flutter_codec/test/support/json_safety_test.dart @@ -0,0 +1,48 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'json_safety.dart'; + +void main() { + group('jsonSafetyViolation accepts JSON values', () { + for (final value in [ + null, + true, + 'text', + 1, + 1.5, + [1, 'a', null], + { + 'k': [1, true], + 'nested': {'x': 2.0}, + }, + ]) { + test('$value', () { + expect(jsonSafetyViolation(value), isNull); + expectJsonSafe(value); + }); + } + }); + + group('jsonSafetyViolation flags non-JSON content', () { + test('reports the path of a leaked runtime object', () { + final violation = jsonSafetyViolation({'color': Object()}); + expect(violation, r'$.color: non-JSON value of type Object'); + }); + + test('rejects non-finite numbers', () { + expect(jsonSafetyViolation(double.infinity), isNotNull); + expect(jsonSafetyViolation(double.nan), isNotNull); + }); + + test('rejects non-string map keys', () { + expect(jsonSafetyViolation({1: 'a'}), isNotNull); + }); + + test('expectJsonSafe fails when a runtime object leaks', () { + expect( + () => expectJsonSafe({'color': Object()}), + throwsA(isA()), + ); + }); + }); +} diff --git a/packages/flutter_codec/test/text_style/text_style_test.dart b/packages/flutter_codec/test/text_style/text_style_test.dart new file mode 100644 index 00000000..78cae5b4 --- /dev/null +++ b/packages/flutter_codec/test/text_style/text_style_test.dart @@ -0,0 +1,258 @@ +import 'dart:convert'; +import 'dart:ui' as ui show Locale, Paint, Shadow; + +import 'package:flutter/painting.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('textStyleCodec decode', () { + test('decodes inherit-only input as the default TextStyle', () { + expect(textStyleCodec.parse({'inherit': true}), const TextStyle()); + }); + + test('decodes a full real-world TextStyle', () { + expect( + textStyleCodec.parse({ + 'inherit': true, + 'color': '#2196F3', + 'backgroundColor': '#FFFDE7', + 'fontSize': 18, + 'fontWeight': 'bold', + 'fontStyle': 'italic', + 'letterSpacing': 0.25, + 'wordSpacing': 1.5, + 'textBaseline': 'alphabetic', + 'height': 1.3, + 'leadingDistribution': 'even', + 'locale': 'en-US', + 'shadows': [ + { + 'color': '#55000000', + 'offset': {'x': 1, 'y': 2}, + 'blurRadius': 3, + }, + ], + 'decoration': ['underline', 'overline'], + 'decorationColor': '#FF0000', + 'decorationStyle': 'dashed', + 'decorationThickness': 2, + 'fontFamily': 'Inter', + 'fontFamilyFallback': ['Roboto', 'Arial'], + 'package': 'my_package', + 'overflow': 'ellipsis', + 'fontFeatures': [ + {'feature': 'smcp', 'value': 1}, + {'feature': 'liga'}, + ], + 'fontVariations': [ + {'axis': 'wght', 'value': 600}, + {'axis': 'wdth', 'value': 100}, + ], + }), + TextStyle( + color: const Color(0xFF2196F3), + backgroundColor: const Color(0xFFFFFDE7), + fontSize: 18, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + letterSpacing: 0.25, + wordSpacing: 1.5, + textBaseline: TextBaseline.alphabetic, + height: 1.3, + leadingDistribution: TextLeadingDistribution.even, + locale: const ui.Locale('en', 'US'), + shadows: const [ + ui.Shadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + ), + ], + decoration: TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.overline, + ]), + decorationColor: const Color(0xFFFF0000), + decorationStyle: TextDecorationStyle.dashed, + decorationThickness: 2, + fontFamily: 'Inter', + fontFamilyFallback: const ['Roboto', 'Arial'], + package: 'my_package', + overflow: TextOverflow.ellipsis, + fontFeatures: const [FontFeature('smcp'), FontFeature('liga')], + fontVariations: const [ + FontVariation('wght', 600), + FontVariation('wdth', 100), + ], + ), + ); + }); + }); + + group('textStyleCodec encode', () { + test('emits a full canonical map with explicit nulls for defaults', () { + final encoded = textStyleCodec.encode(const TextStyle()); + + expect(encoded, { + 'inherit': true, + 'color': null, + 'backgroundColor': null, + 'fontSize': null, + 'fontWeight': null, + 'fontStyle': null, + 'letterSpacing': null, + 'wordSpacing': null, + 'textBaseline': null, + 'height': null, + 'leadingDistribution': null, + 'locale': null, + 'shadows': null, + 'decoration': null, + 'decorationColor': null, + 'decorationStyle': null, + 'decorationThickness': null, + 'fontFamily': null, + 'fontFamilyFallback': null, + 'package': null, + 'overflow': null, + 'fontFeatures': null, + 'fontVariations': null, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a full TextStyle', () { + final original = TextStyle( + inherit: false, + color: const Color(0xFF2196F3), + backgroundColor: const Color(0xFFFFFDE7), + fontSize: 18, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + letterSpacing: 0.25, + wordSpacing: 1.5, + textBaseline: TextBaseline.alphabetic, + height: 1.3, + leadingDistribution: TextLeadingDistribution.even, + locale: const ui.Locale('zh', 'CN'), + shadows: const [ + ui.Shadow( + color: Color(0x55000000), + offset: Offset(1, 2), + blurRadius: 3, + ), + ], + decoration: TextDecoration.combine([ + TextDecoration.underline, + TextDecoration.overline, + ]), + decorationColor: const Color(0xFFFF0000), + decorationStyle: TextDecorationStyle.dashed, + decorationThickness: 2, + fontFamily: 'Inter', + fontFamilyFallback: const ['Roboto', 'Arial'], + package: 'my_package', + overflow: TextOverflow.ellipsis, + fontFeatures: const [FontFeature('smcp'), FontFeature('cv01', 3)], + fontVariations: const [ + FontVariation('wght', 500), + FontVariation('slnt', -10), + ], + ); + + final encoded = textStyleCodec.encode(original); + + expect(textStyleCodec.parse(encoded), original); + expectJsonSafe(encoded); + }); + + test('round-trips a package-prefixed fallback with a null fontFamily', () { + // A package must not be inferred from the fallback alone: re-folding a + // null fontFamily with a package yields the literal 'packages//null'. + const original = TextStyle( + fontFamilyFallback: ['packages/foo/Bar', 'packages/foo/Baz'], + ); + final roundTripped = textStyleCodec.parse( + textStyleCodec.encode(original), + ); + expect(roundTripped, original); + expect(roundTripped!.fontFamily, isNull); + }); + + test('preserves a literal packages// fontFamily string', () { + // A literal 'packages/...' family supplied without a package: argument is + // intentionally read back as package-qualified (the common case). The + // resolved font family string is preserved, though TextStyle equality + // does not hold because the private _package differs. + const original = TextStyle(fontFamily: 'packages/foo/Bar'); + final roundTripped = textStyleCodec.parse( + textStyleCodec.encode(original), + ); + expect(roundTripped!.fontFamily, 'packages/foo/Bar'); + }); + + test('encodes a package with no fontFamily as a null family', () { + // TextStyle(package: 'my_pkg') with no fontFamily folds to the literal + // 'packages/my_pkg/null'. Encode must recover a genuine null primary + // family (not the four-char string 'null') so the JSON is valid for any + // consumer, and it must still round-trip. + const original = TextStyle(package: 'my_pkg'); + final encoded = textStyleCodec.encode(original) as Map; + expect(encoded['fontFamily'], isNull); + expect(encoded['package'], 'my_pkg'); + expect(textStyleCodec.parse(encoded), original); + }); + }); + + group('textStyleCodec rejects invalid input', () { + const invalidCases = { + 'unknown keys': {'inherit': true, 'foo': 1}, + 'invalid fontWeight': {'fontWeight': 'heavy'}, + 'invalid decoration': {'decoration': 'blink'}, + 'invalid color': {'color': 'not-a-color'}, + 'zero fontSize': {'fontSize': 0}, + 'negative fontSize': {'fontSize': -1}, + }; + + invalidCases.forEach((name, input) { + test('rejects $name', () { + expect(textStyleCodec.safeParse(input).isFail, isTrue); + }); + }); + }); + + group('textStyleCodec rejects unsupported paint fields on encode', () { + test('fails to encode a foreground Paint', () { + // foreground is a Paint with no JSON shape; it must fail loudly rather + // than drop to a colorless style. + final result = textStyleCodec.safeEncode( + TextStyle(foreground: ui.Paint()), + ); + expect(result.isFail, isTrue); + }); + + test('fails to encode a background Paint', () { + final result = textStyleCodec.safeEncode( + TextStyle(background: ui.Paint()), + ); + expect(result.isFail, isTrue); + }); + }); + + group('textStyleCodec JSON Schema', () { + test('dependent codec enums flow through composition', () { + final schema = jsonEncode(textStyleCodec.toJsonSchema()); + // textDecorationCodec emits its atomic aliases as an enum; the + // composed object lifts that enum into its property schema. + expect( + schema, + contains('"enum":["none","underline","overline","lineThrough"]'), + ); + // fontWeightCodec's enum branch surfaces the same way. + expect(schema, contains('"enum":["w100"')); + }); + }); +} diff --git a/packages/flutter_codec/test/widgets/container_test.dart b/packages/flutter_codec/test/widgets/container_test.dart new file mode 100644 index 00000000..1928d24d --- /dev/null +++ b/packages/flutter_codec/test/widgets/container_test.dart @@ -0,0 +1,244 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('containerWidgetCodec decode', () { + test('decodes an empty object as the default Container shape', () { + final parsed = containerWidgetCodec.parse({})!; + + expect(parsed.key, isNull); + expect(parsed.alignment, isNull); + expect(parsed.padding, isNull); + expect(parsed.color, isNull); + expect(parsed.isAntiAlias, isTrue); + expect(parsed.decoration, isNull); + expect(parsed.foregroundDecoration, isNull); + expect(parsed.constraints, isNull); + expect(parsed.margin, isNull); + expect(parsed.transform, isNull); + expect(parsed.transformAlignment, isNull); + expect(parsed.clipBehavior, Clip.none); + expect(parsed.child, isNull); + }); + + test('accepts width and height constructor shorthands', () { + final parsed = containerWidgetCodec.parse({'width': 10, 'height': 20})!; + + expect( + parsed.constraints, + BoxConstraints.tightFor(width: 10, height: 20), + ); + }); + }); + + group('containerWidgetCodec encode', () { + test('emits a full canonical map with explicit nulls for defaults', () { + final encoded = containerWidgetCodec.encode(Container()); + + expect(encoded, { + 'key': null, + 'alignment': null, + 'padding': null, + 'color': null, + 'isAntiAlias': true, + 'decoration': null, + 'foregroundDecoration': null, + 'width': null, + 'height': null, + 'constraints': null, + 'margin': null, + 'transform': null, + 'transformAlignment': null, + 'clipBehavior': 'none', + 'child': null, + }); + expectJsonSafe(encoded); + }); + + test('round-trips a color-only container through a stable encoding', () { + final original = Container(color: const Color(0xFF2196F3)); + final encoded = containerWidgetCodec.encode(original); + final parsed = containerWidgetCodec.parse(encoded)!; + + expect(containerWidgetCodec.encode(parsed), encoded); + expect(parsed.color, original.color); + expect(parsed.decoration, isNull); + expectJsonSafe(encoded); + }); + + test( + 'round-trips a populated decorated container through stable encoding', + () { + final transform = Matrix4.identity() + ..translateByDouble(4.0, 8.0, 0.0, 1.0) + ..rotateZ(0.25); + final constraints = const BoxConstraints( + minWidth: 10, + maxWidth: 100, + minHeight: 20, + maxHeight: 200, + ); + final original = Container( + key: const ValueKey('shell'), + alignment: Alignment.centerRight, + padding: const EdgeInsets.all(8), + isAntiAlias: false, + decoration: BoxDecoration( + color: const Color(0xFFE0F2F1), + borderRadius: BorderRadius.circular(6), + ), + foregroundDecoration: BoxDecoration( + border: Border.all(color: const Color(0xFF004D40)), + ), + constraints: constraints, + margin: const EdgeInsetsDirectional.only(start: 2, end: 4), + transform: transform, + transformAlignment: Alignment.bottomLeft, + clipBehavior: Clip.antiAlias, + child: Container(color: const Color(0xFFFF0000)), + ); + + final encoded = containerWidgetCodec.encode(original); + final parsed = containerWidgetCodec.parse(encoded)!; + + expect(containerWidgetCodec.encode(parsed), encoded); + expect(parsed.key, original.key); + expect(parsed.padding, original.padding); + expect(parsed.isAntiAlias, isFalse); + expect(parsed.decoration, isA()); + expect(parsed.foregroundDecoration, isA()); + expect(parsed.constraints, constraints); + expect(parsed.margin, original.margin); + expect(parsed.transform, transform); + expect(parsed.transformAlignment, original.transformAlignment); + expect(parsed.clipBehavior, Clip.antiAlias); + expect(parsed.child, isA()); + expectJsonSafe(encoded); + }, + ); + + test('canonicalizes width and height to constraints on encode', () { + final original = Container(width: 10, height: 20); + final encoded = containerWidgetCodec.encode(original); + + expect(encoded!['width'], isNull); + expect(encoded['height'], isNull); + expect( + encoded['constraints'], + boxConstraintsCodec.encode( + BoxConstraints.tightFor(width: 10, height: 20), + ), + ); + expect( + containerWidgetCodec.encode(containerWidgetCodec.parse(encoded)), + encoded, + ); + }); + + test('uses the direct BoxConstraints shape without a discriminator', () { + final original = Container( + constraints: const BoxConstraints( + minWidth: 1, + maxWidth: 10, + minHeight: 2, + maxHeight: 20, + ), + ); + final encoded = containerWidgetCodec.encode(original)!; + final constraints = encoded['constraints']! as Map; + + expect(constraints.containsKey('type'), isFalse); + expect(constraints, { + 'minWidth': 1.0, + 'maxWidth': 10.0, + 'minHeight': 2.0, + 'maxHeight': 20.0, + }); + expect( + containerWidgetCodec.encode(containerWidgetCodec.parse(encoded)), + encoded, + ); + expectJsonSafe(encoded); + }); + }); + + group('containerWidgetCodec rejects invalid input', () { + test('rejects color and decoration together', () { + expect( + containerWidgetCodec.safeParse({ + 'color': '#FFFFFF', + 'decoration': {'type': 'box'}, + }).isFail, + isTrue, + ); + }); + + test('rejects clipBehavior without a decoration', () { + expect( + containerWidgetCodec.safeParse({'clipBehavior': 'antiAlias'}).isFail, + isTrue, + ); + }); + + // Negative insets are exercised on the decode path: the Container + // constructor itself asserts non-negative padding/margin, so a negative + // value can only reach the codec as untrusted JSON. A bare number sets all + // four EdgeInsets sides. + test('rejects negative padding on decode', () { + expect(containerWidgetCodec.safeParse({'padding': -4}).isFail, isTrue); + }); + + test('rejects negative margin on decode', () { + expect(containerWidgetCodec.safeParse({'margin': -4}).isFail, isTrue); + }); + + test('rejects child nesting beyond the widget recursion cap', () { + // Deep widget nesting can only arrive as untrusted JSON. The codec should + // return a bounded failure instead of recursing to the Dart stack limit. + expect( + containerWidgetCodec + .safeParse(_nestedContainerJson(containerWidgetMaxDepth)) + .isOk, + isTrue, + ); + expect( + containerWidgetCodec + .safeParse(_nestedContainerJson(containerWidgetMaxDepth + 1)) + .isFail, + isTrue, + ); + }); + }); + + group('widgetCodec', () { + test('round-trips nested containers through the widget union', () { + final original = Container( + padding: const EdgeInsets.all(4), + child: Container( + key: const ValueKey(7), + constraints: const BoxConstraints.tightFor(width: 12), + ), + ); + + final encoded = widgetCodec.encode(original); + final parsed = widgetCodec.parse(encoded)!; + + expect(widgetCodec.encode(parsed), encoded); + expect(encoded!['type'], 'container'); + expect(parsed, isA()); + expect((parsed as Container).child, isA()); + expectJsonSafe(encoded); + }); + }); +} + +Map _nestedContainerJson(int childDepth) { + Map? child; + for (var depth = childDepth; depth > 0; depth--) { + child = {'type': 'container', if (child != null) 'child': child}; + } + return {if (child != null) 'child': child}; +} diff --git a/packages/flutter_codec/test/widgets/key_test.dart b/packages/flutter_codec/test/widgets/key_test.dart new file mode 100644 index 00000000..e5a0f91b --- /dev/null +++ b/packages/flutter_codec/test/widgets/key_test.dart @@ -0,0 +1,165 @@ +import 'package:ack/ack.dart' show SchemaNestedError; +import 'package:flutter/widgets.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('keyCodec', () { + test('round-trips supported ValueKey scalar types', () { + final cases = [ + const ValueKey('foo'), + const ValueKey(1), + const ValueKey(1.5), + const ValueKey(true), + ]; + + for (final key in cases) { + final encoded = keyCodec.encode(key); + + expect(keyCodec.parse(encoded), key); + expectJsonSafe(encoded); + } + }); + + test('encodes Key(String) sugar as a string ValueKey', () { + final encoded = keyCodec.encode(const Key('foo')); + + expect(encoded, {'type': 'value', 'valueType': 'string', 'value': 'foo'}); + expect(keyCodec.parse(encoded), const ValueKey('foo')); + expectJsonSafe(encoded); + }); + + test('keeps int and double keys distinct', () { + final intKey = keyCodec.parse({ + 'type': 'value', + 'valueType': 'int', + 'value': 1, + }); + final doubleKey = keyCodec.parse({ + 'type': 'value', + 'valueType': 'double', + 'value': 1, + }); + + expect(intKey, const ValueKey(1)); + expect(doubleKey, const ValueKey(1)); + expect(intKey, isNot(doubleKey)); + }); + + test('rejects identity-based key subtypes on encode', () { + final cases = [const ObjectKey('x'), UniqueKey(), GlobalKey()]; + + for (final key in cases) { + _expectEncodeFailureContains(key, key.runtimeType.toString()); + _expectEncodeFailureContains(key, 'cannot be serialized'); + } + }); + + test('rejects unsupported ValueKey value types on encode', () { + final cases = [ + const ValueKey(1), + const ValueKey('foo'), + const ValueKey>([1]), + ]; + + for (final key in cases) { + _expectEncodeFailureContains(key, key.runtimeType.toString()); + _expectEncodeFailureContains(key, 'no portable JSON shape'); + } + }); + + test('rejects ValueKey subclasses such as PageStorageKey on encode', () { + // PageStorageKey is a ValueKey subclass; encoding it as a + // plain ValueKey would silently drop the subclass on decode. + _expectEncodeFailureContains( + const PageStorageKey('x'), + 'PageStorageKey', + ); + }); + + test('rejects invalid value-key payloads', () { + final invalidCases = { + 'unknown valueType': { + 'type': 'value', + 'valueType': 'date', + 'value': '2026-05-27', + }, + 'generic number valueType': { + 'type': 'value', + 'valueType': 'number', + 'value': 1, + }, + 'missing value': {'type': 'value', 'valueType': 'string'}, + 'int type mismatch': { + 'type': 'value', + 'valueType': 'int', + 'value': 'oops', + }, + 'string type mismatch': { + 'type': 'value', + 'valueType': 'string', + 'value': 1, + }, + 'int valueType with a double value': { + 'type': 'value', + 'valueType': 'int', + 'value': 1.5, + }, + 'bool valueType with an int value': { + 'type': 'value', + 'valueType': 'bool', + 'value': 1, + }, + 'double valueType with a non-numeric value': { + 'type': 'value', + 'valueType': 'double', + 'value': 'oops', + }, + 'object value': { + 'type': 'value', + 'valueType': 'string', + 'value': {'nested': 'value'}, + }, + 'list value': { + 'type': 'value', + 'valueType': 'string', + 'value': ['value'], + }, + }; + + invalidCases.forEach((name, input) { + expect(keyCodec.safeParse(input).isFail, isTrue, reason: name); + }); + }); + + test('exports only supported scalar value schemas', () { + final jsonSchema = keyCodec.toJsonSchema(); + final branches = jsonSchema['anyOf']! as List; + final valueKeySchema = branches.single! as Map; + final properties = valueKeySchema['properties']! as Map; + final valueSchema = properties['value']! as Map; + final valueBranches = valueSchema['anyOf']! as List; + + expect(valueBranches, [ + {'type': 'string'}, + {'type': 'integer'}, + {'type': 'number'}, + {'type': 'boolean'}, + ]); + }); + }); +} + +void _expectEncodeFailureContains(Key key, String fragment) { + final result = keyCodec.safeEncode(key); + + expect(result.isFail, isTrue); + final error = result.getError(); + expect(error, isA()); + expect( + (error as SchemaNestedError).errors.single.toString(), + contains(fragment), + ); +} diff --git a/packages/flutter_codec/test/widgets/text_test.dart b/packages/flutter_codec/test/widgets/text_test.dart new file mode 100644 index 00000000..bcd84fef --- /dev/null +++ b/packages/flutter_codec/test/widgets/text_test.dart @@ -0,0 +1,151 @@ +import 'package:ack/ack.dart' show SchemaNestedError; +import 'package:flutter/widgets.dart'; +import 'package:flutter_codec/flutter_codec.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../support/json_safety.dart'; + +void main() { + group('textWidgetCodec decode', () { + test('decodes a minimal data object', () { + final parsed = textWidgetCodec.parse({'data': 'hello'})!; + + expect(parsed.data, 'hello'); + expect(parsed.style, isNull); + expect(parsed.textScaler, isNull); + }); + }); + + group('textWidgetCodec encode', () { + test('emits a full canonical map with explicit nulls for defaults', () { + final encoded = textWidgetCodec.encode(const Text('hello')); + + expect(encoded, { + 'key': null, + 'data': 'hello', + 'style': null, + 'strutStyle': null, + 'textAlign': null, + 'textDirection': null, + 'locale': null, + 'softWrap': null, + 'overflow': null, + 'maxLines': null, + 'semanticsLabel': null, + 'semanticsIdentifier': null, + 'textWidthBasis': null, + 'textHeightBehavior': null, + 'selectionColor': null, + }); + expect(encoded!.containsKey('textScaler'), isFalse); + expect(encoded.containsKey('textScaleFactor'), isFalse); + expectJsonSafe(encoded); + }); + + test('round-trips a fully populated Text through stable encoding', () { + const original = Text( + 'hello', + key: ValueKey('copy'), + style: TextStyle( + color: Color(0xFF102030), + fontSize: 18, + fontWeight: FontWeight.w600, + ), + strutStyle: StrutStyle(fontSize: 18, height: 1.25), + textAlign: TextAlign.center, + textDirection: TextDirection.rtl, + locale: Locale('en', 'US'), + softWrap: false, + overflow: TextOverflow.ellipsis, + maxLines: 2, + semanticsLabel: 'label', + semanticsIdentifier: 'copy-id', + textWidthBasis: TextWidthBasis.longestLine, + textHeightBehavior: TextHeightBehavior( + applyHeightToFirstAscent: false, + applyHeightToLastDescent: true, + ), + selectionColor: Color(0x330000FF), + ); + + final encoded = textWidgetCodec.encode(original); + final parsed = textWidgetCodec.parse(encoded)!; + + expect(textWidgetCodec.encode(parsed), encoded); + expect(parsed.key, original.key); + expect(parsed.data, original.data); + expect(parsed.style, original.style); + expect(parsed.strutStyle, original.strutStyle); + expect(parsed.textAlign, original.textAlign); + expect(parsed.textDirection, original.textDirection); + expect(parsed.locale, original.locale); + expect(parsed.softWrap, original.softWrap); + expect(parsed.overflow, original.overflow); + expect(parsed.maxLines, original.maxLines); + expect(parsed.semanticsLabel, original.semanticsLabel); + expect(parsed.semanticsIdentifier, original.semanticsIdentifier); + expect(parsed.textWidthBasis, original.textWidthBasis); + expect(parsed.textHeightBehavior, original.textHeightBehavior); + expect(parsed.selectionColor, original.selectionColor); + expectJsonSafe(encoded); + }); + + test('fails to encode opaque textScaler state', () { + // textScaler has no portable JSON shape, so encoding a Text that sets it + // fails loudly instead of silently dropping the scaler. + final result = textWidgetCodec.safeEncode( + Text('scaled', textScaler: TextScaler.linear(1.5)), + ); + + expect(result.isFail, isTrue); + }); + + test('explains why Text.rich cannot be encoded', () { + final result = textWidgetCodec.safeEncode( + const Text.rich(TextSpan(text: 'hello')), + ); + + expect(result.isFail, isTrue); + expect( + result.getError().toString(), + contains('Text.rich inline span trees are not supported'), + ); + }); + + test('widgetCodec keeps the Text.rich diagnostic', () { + final result = widgetCodec.safeEncode( + const Text.rich(TextSpan(text: 'hello')), + ); + + expect(result.isFail, isTrue); + final error = result.getError(); + expect(error, isA()); + expect( + (error as SchemaNestedError).errors + .map((nested) => nested.toString()) + .join('\n'), + contains('Text.rich inline span trees are not supported'), + ); + }); + }); + + group('widgetCodec', () { + test('round-trips Container(child: Text) across widget branches', () { + final original = Container( + padding: const EdgeInsets.all(8), + child: const Text('hi', textAlign: TextAlign.center), + ); + + final encoded = widgetCodec.encode(original); + final parsed = widgetCodec.parse(encoded)!; + + expect(widgetCodec.encode(parsed), encoded); + expect(parsed, isA()); + final child = (parsed as Container).child; + expect(child, isA()); + expect((child as Text).data, 'hi'); + expect(child.textAlign, TextAlign.center); + expectJsonSafe(encoded); + }); + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index 6236c923..7e6e1b19 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: ACK workspace root package environment: sdk: '>=3.9.0 <4.0.0' - flutter: '>=3.35.0' + flutter: '>=3.41.0' workspace: - packages/ack @@ -11,6 +11,7 @@ workspace: - packages/ack_generator - packages/ack_firebase_ai - packages/ack_json_schema_builder + - packages/flutter_codec - example dependencies: @@ -60,6 +61,7 @@ melos: - ack_json_schema_builder - ack_example - ack_annotations + - flutter_codec fix: run: dart run melos exec -- "dart fix --apply"