diff --git a/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.c b/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.c
new file mode 100644
index 0000000..937985e
--- /dev/null
+++ b/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.c
@@ -0,0 +1,172 @@
+/**
+ * TopLevel.c
+ * This file has been autogenerated using quicktype https://github.com/quicktype/quicktype - DO NOT EDIT
+ */
+
+#include "TopLevel.h"
+
+struct Item * cJSON_ParseItem(const char * s) {
+    struct Item * x = NULL;
+    if (NULL != s) {
+        cJSON * j = cJSON_Parse(s);
+        if (NULL != j) {
+            x = cJSON_GetItemValue(j);
+            cJSON_Delete(j);
+        }
+    }
+    return x;
+}
+
+struct Item * cJSON_GetItemValue(const cJSON * j) {
+    struct Item * x = NULL;
+    if (NULL != j) {
+        if (NULL != (x = cJSON_malloc(sizeof(struct Item)))) {
+            memset(x, 0, sizeof(struct Item));
+            if (cJSON_HasObjectItem(j, "aa")) {
+                x->aa = strdup(cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(j, "aa")));
+            }
+            if (cJSON_HasObjectItem(j, "bb")) {
+                x->bb = strdup(cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(j, "bb")));
+            }
+            if (cJSON_HasObjectItem(j, "cc")) {
+                x->cc = strdup(cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(j, "cc")));
+            }
+            if (cJSON_HasObjectItem(j, "dd")) {
+                x->dd = strdup(cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(j, "dd")));
+            }
+        }
+    }
+    return x;
+}
+
+cJSON * cJSON_CreateItem(const struct Item * x) {
+    cJSON * j = NULL;
+    if (NULL != x) {
+        if (NULL != (j = cJSON_CreateObject())) {
+            if (NULL != x->aa) {
+                cJSON_AddStringToObject(j, "aa", x->aa);
+            }
+            if (NULL != x->bb) {
+                cJSON_AddStringToObject(j, "bb", x->bb);
+            }
+            if (NULL != x->cc) {
+                cJSON_AddStringToObject(j, "cc", x->cc);
+            }
+            if (NULL != x->dd) {
+                cJSON_AddStringToObject(j, "dd", x->dd);
+            }
+        }
+    }
+    return j;
+}
+
+char * cJSON_PrintItem(const struct Item * x) {
+    char * s = NULL;
+    if (NULL != x) {
+        cJSON * j = cJSON_CreateItem(x);
+        if (NULL != j) {
+            s = cJSON_Print(j);
+            cJSON_Delete(j);
+        }
+    }
+    return s;
+}
+
+void cJSON_DeleteItem(struct Item * x) {
+    if (NULL != x) {
+        if (NULL != x->aa) {
+            cJSON_free(x->aa);
+        }
+        if (NULL != x->bb) {
+            cJSON_free(x->bb);
+        }
+        if (NULL != x->cc) {
+            cJSON_free(x->cc);
+        }
+        if (NULL != x->dd) {
+            cJSON_free(x->dd);
+        }
+        cJSON_free(x);
+    }
+}
+
+struct TopLevel * cJSON_ParseTopLevel(const char * s) {
+    struct TopLevel * x = NULL;
+    if (NULL != s) {
+        cJSON * j = cJSON_Parse(s);
+        if (NULL != j) {
+            x = cJSON_GetTopLevelValue(j);
+            cJSON_Delete(j);
+        }
+    }
+    return x;
+}
+
+struct TopLevel * cJSON_GetTopLevelValue(const cJSON * j) {
+    struct TopLevel * x = NULL;
+    if (NULL != j) {
+        if (NULL != (x = cJSON_malloc(sizeof(struct TopLevel)))) {
+            memset(x, 0, sizeof(struct TopLevel));
+            if (cJSON_HasObjectItem(j, "items")) {
+                list_t * x1 = list_create(false, NULL);
+                if (NULL != x1) {
+                    cJSON * e1 = NULL;
+                    cJSON * j1 = cJSON_GetObjectItemCaseSensitive(j, "items");
+                    cJSON_ArrayForEach(e1, j1) {
+                        list_add_tail(x1, cJSON_GetItemValue(e1), sizeof(struct Item *));
+                    }
+                    x->items = x1;
+                }
+            }
+            else {
+                x->items = list_create(false, NULL);
+            }
+        }
+    }
+    return x;
+}
+
+cJSON * cJSON_CreateTopLevel(const struct TopLevel * x) {
+    cJSON * j = NULL;
+    if (NULL != x) {
+        if (NULL != (j = cJSON_CreateObject())) {
+            if (NULL != x->items) {
+                cJSON * j1 = cJSON_AddArrayToObject(j, "items");
+                if (NULL != j1) {
+                    struct Item * x1 = list_get_head(x->items);
+                    while (NULL != x1) {
+                        cJSON_AddItemToArray(j1, cJSON_CreateItem(x1));
+                        x1 = list_get_next(x->items);
+                    }
+                }
+            }
+        }
+    }
+    return j;
+}
+
+char * cJSON_PrintTopLevel(const struct TopLevel * x) {
+    char * s = NULL;
+    if (NULL != x) {
+        cJSON * j = cJSON_CreateTopLevel(x);
+        if (NULL != j) {
+            s = cJSON_Print(j);
+            cJSON_Delete(j);
+        }
+    }
+    return s;
+}
+
+void cJSON_DeleteTopLevel(struct TopLevel * x) {
+    if (NULL != x) {
+        if (NULL != x->items) {
+            struct Item * x1 = list_get_head(x->items);
+            while (NULL != x1) {
+                cJSON_DeleteItem(x1);
+                x1 = list_get_next(x->items);
+            }
+            list_release(x->items);
+        }
+        cJSON_free(x);
+    }
+}
diff --git a/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.h b/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.h
new file mode 100644
index 0000000..1dc177d
--- /dev/null
+++ b/head/schema-cjson/test/inputs/schema/one-of-objects.schema/default/TopLevel.h
@@ -0,0 +1,64 @@
+/**
+ * TopLevel.h
+ * This file has been autogenerated using quicktype https://github.com/quicktype/quicktype - DO NOT EDIT
+ * This file depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable
+ * To parse json data from json string use the following: struct <type> * data = cJSON_Parse<type>(<string>);
+ * To get json data from cJSON object use the following: struct <type> * data = cJSON_Get<type>Value(<cjson>);
+ * To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create<type>(<data>);
+ * To print json string from json data use the following: char * string = cJSON_Print<type>(<data>);
+ * To delete json data use the following: cJSON_Delete<type>(<data>);
+ */
+
+#ifndef __TOPLEVEL_H__
+#define __TOPLEVEL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cJSON.h>
+#include <hashtable.h>
+#include <list.h>
+
+#ifndef cJSON_Bool
+#define cJSON_Bool (cJSON_True | cJSON_False)
+#endif
+#ifndef cJSON_Map
+#define cJSON_Map (1 << 16)
+#endif
+#ifndef cJSON_Enum
+#define cJSON_Enum (1 << 17)
+#endif
+
+struct Item {
+    char * aa;
+    char * bb;
+    char * cc;
+    char * dd;
+};
+
+struct TopLevel {
+    list_t * items;
+};
+
+struct Item * cJSON_ParseItem(const char * s);
+struct Item * cJSON_GetItemValue(const cJSON * j);
+cJSON * cJSON_CreateItem(const struct Item * x);
+char * cJSON_PrintItem(const struct Item * x);
+void cJSON_DeleteItem(struct Item * x);
+
+struct TopLevel * cJSON_ParseTopLevel(const char * s);
+struct TopLevel * cJSON_GetTopLevelValue(const cJSON * j);
+cJSON * cJSON_CreateTopLevel(const struct TopLevel * x);
+char * cJSON_PrintTopLevel(const struct TopLevel * x);
+void cJSON_DeleteTopLevel(struct TopLevel * x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TOPLEVEL_H__ */
diff --git a/head/schema-cplusplus/test/inputs/schema/one-of-objects.schema/default/quicktype.hpp b/head/schema-cplusplus/test/inputs/schema/one-of-objects.schema/default/quicktype.hpp
new file mode 100644
index 0000000..b673de8
--- /dev/null
+++ b/head/schema-cplusplus/test/inputs/schema/one-of-objects.schema/default/quicktype.hpp
@@ -0,0 +1,165 @@
+//  To parse this JSON data, first install
+//
+//      json.hpp  https://github.com/nlohmann/json
+//
+//  Then include this file, and then do
+//
+//     TopLevel data = nlohmann::json::parse(jsonString);
+
+#pragma once
+
+#include <optional>
+#include "json.hpp"
+
+#include <optional>
+#include <stdexcept>
+#include <regex>
+
+#ifndef NLOHMANN_OPT_HELPER
+#define NLOHMANN_OPT_HELPER
+namespace nlohmann {
+    template <typename T>
+    struct adl_serializer<std::shared_ptr<T>> {
+        static void to_json(json & j, const std::shared_ptr<T> & opt) {
+            if (!opt) j = nullptr; else j = *opt;
+        }
+
+        static std::shared_ptr<T> from_json(const json & j) {
+            if (j.is_null()) return std::shared_ptr<T>(); else return std::make_shared<T>(j.get<T>());
+        }
+    };
+    template <typename T>
+    struct adl_serializer<std::optional<T>> {
+        static void to_json(json & j, const std::optional<T> & opt) {
+            if (!opt) j = nullptr; else j = *opt;
+        }
+
+        static std::optional<T> from_json(const json & j) {
+            if (j.is_null()) return std::optional<T>(); else return std::make_optional<T>(j.get<T>());
+        }
+    };
+}
+#endif
+
+namespace quicktype {
+    using nlohmann::json;
+
+    #ifndef NLOHMANN_UNTYPED_quicktype_HELPER
+    #define NLOHMANN_UNTYPED_quicktype_HELPER
+    inline json get_untyped(const json & j, const char * property) {
+        if (j.find(property) != j.end()) {
+            return j.at(property).get<json>();
+        }
+        return json();
+    }
+
+    inline json get_untyped(const json & j, std::string property) {
+        return get_untyped(j, property.data());
+    }
+    #endif
+
+    #ifndef NLOHMANN_OPTIONAL_quicktype_HELPER
+    #define NLOHMANN_OPTIONAL_quicktype_HELPER
+    template <typename T>
+    inline std::shared_ptr<T> get_heap_optional(const json & j, const char * property) {
+        auto it = j.find(property);
+        if (it != j.end() && !it->is_null()) {
+            return j.at(property).get<std::shared_ptr<T>>();
+        }
+        return std::shared_ptr<T>();
+    }
+
+    template <typename T>
+    inline std::shared_ptr<T> get_heap_optional(const json & j, std::string property) {
+        return get_heap_optional<T>(j, property.data());
+    }
+    template <typename T>
+    inline std::optional<T> get_stack_optional(const json & j, const char * property) {
+        auto it = j.find(property);
+        if (it != j.end() && !it->is_null()) {
+            return j.at(property).get<std::optional<T>>();
+        }
+        return std::optional<T>();
+    }
+
+    template <typename T>
+    inline std::optional<T> get_stack_optional(const json & j, std::string property) {
+        return get_stack_optional<T>(j, property.data());
+    }
+    #endif
+
+    class Item {
+        public:
+        Item() = default;
+        virtual ~Item() = default;
+
+        private:
+        std::optional<std::string> aa;
+        std::optional<std::string> bb;
+        std::optional<std::string> cc;
+        std::optional<std::string> dd;
+
+        public:
+        const std::optional<std::string> & get_aa() const { return aa; }
+        std::optional<std::string> & get_mutable_aa() { return aa; }
+        void set_aa(const std::optional<std::string> & value) { this->aa = value; }
+
+        const std::optional<std::string> & get_bb() const { return bb; }
+        std::optional<std::string> & get_mutable_bb() { return bb; }
+        void set_bb(const std::optional<std::string> & value) { this->bb = value; }
+
+        const std::optional<std::string> & get_cc() const { return cc; }
+        std::optional<std::string> & get_mutable_cc() { return cc; }
+        void set_cc(const std::optional<std::string> & value) { this->cc = value; }
+
+        const std::optional<std::string> & get_dd() const { return dd; }
+        std::optional<std::string> & get_mutable_dd() { return dd; }
+        void set_dd(const std::optional<std::string> & value) { this->dd = value; }
+    };
+
+    class TopLevel {
+        public:
+        TopLevel() = default;
+        virtual ~TopLevel() = default;
+
+        private:
+        std::vector<Item> items;
+
+        public:
+        const std::vector<Item> & get_items() const { return items; }
+        std::vector<Item> & get_mutable_items() { return items; }
+        void set_items(const std::vector<Item> & value) { this->items = value; }
+    };
+}
+
+namespace quicktype {
+    void from_json(const json & j, Item & x);
+    void to_json(json & j, const Item & x);
+
+    void from_json(const json & j, TopLevel & x);
+    void to_json(json & j, const TopLevel & x);
+
+    inline void from_json(const json & j, Item& x) {
+        x.set_aa(get_stack_optional<std::string>(j, "aa"));
+        x.set_bb(get_stack_optional<std::string>(j, "bb"));
+        x.set_cc(get_stack_optional<std::string>(j, "cc"));
+        x.set_dd(get_stack_optional<std::string>(j, "dd"));
+    }
+
+    inline void to_json(json & j, const Item & x) {
+        j = json::object();
+        j["aa"] = x.get_aa();
+        j["bb"] = x.get_bb();
+        j["cc"] = x.get_cc();
+        j["dd"] = x.get_dd();
+    }
+
+    inline void from_json(const json & j, TopLevel& x) {
+        x.set_items(j.at("items").get<std::vector<Item>>());
+    }
+
+    inline void to_json(json & j, const TopLevel & x) {
+        j = json::object();
+        j["items"] = x.get_items();
+    }
+}
diff --git a/head/schema-csharp/test/inputs/schema/one-of-objects.schema/default/QuickType.cs b/head/schema-csharp/test/inputs/schema/one-of-objects.schema/default/QuickType.cs
new file mode 100644
index 0000000..f9ff52e
--- /dev/null
+++ b/head/schema-csharp/test/inputs/schema/one-of-objects.schema/default/QuickType.cs
@@ -0,0 +1,76 @@
+// <auto-generated />
+//
+// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
+//
+//    using QuickType;
+//
+//    var topLevel = TopLevel.FromJson(jsonString);
+#nullable enable
+#pragma warning disable CS8618
+#pragma warning disable CS8601
+#pragma warning disable CS8602
+#pragma warning disable CS8603
+#pragma warning disable CS8604
+#pragma warning disable CS8625
+#pragma warning disable CS8765
+
+namespace QuickType
+{
+    using System;
+    using System.Collections.Generic;
+
+    using System.Globalization;
+    using Newtonsoft.Json;
+    using Newtonsoft.Json.Converters;
+
+    public partial class TopLevel
+    {
+        [JsonProperty("items", Required = Required.Always)]
+        public Item[] Items { get; set; }
+    }
+
+    public partial class Item
+    {
+        [JsonProperty("aa", Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
+        public string? Aa { get; set; }
+
+        [JsonProperty("bb", Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
+        public string? Bb { get; set; }
+
+        [JsonProperty("cc", Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
+        public string? Cc { get; set; }
+
+        [JsonProperty("dd", Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
+        public string? Dd { get; set; }
+    }
+
+    public partial class TopLevel
+    {
+        public static TopLevel FromJson(string json) => JsonConvert.DeserializeObject<TopLevel>(json, QuickType.Converter.Settings);
+    }
+
+    public static partial class Serialize
+    {
+        public static string ToJson(this TopLevel self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
+    }
+
+    internal static partial class Converter
+    {
+        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
+        {
+            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
+            DateParseHandling = DateParseHandling.None,
+            Converters =
+            {
+                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
+            },
+        };
+    }
+}
+#pragma warning restore CS8618
+#pragma warning restore CS8601
+#pragma warning restore CS8602
+#pragma warning restore CS8603
+#pragma warning restore CS8604
+#pragma warning restore CS8625
+#pragma warning restore CS8765
diff --git a/head/schema-csharp-SystemTextJson/test/inputs/schema/one-of-objects.schema/default/QuickType.cs b/head/schema-csharp-SystemTextJson/test/inputs/schema/one-of-objects.schema/default/QuickType.cs
new file mode 100644
index 0000000..80ffb61
--- /dev/null
+++ b/head/schema-csharp-SystemTextJson/test/inputs/schema/one-of-objects.schema/default/QuickType.cs
@@ -0,0 +1,185 @@
+// <auto-generated />
+//
+// To parse this JSON data, add NuGet 'System.Text.Json' then do:
+//
+//    using QuickType;
+//
+//    var topLevel = TopLevel.FromJson(jsonString);
+#nullable enable
+#pragma warning disable CS8618
+#pragma warning disable CS8601
+#pragma warning disable CS8602
+#pragma warning disable CS8603
+
+namespace QuickType
+{
+    using System;
+    using System.Collections.Generic;
+
+    using System.Text.Json;
+    using System.Text.Json.Serialization;
+    using System.Globalization;
+
+    public partial class TopLevel
+    {
+        [JsonRequired]
+        [JsonPropertyName("items")]
+        public Item[] Items { get; set; }
+    }
+
+    public partial class Item
+    {
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+        [JsonPropertyName("aa")]
+        public string? Aa { get; set; }
+
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+        [JsonPropertyName("bb")]
+        public string? Bb { get; set; }
+
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+        [JsonPropertyName("cc")]
+        public string? Cc { get; set; }
+
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+        [JsonPropertyName("dd")]
+        public string? Dd { get; set; }
+    }
+
+    public partial class TopLevel
+    {
+        public static TopLevel FromJson(string json) => JsonSerializer.Deserialize<TopLevel>(json, QuickType.Converter.Settings);
+    }
+
+    public static partial class Serialize
+    {
+        public static string ToJson(this TopLevel self) => JsonSerializer.Serialize(self, QuickType.Converter.Settings);
+    }
+
+    internal static partial class Converter
+    {
+        public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)
+        {
+            Converters =
+            {
+                new DateOnlyConverter(),
+                new TimeOnlyConverter(),
+                IsoDateTimeOffsetConverter.Singleton
+            },
+        };
+    }
+    
+    public class DateOnlyConverter : JsonConverter<DateOnly>
+    {
+        private readonly string serializationFormat;
+        public DateOnlyConverter() : this(null) { }
+
+        public DateOnlyConverter(string? serializationFormat)
+        {
+                this.serializationFormat = serializationFormat ?? "yyyy-MM-dd";
+        }
+
+        public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+                var value = reader.GetString();
+                return DateOnly.Parse(value!);
+        }
+
+        public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
+                => writer.WriteStringValue(value.ToString(serializationFormat));
+    }
+
+    public class TimeOnlyConverter : JsonConverter<TimeOnly>
+    {
+        private readonly string serializationFormat;
+
+        public TimeOnlyConverter() : this(null) { }
+
+        public TimeOnlyConverter(string? serializationFormat)
+        {
+                this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff";
+        }
+
+        public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+                var value = reader.GetString();
+                return TimeOnly.Parse(value!);
+        }
+
+        public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
+                => writer.WriteStringValue(value.ToString(serializationFormat));
+    }
+
+    internal class IsoDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
+    {
+        public override bool CanConvert(Type t) => t == typeof(DateTimeOffset);
+
+        private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+        private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
+        private string? _dateTimeFormat;
+        private CultureInfo? _culture;
+
+        public DateTimeStyles DateTimeStyles
+        {
+                get => _dateTimeStyles;
+                set => _dateTimeStyles = value;
+        }
+
+        public string? DateTimeFormat
+        {
+                get => _dateTimeFormat ?? string.Empty;
+                set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value;
+        }
+
+        public CultureInfo Culture
+        {
+                get => _culture ?? CultureInfo.CurrentCulture;
+                set => _culture = value;
+        }
+
+        public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
+        {
+                string text;
+
+
+                if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+                        || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+                {
+                        value = value.ToUniversalTime();
+                }
+
+                text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+
+                writer.WriteStringValue(text);
+        }
+
+        public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+                string? dateText = reader.GetString();
+
+                if (string.IsNullOrEmpty(dateText) == false)
+                {
+                        if (!string.IsNullOrEmpty(_dateTimeFormat))
+                        {
+                                return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+                        }
+                        else
+                        {
+                                return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
+                        }
+                }
+                else
+                {
+                        return default(DateTimeOffset);
+                }
+        }
+
+
+        public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter();
+    }
+}
+#pragma warning restore CS8618
+#pragma warning restore CS8601
+#pragma warning restore CS8602
+#pragma warning restore CS8603
diff --git a/head/schema-dart/test/inputs/schema/one-of-objects.schema/default/TopLevel.dart b/head/schema-dart/test/inputs/schema/one-of-objects.schema/default/TopLevel.dart
new file mode 100644
index 0000000..0a309f3
--- /dev/null
+++ b/head/schema-dart/test/inputs/schema/one-of-objects.schema/default/TopLevel.dart
@@ -0,0 +1,53 @@
+// To parse this JSON data, do
+//
+//     final topLevel = topLevelFromJson(jsonString);
+
+import 'dart:convert';
+
+TopLevel topLevelFromJson(String str) => TopLevel.fromJson(json.decode(str));
+
+String topLevelToJson(TopLevel data) => json.encode(data.toJson());
+
+class TopLevel {
+    final List<Item> items;
+
+    TopLevel({
+        required this.items,
+    });
+
+    factory TopLevel.fromJson(Map<String, dynamic> json) => TopLevel(
+        items: List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
+    );
+
+    Map<String, dynamic> toJson() => {
+        "items": List<dynamic>.from(items.map((x) => x.toJson())),
+    };
+}
+
+class Item {
+    final String? aa;
+    final String? bb;
+    final String? cc;
+    final String? dd;
+
+    Item({
+        this.aa,
+        this.bb,
+        this.cc,
+        this.dd,
+    });
+
+    factory Item.fromJson(Map<String, dynamic> json) => Item(
+        aa: json["aa"],
+        bb: json["bb"],
+        cc: json["cc"],
+        dd: json["dd"],
+    );
+
+    Map<String, dynamic> toJson() => {
+        "aa": aa,
+        "bb": bb,
+        "cc": cc,
+        "dd": dd,
+    };
+}
diff --git a/head/schema-elixir/test/inputs/schema/one-of-objects.schema/default/QuickType.ex b/head/schema-elixir/test/inputs/schema/one-of-objects.schema/default/QuickType.ex
new file mode 100644
index 0000000..9a7a2e4
--- /dev/null
+++ b/head/schema-elixir/test/inputs/schema/one-of-objects.schema/default/QuickType.ex
@@ -0,0 +1,80 @@
+# This file was autogenerated using quicktype https://github.com/quicktype/quicktype
+#
+# Add Jason to your mix.exs
+#
+# Decode a JSON string: TopLevel.from_json(data)
+# Encode into a JSON string: TopLevel.to_json(struct)
+
+defmodule Item do
+  defstruct [:aa, :bb, :cc, :dd]
+
+  @type t :: %__MODULE__{
+          aa: String.t() | nil,
+          bb: String.t() | nil,
+          cc: String.t() | nil,
+          dd: String.t() | nil
+        }
+
+  def from_map(m) do
+    %Item{
+      aa: m["aa"],
+      bb: m["bb"],
+      cc: m["cc"],
+      dd: m["dd"],
+    }
+  end
+
+  def from_json(json) do
+    json
+          |> Jason.decode!()
+          |> from_map()
+  end
+
+  def to_map(struct) do
+    %{
+      "aa" => struct.aa,
+      "bb" => struct.bb,
+      "cc" => struct.cc,
+      "dd" => struct.dd,
+    }
+  end
+
+  def to_json(struct) do
+    struct
+          |> to_map()
+          |> Jason.encode!()
+  end
+end
+
+defmodule TopLevel do
+  @enforce_keys [:items]
+  defstruct [:items]
+
+  @type t :: %__MODULE__{
+          items: [Item.t()]
+        }
+
+  def from_map(m) do
+    %TopLevel{
+      items: Enum.map(m["items"], &Item.from_map/1),
+    }
+  end
+
+  def from_json(json) do
+    json
+          |> Jason.decode!()
+          |> from_map()
+  end
+
+  def to_map(struct) do
+    %{
+      "items" => struct.items && Enum.map(struct.items, &Item.to_map/1),
+    }
+  end
+
+  def to_json(struct) do
+    struct
+          |> to_map()
+          |> Jason.encode!()
+  end
+end
diff --git a/head/schema-elm/test/inputs/schema/one-of-objects.schema/default/QuickType.elm b/head/schema-elm/test/inputs/schema/one-of-objects.schema/default/QuickType.elm
new file mode 100644
index 0000000..bd1f822
--- /dev/null
+++ b/head/schema-elm/test/inputs/schema/one-of-objects.schema/default/QuickType.elm
@@ -0,0 +1,76 @@
+-- To decode the JSON data, add this file to your project, run
+--
+--     elm install NoRedInk/elm-json-decode-pipeline
+--
+-- add these imports
+--
+--     import Json.Decode exposing (decodeString)
+--     import QuickType exposing (quickType)
+--
+-- and you're off to the races with
+--
+--     decodeString quickType myJsonString
+
+module QuickType exposing
+    ( QuickType
+    , quickTypeToString
+    , quickType
+    , Item
+    )
+
+import Json.Decode as Jdec
+import Json.Decode.Pipeline as Jpipe
+import Json.Encode as Jenc
+import Dict exposing (Dict)
+
+type alias QuickType =
+    { items : List Item
+    }
+
+type alias Item =
+    { aa : Maybe String
+    , bb : Maybe String
+    , cc : Maybe String
+    , dd : Maybe String
+    }
+
+-- decoders and encoders
+
+quickTypeToString : QuickType -> String
+quickTypeToString r = Jenc.encode 0 (encodeQuickType r)
+
+quickType : Jdec.Decoder QuickType
+quickType =
+    Jdec.succeed QuickType
+        |> Jpipe.required "items" (Jdec.list item)
+
+encodeQuickType : QuickType -> Jenc.Value
+encodeQuickType x =
+    Jenc.object
+        [ ("items", Jenc.list encodeItem x.items)
+        ]
+
+item : Jdec.Decoder Item
+item =
+    Jdec.succeed Item
+        |> Jpipe.optional "aa" (Jdec.nullable Jdec.string) Nothing
+        |> Jpipe.optional "bb" (Jdec.nullable Jdec.string) Nothing
+        |> Jpipe.optional "cc" (Jdec.nullable Jdec.string) Nothing
+        |> Jpipe.optional "dd" (Jdec.nullable Jdec.string) Nothing
+
+encodeItem : Item -> Jenc.Value
+encodeItem x =
+    Jenc.object
+        [ ("aa", makeNullableEncoder Jenc.string x.aa)
+        , ("bb", makeNullableEncoder Jenc.string x.bb)
+        , ("cc", makeNullableEncoder Jenc.string x.cc)
+        , ("dd", makeNullableEncoder Jenc.string x.dd)
+        ]
+
+--- encoder helpers
+
+makeNullableEncoder : (a -> Jenc.Value) -> Maybe a -> Jenc.Value
+makeNullableEncoder f m =
+    case m of
+    Just x -> f x
+    Nothing -> Jenc.null
diff --git a/base/schema-flow/test/inputs/schema/class-map-union.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/class-map-union.schema/default/TopLevel.js
index dd3b326..31bfca9 100644
--- a/base/schema-flow/test/inputs/schema/class-map-union.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/class-map-union.schema/default/TopLevel.js
@@ -13,23 +13,21 @@ export type TopLevel = {
     union?: TopLevelUnion;
 };
 
-export type TopLevelUnion = {
-    foo?: Foo;
-    bar?: Bar;
-    [property: string]: UnionValue;
+export type TopLevelUnion = PurpleUnion | FluffyUnion | { [key: string]: boolean } | { [key: string]: UnionValue };
+
+export type PurpleUnion = {
+    foo?: number;
 };
 
-export type Bar = boolean | BarObject | string;
+export type FluffyUnion = {
+    bar?: string;
+};
 
-export type BarObject = {
+export type UnionValue = {
     quux?: number;
     [property: string]: mixed;
 };
 
-export type Foo = boolean | number | BarObject;
-
-export type UnionValue = boolean | BarObject;
-
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json: string): TopLevel {
@@ -195,13 +193,15 @@ function r(name: string) {
 
 const typeMap: any = {
     "TopLevel": o([
-        { json: "union", js: "union", typ: u(undefined, r("TopLevelUnion")) },
+        { json: "union", js: "union", typ: u(undefined, u(r("PurpleUnion"), r("FluffyUnion"), m(true), m(r("UnionValue")))) },
+    ], false),
+    "PurpleUnion": o([
+        { json: "foo", js: "foo", typ: u(undefined, 3.14) },
+    ], false),
+    "FluffyUnion": o([
+        { json: "bar", js: "bar", typ: u(undefined, "") },
     ], false),
-    "TopLevelUnion": o([
-        { json: "foo", js: "foo", typ: u(undefined, u(true, 3.14, r("BarObject"))) },
-        { json: "bar", js: "bar", typ: u(undefined, u(true, r("BarObject"), "")) },
-    ], u(true, r("BarObject"))),
-    "BarObject": o([
+    "UnionValue": o([
         { json: "quux", js: "quux", typ: u(undefined, 0) },
     ], "any"),
 };
diff --git a/base/schema-flow/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
index 6ae6502..36c6600 100644
--- a/base/schema-flow/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
@@ -13,11 +13,21 @@ export type TopLevel = {
     input: Item[];
 };
 
-export type Item = {
-    content?: string;
-    id?:      string;
-    output?:  string;
-    summary?: string;
+export type Item = Message | FunctionOutput | ReasoningItem;
+
+export type Message = {
+    content: string;
+    [property: string]: mixed;
+};
+
+export type FunctionOutput = {
+    id:     string;
+    output: string;
+    [property: string]: mixed;
+};
+
+export type ReasoningItem = {
+    summary: string;
     [property: string]: mixed;
 };
 
@@ -186,13 +196,17 @@ function r(name: string) {
 
 const typeMap: any = {
     "TopLevel": o([
-        { json: "input", js: "input", typ: a(r("Item")) },
+        { json: "input", js: "input", typ: a(u(r("Message"), r("FunctionOutput"), r("ReasoningItem"))) },
     ], false),
-    "Item": o([
-        { json: "content", js: "content", typ: u(undefined, "") },
-        { json: "id", js: "id", typ: u(undefined, "") },
-        { json: "output", js: "output", typ: u(undefined, "") },
-        { json: "summary", js: "summary", typ: u(undefined, "") },
+    "Message": o([
+        { json: "content", js: "content", typ: "" },
+    ], "any"),
+    "FunctionOutput": o([
+        { json: "id", js: "id", typ: "" },
+        { json: "output", js: "output", typ: "" },
+    ], "any"),
+    "ReasoningItem": o([
+        { json: "summary", js: "summary", typ: "" },
     ], "any"),
 };
 
diff --git a/base/schema-flow/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
index e5e3d2f..a0cf809 100644
--- a/base/schema-flow/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
@@ -9,24 +9,34 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
-export type TopLevel = {
+export type TopLevel = One | Two;
+
+export type One = {
+    b:    null | string;
+    kind: PurpleKind;
+    [property: string]: mixed;
+};
+
+export type PurpleKind =
+      "one";
+
+export type Two = {
     b?:   null | string;
-    kind: Kind;
+    kind: FluffyKind;
     [property: string]: mixed;
 };
 
-export type Kind =
-      "one"
-    | "two";
+export type FluffyKind =
+      "two";
 
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json: string): TopLevel {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("One"), r("Two")));
 }
 
 function topLevelToJson(value: TopLevel): string {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("One"), r("Two"))), null, 2);
 }
 
 function invalidValue(typ: any, val: any, key: any, parent: any = '') {
@@ -183,12 +193,18 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
+    "One": o([
+        { json: "b", js: "b", typ: u(null, "") },
+        { json: "kind", js: "kind", typ: r("PurpleKind") },
+    ], "any"),
+    "Two": o([
         { json: "b", js: "b", typ: u(undefined, u(null, "")) },
-        { json: "kind", js: "kind", typ: r("Kind") },
+        { json: "kind", js: "kind", typ: r("FluffyKind") },
     ], "any"),
-    "Kind": [
+    "PurpleKind": [
         "one",
+    ],
+    "FluffyKind": [
         "two",
     ],
 };
diff --git a/head/schema-flow/test/inputs/schema/one-of-objects.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/one-of-objects.schema/default/TopLevel.js
new file mode 100644
index 0000000..64e68e5
--- /dev/null
+++ b/head/schema-flow/test/inputs/schema/one-of-objects.schema/default/TopLevel.js
@@ -0,0 +1,208 @@
+// @flow
+
+// To parse this data:
+//
+//   const Convert = require("./TopLevel");
+//
+//   const topLevel = Convert.toTopLevel(json);
+//
+// These functions will throw an error if the JSON doesn't
+// match the expected interface, even if the JSON is valid.
+
+export type TopLevel = {
+    items: ItemElement[];
+};
+
+export type ItemElement = PurpleItem | FluffyItem;
+
+export type PurpleItem = {
+    aa?: string;
+    bb?: string;
+};
+
+export type FluffyItem = {
+    cc?: string;
+    dd?: string;
+};
+
+// Converts JSON strings to/from your types
+// and asserts the results of JSON.parse at runtime
+function toTopLevel(json: string): TopLevel {
+    return cast(JSON.parse(json), r("TopLevel"));
+}
+
+function topLevelToJson(value: TopLevel): string {
+    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+}
+
+function invalidValue(typ: any, val: any, key: any, parent: any = '') {
+    const prettyTyp = prettyTypeName(typ);
+    const parentText = parent ? ` on ${parent}` : '';
+    const keyText = key ? ` for key "${key}"` : '';
+    throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);
+}
+
+function prettyTypeName(typ: any): string {
+    if (Array.isArray(typ)) {
+        if (typ.length === 2 && typ[0] === undefined) {
+            return `an optional ${prettyTypeName(typ[1])}`;
+        } else {
+            return `one of [${typ.map(a => { return prettyTypeName(a); }).join(", ")}]`;
+        }
+    } else if (typeof typ === "object" && typ.literal !== undefined) {
+        return typ.literal;
+    } else {
+        return typeof typ;
+    }
+}
+
+function jsonToJSProps(typ: any): any {
+    if (typ.jsonToJS === undefined) {
+        const map: any = {};
+        typ.props.forEach((p: any) => map[p.json] = { key: p.js, typ: p.typ });
+        typ.jsonToJS = map;
+    }
+    return typ.jsonToJS;
+}
+
+function jsToJSONProps(typ: any): any {
+    if (typ.jsToJSON === undefined) {
+        const map: any = {};
+        typ.props.forEach((p: any) => map[p.js] = { key: p.json, typ: p.typ });
+        typ.jsToJSON = map;
+    }
+    return typ.jsToJSON;
+}
+
+function transform(val: any, typ: any, getProps: any, key: any = '', parent: any = ''): any {
+    function transformPrimitive(typ: string, val: any): any {
+        if (typeof typ === typeof val) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+
+    function transformUnion(typs: any[], val: any): any {
+        // val must validate against one typ in typs
+        const l = typs.length;
+        for (let i = 0; i < l; i++) {
+            const typ = typs[i];
+            try {
+                return transform(val, typ, getProps);
+            } catch (_) {}
+        }
+        return invalidValue(typs, val, key, parent);
+    }
+
+    function transformEnum(cases: string[], val: any): any {
+        if (cases.indexOf(val) !== -1) return val;
+        return invalidValue(cases.map(a => { return l(a); }), val, key, parent);
+    }
+
+    function transformArray(typ: any, val: any): any {
+        // val must be an array with no invalid elements
+        if (!Array.isArray(val)) return invalidValue(l("array"), val, key, parent);
+        return val.map(el => transform(el, typ, getProps));
+    }
+
+    function transformDate(val: any): any {
+        if (val === null) {
+            return null;
+        }
+        const d = new Date(val);
+        if (isNaN(d.valueOf())) {
+            return invalidValue(l("Date"), val, key, parent);
+        }
+        return d;
+    }
+
+    function transformObject(props: { [k: string]: any }, additional: any, val: any): any {
+        if (val === null || typeof val !== "object" || Array.isArray(val)) {
+            return invalidValue(l(ref || "object"), val, key, parent);
+        }
+        const result: any = {};
+        Object.getOwnPropertyNames(props).forEach(key => {
+            const prop = props[key];
+            const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;
+            result[prop.key] = transform(v, prop.typ, getProps, key, ref);
+        });
+        Object.getOwnPropertyNames(val).forEach(key => {
+            if (!Object.prototype.hasOwnProperty.call(props, key)) {
+                result[key] = transform(val[key], additional, getProps, key, ref);
+            }
+        });
+        return result;
+    }
+
+    if (typ === "any") return val;
+    if (typ === null) {
+        if (val === null) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+    if (typ === false) return invalidValue(typ, val, key, parent);
+    let ref: any = undefined;
+    while (typeof typ === "object" && typ.ref !== undefined) {
+        ref = typ.ref;
+        typ = typeMap[typ.ref];
+    }
+    if (Array.isArray(typ)) return transformEnum(typ, val);
+    if (typeof typ === "object") {
+        return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val)
+            : typ.hasOwnProperty("arrayItems")    ? transformArray(typ.arrayItems, val)
+            : typ.hasOwnProperty("props")         ? transformObject(getProps(typ), typ.additional, val)
+            : invalidValue(typ, val, key, parent);
+    }
+    // Numbers can be parsed by Date but shouldn't be.
+    if (typ === Date && typeof val !== "number") return transformDate(val);
+    return transformPrimitive(typ, val);
+}
+
+function cast<T>(val: any, typ: any): T {
+    return transform(val, typ, jsonToJSProps);
+}
+
+function uncast<T>(val: T, typ: any): any {
+    return transform(val, typ, jsToJSONProps);
+}
+
+function l(typ: any) {
+    return { literal: typ };
+}
+
+function a(typ: any) {
+    return { arrayItems: typ };
+}
+
+function u(...typs: any[]) {
+    return { unionMembers: typs };
+}
+
+function o(props: any[], additional: any) {
+    return { props, additional };
+}
+
+function m(additional: any) {
+    const props: any[] = [];
+    return { props, additional };
+}
+
+function r(name: string) {
+    return { ref: name };
+}
+
+const typeMap: any = {
+    "TopLevel": o([
+        { json: "items", js: "items", typ: a(u(r("PurpleItem"), r("FluffyItem"))) },
+    ], false),
+    "PurpleItem": o([
+        { json: "aa", js: "aa", typ: u(undefined, "") },
+        { json: "bb", js: "bb", typ: u(undefined, "") },
+    ], false),
+    "FluffyItem": o([
+        { json: "cc", js: "cc", typ: u(undefined, "") },
+        { json: "dd", js: "dd", typ: u(undefined, "") },
+    ], false),
+};
+
+module.exports = {
+    "topLevelToJson": topLevelToJson,
+    "toTopLevel": toTopLevel,
+};
diff --git a/base/schema-flow/test/inputs/schema/postman-collection.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/postman-collection.schema/default/TopLevel.js
index 65a8469..12f63f9 100644
--- a/base/schema-flow/test/inputs/schema/postman-collection.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/postman-collection.schema/default/TopLevel.js
@@ -9,11 +9,17 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
+export type Group = {
+    item?: TopLevel[];
+    [property: string]: mixed;
+};
+
 /**
  * Postman collection
  */
-export type TopLevel = {
-    item?:     TopLevel[];
+export type TopLevel = Group | Item;
+
+export type Item = {
     name?:     string;
     response?: Response[];
     [property: string]: mixed;
@@ -27,11 +33,11 @@ export type Response = {
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json: string): TopLevel {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("Group"), r("Item")));
 }
 
 function topLevelToJson(value: TopLevel): string {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("Group"), r("Item"))), null, 2);
 }
 
 function invalidValue(typ: any, val: any, key: any, parent: any = '') {
@@ -188,8 +194,10 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
-        { json: "item", js: "item", typ: u(undefined, a(r("TopLevel"))) },
+    "Group": o([
+        { json: "item", js: "item", typ: u(undefined, a(u(r("Group"), r("Item")))) },
+    ], "any"),
+    "Item": o([
         { json: "name", js: "name", typ: u(undefined, "") },
         { json: "response", js: "response", typ: u(undefined, a(r("Response"))) },
     ], "any"),
diff --git a/base/schema-flow/test/inputs/schema/union.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/union.schema/default/TopLevel.js
index 828bfcb..16bf58b 100644
--- a/base/schema-flow/test/inputs/schema/union.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/union.schema/default/TopLevel.js
@@ -9,21 +9,28 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
-export type TopLevel = {
-    one?:   number;
-    two:    boolean;
-    three?: number;
+export type TopLevel = PurpleTopLevel | FluffyTopLevel;
+
+export type PurpleTopLevel = {
+    one: number;
+    two: boolean;
+    [property: string]: mixed;
+};
+
+export type FluffyTopLevel = {
+    three: number;
+    two:   boolean;
     [property: string]: mixed;
 };
 
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json: string): TopLevel[] {
-    return cast(JSON.parse(json), a(r("TopLevel")));
+    return cast(JSON.parse(json), a(u(r("PurpleTopLevel"), r("FluffyTopLevel"))));
 }
 
 function topLevelToJson(value: TopLevel[]): string {
-    return JSON.stringify(uncast(value, a(r("TopLevel"))), null, 2);
+    return JSON.stringify(uncast(value, a(u(r("PurpleTopLevel"), r("FluffyTopLevel")))), null, 2);
 }
 
 function invalidValue(typ: any, val: any, key: any, parent: any = '') {
@@ -180,10 +187,13 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
-        { json: "one", js: "one", typ: u(undefined, 0) },
+    "PurpleTopLevel": o([
+        { json: "one", js: "one", typ: 0 },
+        { json: "two", js: "two", typ: true },
+    ], "any"),
+    "FluffyTopLevel": o([
+        { json: "three", js: "three", typ: 3.14 },
         { json: "two", js: "two", typ: true },
-        { json: "three", js: "three", typ: u(undefined, 3.14) },
     ], "any"),
 };
 
diff --git a/base/schema-flow/test/inputs/schema/vega-lite.schema/default/TopLevel.js b/head/schema-flow/test/inputs/schema/vega-lite.schema/default/TopLevel.js
index 988f4c8..c6232b2 100644
--- a/base/schema-flow/test/inputs/schema/vega-lite.schema/default/TopLevel.js
+++ b/head/schema-flow/test/inputs/schema/vega-lite.schema/default/TopLevel.js
@@ -9,7 +9,9 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
-export type TopLevel = {
+export type TopLevel = TopLevelFacetedUnitSpec | TopLevelLayerSpec | TopLevelFacetSpec | TopLevelRepeatSpec | TopLevelVConcatSpec | TopLevelHConcatSpec;
+
+export type TopLevelFacetedUnitSpec = {
     /**
      * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
      * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
@@ -49,7 +51,7 @@ export type TopLevel = {
     /**
      * A key-value mapping between encoding channels and definition of fields.
      */
-    encoding?: EncodingWithFacet;
+    encoding: EncodingWithFacet;
     /**
      * The height of a visualization.
      *
@@ -76,7 +78,7 @@ export type TopLevel = {
      * * `"area"`, `"point"`, `"rule"`, `"geoshape"`, and `"text"`) or a [mark definition
      * object](mark.html#mark-def).
      */
-    mark?: AnyMark;
+    mark: AnyMark;
     /**
      * Name of the visualization for later reference.
      */
@@ -132,47 +134,6 @@ export type TopLevel = {
      * __See also:__ The documentation for [width and height](size.html) contains more examples.
      */
     width?: number;
-    /**
-     * Layer or single view specifications to be layered.
-     *
-     * __Note__: Specifications inside `layer` cannot use `row` and `column` channels as
-     * layering facet specifications is not allowed.
-     */
-    layer?: LayerSpec[];
-    /**
-     * Scale, axis, and legend resolutions for layers.
-     *
-     * Scale, axis, and legend resolutions for facets.
-     *
-     * Scale and legend resolutions for repeated charts.
-     *
-     * Scale, axis, and legend resolutions for vertically concatenated charts.
-     *
-     * Scale, axis, and legend resolutions for horizontally concatenated charts.
-     */
-    resolve?: Resolve;
-    /**
-     * An object that describes mappings between `row` and `column` channels and their field
-     * definitions.
-     */
-    facet?: FacetMapping;
-    /**
-     * A specification of the view that gets faceted.
-     */
-    spec?: Spec;
-    /**
-     * An object that describes what fields should be repeated into views that are laid out as a
-     * `row` or `column`.
-     */
-    repeat?: Repeat;
-    /**
-     * A list of views that should be concatenated and put into a column.
-     */
-    vconcat?: Spec[];
-    /**
-     * A list of views that should be concatenated and put into a row.
-     */
-    hconcat?: Spec[];
 };
 
 /**
@@ -1814,21 +1775,18 @@ export type RangeConfig = {
  *
  * Default range for _quantitative_ and _temporal_ fields.
  */
-export type Category = string[] | CategoryVGScheme;
+export type Category = string[] | VGScheme;
 
-export type CategoryVGScheme = {
+export type VGScheme = {
     count?:  number;
     extent?: number[];
     scheme:  string;
 };
 
-export type RangeConfigValue = TitleFontWeight[] | RangeConfigValueVGScheme;
+export type RangeConfigValue = TitleFontWeight[] | VGScheme | RangeConfigValueClass;
 
-export type RangeConfigValueVGScheme = {
-    count?:  number;
-    extent?: number[];
-    scheme?: string;
-    step?:   number;
+export type RangeConfigValueClass = {
+    step: number;
 };
 
 /**
@@ -2009,7 +1967,7 @@ export type IntervalSelectionConfig = {
      * used within the same view. This allows a user to interactively pan and
      * zoom the view.
      */
-    bind?: BindEnum;
+    bind?: Bind;
     /**
      * By default, all data values are considered to lie within an empty selection.
      * When set to `none`, empty selections contain no data values.
@@ -2072,7 +2030,7 @@ export type IntervalSelectionConfig = {
  * used within the same view. This allows a user to interactively pan and
  * zoom the view.
  */
-export type BindEnum =
+export type Bind =
       "scales";
 
 /**
@@ -2292,15 +2250,50 @@ export type SingleSelectionConfig = {
     resolve?: SelectionResolution;
 };
 
-export type VGBinding = {
+export type VGBinding = VGCheckboxBinding | VGRadioBinding | VGSelectBinding | VGRangeBinding | VGGenericBinding;
+
+export type VGCheckboxBinding = {
     element?: string;
-    input:    string;
-    options?: string[];
+    input:    PurpleInput;
+};
+
+export type PurpleInput =
+      "checkbox";
+
+export type VGRadioBinding = {
+    element?: string;
+    input:    FluffyInput;
+    options:  string[];
+};
+
+export type FluffyInput =
+      "radio";
+
+export type VGSelectBinding = {
+    element?: string;
+    input:    TentacledInput;
+    options:  string[];
+};
+
+export type TentacledInput =
+      "select";
+
+export type VGRangeBinding = {
+    element?: string;
+    input:    StickyInput;
     max?:     number;
     min?:     number;
     step?:    number;
 };
 
+export type StickyInput =
+      "range";
+
+export type VGGenericBinding = {
+    element?: string;
+    input:    string;
+};
+
 /**
  * Default stack offset for stackable mark.
  */
@@ -3039,31 +3032,18 @@ export type ViewConfig = {
  *
  * Secondary data source to lookup in.
  */
-export type Data = {
+export type Data = URLData | InlineData | NamedData;
+
+export type URLData = {
     /**
      * An object that specifies the format for parsing the data file.
-     *
-     * An object that specifies the format for parsing the data values.
-     *
-     * An object that specifies the format for parsing the data.
      */
     format?: DataFormat;
     /**
      * An URL from which to load the data set. Use the `format.type` property
      * to ensure the loaded data is correctly parsed.
      */
-    url?: string;
-    /**
-     * The full data set, included inline. This can be an array of objects or primitive values
-     * or a string.
-     * Arrays of primitive values are ingested as objects with a `data` property. Strings are
-     * parsed according to the specified format type.
-     */
-    values?: Values;
-    /**
-     * Provide a placeholder name and bind data at runtime.
-     */
-    name?: string;
+    url: string;
 };
 
 /**
@@ -3073,7 +3053,9 @@ export type Data = {
  *
  * An object that specifies the format for parsing the data.
  */
-export type DataFormat = {
+export type DataFormat = CSVDataFormat | JSONDataFormat | TopoDataFormat;
+
+export type CSVDataFormat = {
     /**
      * If set to auto (the default), perform automatic type inference to determine the desired
      * data types.
@@ -3096,7 +3078,41 @@ export type DataFormat = {
      * The default format type is determined by the extension of the file URL.
      * If no extension is detected, `"json"` will be used by default.
      */
-    type?: DataFormatType;
+    type?: PurpleType;
+};
+
+export type ParseUnion = ParseEnum | { [key: string]: mixed };
+
+export type ParseEnum =
+      "auto";
+
+/**
+ * Type of input data: `"json"`, `"csv"`, `"tsv"`.
+ * The default format type is determined by the extension of the file URL.
+ * If no extension is detected, `"json"` will be used by default.
+ */
+export type PurpleType =
+      "csv"
+    | "tsv";
+
+export type JSONDataFormat = {
+    /**
+     * If set to auto (the default), perform automatic type inference to determine the desired
+     * data types.
+     * Alternatively, a parsing directive object can be provided for explicit data types. Each
+     * property of the object corresponds to a field name, and the value to the desired data
+     * type (one of `"number"`, `"boolean"` or `"date"`).
+     * For example, `"parse": {"modified_on": "date"}` parses the `modified_on` field in each
+     * input record a Date value.
+     *
+     * For `"date"`, we parse data based using Javascript's
+     * [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
+     * For Specific date formats can be provided (e.g., `{foo: 'date:"%m%d%Y"'}`), using the
+     * [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date
+     * format parsing is supported similarly (e.g., `{foo: 'utc:"%m%d%Y"'}`). See more about
+     * [UTC time](timeunit.html#utc)
+     */
+    parse?: ParseUnion;
     /**
      * The JSON property containing the desired data.
      * This parameter can be used when the loaded JSON file may have surrounding structure or
@@ -3106,6 +3122,23 @@ export type DataFormat = {
      * from the loaded JSON object.
      */
     property?: string;
+    /**
+     * Type of input data: `"json"`, `"csv"`, `"tsv"`.
+     * The default format type is determined by the extension of the file URL.
+     * If no extension is detected, `"json"` will be used by default.
+     */
+    type?: FluffyType;
+};
+
+/**
+ * Type of input data: `"json"`, `"csv"`, `"tsv"`.
+ * The default format type is determined by the extension of the file URL.
+ * If no extension is detected, `"json"` will be used by default.
+ */
+export type FluffyType =
+      "json";
+
+export type TopoDataFormat = {
     /**
      * The name of the TopoJSON object set to convert to a GeoJSON feature collection.
      * For example, in a map of the world, there may be an object set named `"countries"`.
@@ -3123,23 +3156,52 @@ export type DataFormat = {
      * countries, states or counties.
      */
     mesh?: string;
+    /**
+     * If set to auto (the default), perform automatic type inference to determine the desired
+     * data types.
+     * Alternatively, a parsing directive object can be provided for explicit data types. Each
+     * property of the object corresponds to a field name, and the value to the desired data
+     * type (one of `"number"`, `"boolean"` or `"date"`).
+     * For example, `"parse": {"modified_on": "date"}` parses the `modified_on` field in each
+     * input record a Date value.
+     *
+     * For `"date"`, we parse data based using Javascript's
+     * [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
+     * For Specific date formats can be provided (e.g., `{foo: 'date:"%m%d%Y"'}`), using the
+     * [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date
+     * format parsing is supported similarly (e.g., `{foo: 'utc:"%m%d%Y"'}`). See more about
+     * [UTC time](timeunit.html#utc)
+     */
+    parse?: ParseUnion;
+    /**
+     * Type of input data: `"json"`, `"csv"`, `"tsv"`.
+     * The default format type is determined by the extension of the file URL.
+     * If no extension is detected, `"json"` will be used by default.
+     */
+    type?: TentacledType;
 };
 
-export type ParseUnion = ParseEnum | { [key: string]: mixed };
-
-export type ParseEnum =
-      "auto";
-
 /**
  * Type of input data: `"json"`, `"csv"`, `"tsv"`.
  * The default format type is determined by the extension of the file URL.
  * If no extension is detected, `"json"` will be used by default.
  */
-export type DataFormatType =
-      "csv"
-    | "tsv"
-    | "json"
-    | "topojson";
+export type TentacledType =
+      "topojson";
+
+export type InlineData = {
+    /**
+     * An object that specifies the format for parsing the data values.
+     */
+    format?: DataFormat;
+    /**
+     * The full data set, included inline. This can be an array of objects or primitive values
+     * or a string.
+     * Arrays of primitive values are ingested as objects with a `data` property. Strings are
+     * parsed according to the specified format type.
+     */
+    values: Values;
+};
 
 /**
  * The full data set, included inline. This can be an array of objects or primitive values
@@ -3151,6 +3213,17 @@ export type Values = ValuesValue[] | { [key: string]: mixed } | string;
 
 export type ValuesValue = boolean | number | { [key: string]: mixed } | string;
 
+export type NamedData = {
+    /**
+     * An object that specifies the format for parsing the data.
+     */
+    format?: DataFormat;
+    /**
+     * Provide a placeholder name and bind data at runtime.
+     */
+    name: string;
+};
+
 /**
  * A key-value mapping between encoding channels and definition of fields.
  */
@@ -3166,7 +3239,7 @@ export type EncodingWithFacet = {
      * _Note:_ See the scale documentation for more information about customizing [color
      * scheme](scale.html#scheme).
      */
-    color?: MarkPropDefWithCondition;
+    color?: Color;
     /**
      * Horizontal facets for trellis plots.
      */
@@ -3179,14 +3252,14 @@ export type EncodingWithFacet = {
     /**
      * A URL to load upon mouse click.
      */
-    href?: DefWithCondition;
+    href?: Href;
     /**
      * Opacity of the marks – either can be a value or a range.
      *
      * __Default value:__ If undefined, the default opacity depends on [mark
      * config](config.html#mark)'s `opacity` property.
      */
-    opacity?: MarkPropDefWithCondition;
+    opacity?: Color;
     /**
      * Stack order for stacked marks or order of data points in line marks for connected scatter
      * plots.
@@ -3208,7 +3281,7 @@ export type EncodingWithFacet = {
      * __Default value:__ If undefined, the default shape depends on [mark
      * config](config.html#point-config)'s `shape` property.
      */
-    shape?: MarkPropDefWithCondition;
+    shape?: Color;
     /**
      * Size of the mark.
      * - For `"point"`, `"square"` and `"circle"`, – the symbol size, or pixel area of the mark.
@@ -3216,31 +3289,31 @@ export type EncodingWithFacet = {
      * - For `"text"` – the text's font size.
      * - Size is currently unsupported for `"line"`, `"area"`, and `"rect"`.
      */
-    size?: MarkPropDefWithCondition;
+    size?: Color;
     /**
      * Text of the `text` mark.
      */
-    text?: TextDefWithCondition;
+    text?: Text;
     /**
      * The tooltip text to show upon mouse hover.
      */
-    tooltip?: TextDefWithCondition;
+    tooltip?: Text;
     /**
      * X coordinates of the marks, or width of horizontal `"bar"` and `"area"`.
      */
-    x?: XClass;
+    x?: X;
     /**
      * X2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
      */
-    x2?: X2Class;
+    x2?: X2;
     /**
      * Y coordinates of the marks, or height of vertical `"bar"` and `"area"`.
      */
-    y?: XClass;
+    y?: X;
     /**
      * Y2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
      */
-    y2?: X2Class;
+    y2?: X2;
 };
 
 /**
@@ -3272,21 +3345,18 @@ export type EncodingWithFacet = {
  * - For `"bar"` and `"tick"` – the bar and tick's size.
  * - For `"text"` – the text's font size.
  * - Size is currently unsupported for `"line"`, `"area"`, and `"rect"`.
- *
+ */
+export type Color = MarkPropFieldDefWithCondition | MarkPropValueDefWithCondition;
+
+/**
  * A FieldDef with Condition<ValueDef>
  * {
  * condition: {value: ...},
  * field: ...,
  * ...
  * }
- *
- * A ValueDef with Condition<ValueDef | FieldDef>
- * {
- * condition: {field: ...} | {value: ...},
- * value: ...,
- * }
  */
-export type MarkPropDefWithCondition = {
+export type MarkPropFieldDefWithCondition = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -3308,10 +3378,8 @@ export type MarkPropDefWithCondition = {
      * __Note:__ A field definition's `condition` property can only contain [value
      * definitions](encoding.html#value-def)
      * since Vega-Lite only allows at most one encoded field per encoding channel.
-     *
-     * A field definition or one or more value definition(s) with a selection predicate.
      */
-    condition?: ColorCondition;
+    condition?: ConditionUnion;
     /**
      * __Required.__ A string defining the name of the field from which to pull a data value
      * or an object defining iterated values from the [`repeat`](repeat.html) operator.
@@ -3362,11 +3430,7 @@ export type MarkPropDefWithCondition = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
-    /**
-     * A constant value in visual domain.
-     */
-    value?: ConditionalValueDefValue;
+    type: Type;
 };
 
 /**
@@ -3465,84 +3529,58 @@ export type BinParams = {
     steps?: number[];
 };
 
-export type ColorCondition = ConditionalValueDef[] | ConditionalPredicateMarkPropFieldDefClass;
+export type ConditionUnion = ConditionalValueDef[] | ConditionalPredicateValueDef | ConditionalSelectionValueDef;
 
-export type ConditionalValueDef = {
-    test?: LogicalOperandPredicate;
+export type ConditionalValueDef = ConditionalPredicateValueDef | ConditionalSelectionValueDef;
+
+export type ConditionalPredicateValueDef = {
+    test: LogicalOperandPredicate;
     /**
      * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
      * `0` to `1` for opacity).
      */
-    value: ConditionalValueDefValue;
-    /**
-     * A [selection name](selection.html), or a series of [composed
-     * selections](selection.html#compose).
-     */
-    selection?: SelectionOperand;
+    value: ConditionValue;
+};
+
+export type LogicalOrPredicate = {
+    or: LogicalOperandPredicate[];
+};
+
+export type LogicalAndPredicate = {
+    and: LogicalOperandPredicate[];
 };
 
-export type Selection = {
-    not?: SelectionOperand;
-    and?: SelectionOperand[];
-    or?:  SelectionOperand[];
+export type LogicalNotPredicate = {
+    not: LogicalOperandPredicate;
 };
 
 /**
- * Filter using a selection name.
- *
- * A [selection name](selection.html), or a series of [composed
- * selections](selection.html#compose).
+ * The `filter` property must be one of the predicate definitions:
+ * (1) an [expression](types.html#expression) string,
+ * where `datum` can be used to refer to the current data object;
+ * (2) one of the field predicates: [equal predicate](filter.html#equal-predicate);
+ * [range predicate](filter.html#range-predicate), [one-of
+ * predicate](filter.html#one-of-predicate);
+ * (3) a [selection predicate](filter.html#selection-predicate);
+ * or (4) a logical operand that combines (1), (2), or (3).
  */
-export type SelectionOperand = Selection | string;
+export type LogicalOperandPredicate = LogicalNotPredicate | LogicalAndPredicate | LogicalOrPredicate | FieldEqualPredicate | FieldRangePredicate | FieldOneOfPredicate | SelectionPredicate | string;
 
-export type Predicate = {
-    not?: LogicalOperandPredicate;
-    and?: LogicalOperandPredicate[];
-    or?:  LogicalOperandPredicate[];
+export type FieldEqualPredicate = {
     /**
      * The value that the field should be equal to.
      */
-    equal?: Equal;
+    equal: Equal;
     /**
      * Field to be filtered.
-     *
-     * Field to be filtered
      */
-    field?: string;
+    field: string;
     /**
      * Time unit for the field to be filtered.
-     *
-     * time unit for the field to be filtered.
      */
     timeUnit?: TimeUnit;
-    /**
-     * An array of inclusive minimum and maximum values
-     * for a field value of a data item to be included in the filtered data.
-     */
-    range?: RangeElement[];
-    /**
-     * A set of values that the `field`'s value should be a member of,
-     * for a data item included in the filtered data.
-     */
-    oneOf?: Equal[];
-    /**
-     * Filter using a selection name.
-     */
-    selection?: SelectionOperand;
 };
 
-/**
- * The `filter` property must be one of the predicate definitions:
- * (1) an [expression](types.html#expression) string,
- * where `datum` can be used to refer to the current data object;
- * (2) one of the field predicates: [equal predicate](filter.html#equal-predicate);
- * [range predicate](filter.html#range-predicate), [one-of
- * predicate](filter.html#one-of-predicate);
- * (3) a [selection predicate](filter.html#selection-predicate);
- * or (4) a logical operand that combines (1), (2), or (3).
- */
-export type LogicalOperandPredicate = Predicate | string;
-
 /**
  * The value that the field should be equal to.
  */
@@ -3620,8 +3658,6 @@ export type Day = number | string;
  */
 export type Month = number | string;
 
-export type RangeElement = DateTime | number | null;
-
 /**
  * Time unit for the field to be filtered.
  *
@@ -3680,92 +3716,86 @@ export type TimeUnit =
     | "utcminutesseconds"
     | "utcsecondsmilliseconds";
 
-/**
- * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
- * `0` to `1` for opacity).
- *
- * A constant value in visual domain.
- */
-export type ConditionalValueDefValue = boolean | number | string;
-
-export type ConditionalPredicateMarkPropFieldDefClass = {
-    test?: LogicalOperandPredicate;
+export type FieldRangePredicate = {
     /**
-     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
-     * `0` to `1` for opacity).
+     * Field to be filtered
      */
-    value?: ConditionalValueDefValue;
+    field: string;
     /**
-     * A [selection name](selection.html), or a series of [composed
-     * selections](selection.html#compose).
+     * An array of inclusive minimum and maximum values
+     * for a field value of a data item to be included in the filtered data.
      */
-    selection?: SelectionOperand;
+    range: RangeElement[];
     /**
-     * Aggregation function for the field
-     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
-     *
-     * __Default value:__ `undefined` (None)
+     * time unit for the field to be filtered.
      */
-    aggregate?: AggregateOp;
-    /**
-     * A flag for binning a `quantitative` field, or [an object defining binning
-     * parameters](bin.html#params).
-     * If `true`, default [binning parameters](bin.html) will be applied.
-     *
-     * __Default value:__ `false`
-     */
-    bin?: Bin;
+    timeUnit?: TimeUnit;
+};
+
+export type RangeElement = DateTime | number | null;
+
+export type FieldOneOfPredicate = {
     /**
-     * __Required.__ A string defining the name of the field from which to pull a data value
-     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
-     *
-     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
-     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
-     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
-     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
-     * See more details about escaping in the [field documentation](field.html).
-     *
-     * __Note:__ `field` is not required if `aggregate` is `count`.
+     * Field to be filtered
      */
-    field?: Field;
+    field: string;
     /**
-     * An object defining properties of the legend.
-     * If `null`, the legend for the encoding channel will be removed.
-     *
-     * __Default value:__ If undefined, default [legend properties](legend.html) are applied.
+     * A set of values that the `field`'s value should be a member of,
+     * for a data item included in the filtered data.
      */
-    legend?: Legend | null;
+    oneOf: Equal[];
     /**
-     * An object defining properties of the channel's scale, which is the function that
-     * transforms values in the data domain (numbers, dates, strings, etc) to visual values
-     * (pixels, colors, sizes) of the encoding channels.
-     *
-     * __Default value:__ If undefined, default [scale properties](scale.html) are applied.
+     * time unit for the field to be filtered.
      */
-    scale?: Scale;
+    timeUnit?: TimeUnit;
+};
+
+export type SelectionPredicate = {
     /**
-     * Sort order for the encoded field.
-     * Supported `sort` values include `"ascending"`, `"descending"` and `null` (no sorting).
-     * For fields with discrete domains, `sort` can also be a [sort field definition
-     * object](sort.html#sort-field).
-     *
-     * __Default value:__ `"ascending"`
+     * Filter using a selection name.
      */
-    sort?: SortUnion;
+    selection: SelectionOperand;
+};
+
+export type SelectionOr = {
+    or: SelectionOperand[];
+};
+
+export type SelectionAnd = {
+    and: SelectionOperand[];
+};
+
+export type SelectionNot = {
+    not: SelectionOperand;
+};
+
+/**
+ * Filter using a selection name.
+ *
+ * A [selection name](selection.html), or a series of [composed
+ * selections](selection.html#compose).
+ */
+export type SelectionOperand = SelectionNot | SelectionAnd | SelectionOr | string;
+
+/**
+ * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
+ * `0` to `1` for opacity).
+ *
+ * A constant value in visual domain.
+ */
+export type ConditionValue = boolean | number | string;
+
+export type ConditionalSelectionValueDef = {
     /**
-     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
-     * or [a temporal field that gets casted as ordinal](type.html#cast).
-     *
-     * __Default value:__ `undefined` (None)
+     * A [selection name](selection.html), or a series of [composed
+     * selections](selection.html#compose).
      */
-    timeUnit?: TimeUnit;
+    selection: SelectionOperand;
     /**
-     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
-     * `"nominal"`).
-     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
-     * [geographic projection](projection.html) is applied.
+     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
+     * `0` to `1` for opacity).
      */
-    type?: Type;
+    value: ConditionValue;
 };
 
 export type Field = RepeatRef | string;
@@ -4098,9 +4128,9 @@ export type Scale = {
  * The `selection` property can be used to [interactively
  * determine](selection.html#scale-domains) the scale domain.
  */
-export type DomainUnion = Equal[] | DomainClass | Domain;
+export type DomainUnion = Equal[] | PurpleSelectionDomain | FluffySelectionDomain | Domain;
 
-export type DomainClass = {
+export type PurpleSelectionDomain = {
     /**
      * The field name to extract selected values for, when a selection is
      * [projected](project.html)
@@ -4111,12 +4141,19 @@ export type DomainClass = {
      * The name of a selection.
      */
     selection: string;
+};
+
+export type FluffySelectionDomain = {
     /**
      * The encoding channel to extract selected values for, when a selection is
      * [projected](project.html)
      * over multiple fields or encodings.
      */
     encoding?: string;
+    /**
+     * The name of a selection.
+     */
+    selection: string;
 };
 
 export type Domain =
@@ -4273,7 +4310,7 @@ export type ScaleType =
     | "point"
     | "band";
 
-export type SortUnion = SortField | SortEnum | null;
+export type SortUnion = SortField | SortOrderEnum | null;
 
 export type SortField = {
     /**
@@ -4297,10 +4334,10 @@ export type SortField = {
     /**
      * The sort order. One of `"ascending"` (default) or `"descending"`.
      */
-    order?: SortEnum | null;
+    order?: SortOrderEnum | null;
 };
 
-export type SortEnum =
+export type SortOrderEnum =
       "ascending"
     | "descending";
 
@@ -4322,6 +4359,173 @@ export type Type =
     | "longitude"
     | "geojson";
 
+/**
+ * A ValueDef with Condition<ValueDef | FieldDef>
+ * {
+ * condition: {field: ...} | {value: ...},
+ * value: ...,
+ * }
+ */
+export type MarkPropValueDefWithCondition = {
+    /**
+     * A field definition or one or more value definition(s) with a selection predicate.
+     */
+    condition?: ColorCondition;
+    /**
+     * A constant value in visual domain.
+     */
+    value?: ConditionValue;
+};
+
+/**
+ * A field definition or one or more value definition(s) with a selection predicate.
+ */
+export type ColorCondition = ConditionalValueDef[] | ConditionalPredicateMarkPropFieldDef | ConditionalSelectionMarkPropFieldDef | ConditionalPredicateValueDef | ConditionalSelectionValueDef;
+
+export type ConditionalPredicateMarkPropFieldDef = {
+    /**
+     * Aggregation function for the field
+     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    aggregate?: AggregateOp;
+    /**
+     * A flag for binning a `quantitative` field, or [an object defining binning
+     * parameters](bin.html#params).
+     * If `true`, default [binning parameters](bin.html) will be applied.
+     *
+     * __Default value:__ `false`
+     */
+    bin?: Bin;
+    /**
+     * __Required.__ A string defining the name of the field from which to pull a data value
+     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
+     *
+     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
+     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
+     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
+     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
+     * See more details about escaping in the [field documentation](field.html).
+     *
+     * __Note:__ `field` is not required if `aggregate` is `count`.
+     */
+    field?: Field;
+    /**
+     * An object defining properties of the legend.
+     * If `null`, the legend for the encoding channel will be removed.
+     *
+     * __Default value:__ If undefined, default [legend properties](legend.html) are applied.
+     */
+    legend?: Legend | null;
+    /**
+     * An object defining properties of the channel's scale, which is the function that
+     * transforms values in the data domain (numbers, dates, strings, etc) to visual values
+     * (pixels, colors, sizes) of the encoding channels.
+     *
+     * __Default value:__ If undefined, default [scale properties](scale.html) are applied.
+     */
+    scale?: Scale;
+    /**
+     * Sort order for the encoded field.
+     * Supported `sort` values include `"ascending"`, `"descending"` and `null` (no sorting).
+     * For fields with discrete domains, `sort` can also be a [sort field definition
+     * object](sort.html#sort-field).
+     *
+     * __Default value:__ `"ascending"`
+     */
+    sort?: SortUnion;
+    test:  LogicalOperandPredicate;
+    /**
+     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
+     * or [a temporal field that gets casted as ordinal](type.html#cast).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    timeUnit?: TimeUnit;
+    /**
+     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
+     * `"nominal"`).
+     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
+     * [geographic projection](projection.html) is applied.
+     */
+    type: Type;
+};
+
+export type ConditionalSelectionMarkPropFieldDef = {
+    /**
+     * Aggregation function for the field
+     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    aggregate?: AggregateOp;
+    /**
+     * A flag for binning a `quantitative` field, or [an object defining binning
+     * parameters](bin.html#params).
+     * If `true`, default [binning parameters](bin.html) will be applied.
+     *
+     * __Default value:__ `false`
+     */
+    bin?: Bin;
+    /**
+     * __Required.__ A string defining the name of the field from which to pull a data value
+     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
+     *
+     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
+     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
+     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
+     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
+     * See more details about escaping in the [field documentation](field.html).
+     *
+     * __Note:__ `field` is not required if `aggregate` is `count`.
+     */
+    field?: Field;
+    /**
+     * An object defining properties of the legend.
+     * If `null`, the legend for the encoding channel will be removed.
+     *
+     * __Default value:__ If undefined, default [legend properties](legend.html) are applied.
+     */
+    legend?: Legend | null;
+    /**
+     * An object defining properties of the channel's scale, which is the function that
+     * transforms values in the data domain (numbers, dates, strings, etc) to visual values
+     * (pixels, colors, sizes) of the encoding channels.
+     *
+     * __Default value:__ If undefined, default [scale properties](scale.html) are applied.
+     */
+    scale?: Scale;
+    /**
+     * A [selection name](selection.html), or a series of [composed
+     * selections](selection.html#compose).
+     */
+    selection: SelectionOperand;
+    /**
+     * Sort order for the encoded field.
+     * Supported `sort` values include `"ascending"`, `"descending"` and `null` (no sorting).
+     * For fields with discrete domains, `sort` can also be a [sort field definition
+     * object](sort.html#sort-field).
+     *
+     * __Default value:__ `"ascending"`
+     */
+    sort?: SortUnion;
+    /**
+     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
+     * or [a temporal field that gets casted as ordinal](type.html#cast).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    timeUnit?: TimeUnit;
+    /**
+     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
+     * `"nominal"`).
+     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
+     * [geographic projection](projection.html) is applied.
+     */
+    type: Type;
+};
+
 /**
  * Horizontal facets for trellis plots.
  *
@@ -4364,7 +4568,7 @@ export type FacetFieldDef = {
      * Sort order for a facet field.
      * This can be `"ascending"`, `"descending"`.
      */
-    sort?: SortEnum | null;
+    sort?: SortOrderEnum | null;
     /**
      * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
      * or [a temporal field that gets casted as ordinal](type.html#cast).
@@ -4474,21 +4678,18 @@ export type FieldDef = {
 
 /**
  * A URL to load upon mouse click.
- *
+ */
+export type Href = FieldDefWithCondition | ValueDefWithCondition;
+
+/**
  * A FieldDef with Condition<ValueDef>
  * {
  * condition: {value: ...},
  * field: ...,
  * ...
  * }
- *
- * A ValueDef with Condition<ValueDef | FieldDef>
- * {
- * condition: {field: ...} | {value: ...},
- * value: ...,
- * }
  */
-export type DefWithCondition = {
+export type FieldDefWithCondition = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -4510,10 +4711,8 @@ export type DefWithCondition = {
      * __Note:__ A field definition's `condition` property can only contain [value
      * definitions](encoding.html#value-def)
      * since Vega-Lite only allows at most one encoded field per encoding channel.
-     *
-     * A field definition or one or more value definition(s) with a selection predicate.
      */
-    condition?: HrefCondition;
+    condition?: ConditionUnion;
     /**
      * __Required.__ A string defining the name of the field from which to pull a data value
      * or an object defining iterated values from the [`repeat`](repeat.html) operator.
@@ -4540,27 +4739,79 @@ export type DefWithCondition = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
+    type: Type;
+};
+
+/**
+ * A ValueDef with Condition<ValueDef | FieldDef>
+ * {
+ * condition: {field: ...} | {value: ...},
+ * value: ...,
+ * }
+ */
+export type ValueDefWithCondition = {
+    /**
+     * A field definition or one or more value definition(s) with a selection predicate.
+     */
+    condition?: HrefCondition;
     /**
      * A constant value in visual domain.
      */
-    value?: ConditionalValueDefValue;
+    value?: ConditionValue;
 };
 
-export type HrefCondition = ConditionalValueDef[] | ConditionalPredicateFieldDefClass;
+/**
+ * A field definition or one or more value definition(s) with a selection predicate.
+ */
+export type HrefCondition = ConditionalValueDef[] | ConditionalPredicateFieldDef | ConditionalSelectionFieldDef | ConditionalPredicateValueDef | ConditionalSelectionValueDef;
 
-export type ConditionalPredicateFieldDefClass = {
-    test?: LogicalOperandPredicate;
+export type ConditionalPredicateFieldDef = {
     /**
-     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
-     * `0` to `1` for opacity).
+     * Aggregation function for the field
+     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
+     *
+     * __Default value:__ `undefined` (None)
      */
-    value?: ConditionalValueDefValue;
+    aggregate?: AggregateOp;
     /**
-     * A [selection name](selection.html), or a series of [composed
-     * selections](selection.html#compose).
+     * A flag for binning a `quantitative` field, or [an object defining binning
+     * parameters](bin.html#params).
+     * If `true`, default [binning parameters](bin.html) will be applied.
+     *
+     * __Default value:__ `false`
+     */
+    bin?: Bin;
+    /**
+     * __Required.__ A string defining the name of the field from which to pull a data value
+     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
+     *
+     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
+     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
+     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
+     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
+     * See more details about escaping in the [field documentation](field.html).
+     *
+     * __Note:__ `field` is not required if `aggregate` is `count`.
+     */
+    field?: Field;
+    test:   LogicalOperandPredicate;
+    /**
+     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
+     * or [a temporal field that gets casted as ordinal](type.html#cast).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    timeUnit?: TimeUnit;
+    /**
+     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
+     * `"nominal"`).
+     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
+     * [geographic projection](projection.html) is applied.
      */
-    selection?: SelectionOperand;
+    type: Type;
+};
+
+export type ConditionalSelectionFieldDef = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -4589,6 +4840,11 @@ export type ConditionalPredicateFieldDefClass = {
      * __Note:__ `field` is not required if `aggregate` is `count`.
      */
     field?: Field;
+    /**
+     * A [selection name](selection.html), or a series of [composed
+     * selections](selection.html#compose).
+     */
+    selection: SelectionOperand;
     /**
      * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
      * or [a temporal field that gets casted as ordinal](type.html#cast).
@@ -4602,7 +4858,7 @@ export type ConditionalPredicateFieldDefClass = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
+    type: Type;
 };
 
 export type Order = OrderFieldDef[] | OrderFieldDef;
@@ -4639,7 +4895,7 @@ export type OrderFieldDef = {
     /**
      * The sort order. One of `"ascending"` (default) or `"descending"`.
      */
-    sort?: SortEnum | null;
+    sort?: SortOrderEnum | null;
     /**
      * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
      * or [a temporal field that gets casted as ordinal](type.html#cast).
@@ -4660,21 +4916,18 @@ export type OrderFieldDef = {
  * Text of the `text` mark.
  *
  * The tooltip text to show upon mouse hover.
- *
+ */
+export type Text = TextFieldDefWithCondition | TextValueDefWithCondition;
+
+/**
  * A FieldDef with Condition<ValueDef>
  * {
  * condition: {value: ...},
  * field: ...,
  * ...
  * }
- *
- * A ValueDef with Condition<ValueDef | FieldDef>
- * {
- * condition: {field: ...} | {value: ...},
- * value: ...,
- * }
  */
-export type TextDefWithCondition = {
+export type TextFieldDefWithCondition = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -4696,10 +4949,8 @@ export type TextDefWithCondition = {
      * __Note:__ A field definition's `condition` property can only contain [value
      * definitions](encoding.html#value-def)
      * since Vega-Lite only allows at most one encoded field per encoding channel.
-     *
-     * A field definition or one or more value definition(s) with a selection predicate.
      */
-    condition?: TextCondition;
+    condition?: ConditionUnion;
     /**
      * __Required.__ A string defining the name of the field from which to pull a data value
      * or an object defining iterated values from the [`repeat`](repeat.html) operator.
@@ -4731,27 +4982,84 @@ export type TextDefWithCondition = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
+    type: Type;
+};
+
+/**
+ * A ValueDef with Condition<ValueDef | FieldDef>
+ * {
+ * condition: {field: ...} | {value: ...},
+ * value: ...,
+ * }
+ */
+export type TextValueDefWithCondition = {
+    /**
+     * A field definition or one or more value definition(s) with a selection predicate.
+     */
+    condition?: TextCondition;
     /**
      * A constant value in visual domain.
      */
-    value?: ConditionalValueDefValue;
+    value?: ConditionValue;
 };
 
-export type TextCondition = ConditionalValueDef[] | ConditionalPredicateTextFieldDefClass;
+/**
+ * A field definition or one or more value definition(s) with a selection predicate.
+ */
+export type TextCondition = ConditionalValueDef[] | ConditionalPredicateTextFieldDef | ConditionalSelectionTextFieldDef | ConditionalPredicateValueDef | ConditionalSelectionValueDef;
 
-export type ConditionalPredicateTextFieldDefClass = {
-    test?: LogicalOperandPredicate;
+export type ConditionalPredicateTextFieldDef = {
     /**
-     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
-     * `0` to `1` for opacity).
+     * Aggregation function for the field
+     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
+     *
+     * __Default value:__ `undefined` (None)
      */
-    value?: ConditionalValueDefValue;
+    aggregate?: AggregateOp;
     /**
-     * A [selection name](selection.html), or a series of [composed
-     * selections](selection.html#compose).
+     * A flag for binning a `quantitative` field, or [an object defining binning
+     * parameters](bin.html#params).
+     * If `true`, default [binning parameters](bin.html) will be applied.
+     *
+     * __Default value:__ `false`
+     */
+    bin?: Bin;
+    /**
+     * __Required.__ A string defining the name of the field from which to pull a data value
+     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
+     *
+     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
+     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
+     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
+     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
+     * See more details about escaping in the [field documentation](field.html).
+     *
+     * __Note:__ `field` is not required if `aggregate` is `count`.
+     */
+    field?: Field;
+    /**
+     * The [formatting pattern](format.html) for a text field. If not defined, this will be
+     * determined automatically.
+     */
+    format?: string;
+    test:    LogicalOperandPredicate;
+    /**
+     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
+     * or [a temporal field that gets casted as ordinal](type.html#cast).
+     *
+     * __Default value:__ `undefined` (None)
+     */
+    timeUnit?: TimeUnit;
+    /**
+     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
+     * `"nominal"`).
+     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
+     * [geographic projection](projection.html) is applied.
      */
-    selection?: SelectionOperand;
+    type: Type;
+};
+
+export type ConditionalSelectionTextFieldDef = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -4785,6 +5093,11 @@ export type ConditionalPredicateTextFieldDefClass = {
      * determined automatically.
      */
     format?: string;
+    /**
+     * A [selection name](selection.html), or a series of [composed
+     * selections](selection.html#compose).
+     */
+    selection: SelectionOperand;
     /**
      * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
      * or [a temporal field that gets casted as ordinal](type.html#cast).
@@ -4798,17 +5111,17 @@ export type ConditionalPredicateTextFieldDefClass = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
+    type: Type;
 };
 
 /**
  * X coordinates of the marks, or width of horizontal `"bar"` and `"area"`.
  *
  * Y coordinates of the marks, or height of vertical `"bar"` and `"area"`.
- *
- * Definition object for a constant value of an encoding channel.
  */
-export type XClass = {
+export type X = PositionFieldDef | ValueDef;
+
+export type PositionFieldDef = {
     /**
      * Aggregation function for the field
      * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
@@ -4897,12 +5210,7 @@ export type XClass = {
      * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
      * [geographic projection](projection.html) is applied.
      */
-    type?: Type;
-    /**
-     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
-     * `0` to `1` for opacity).
-     */
-    value?: ConditionalValueDefValue;
+    type: Type;
 };
 
 export type Axis = {
@@ -5074,308 +5382,833 @@ export type Axis = {
 
 export type AxisValue = DateTime | number;
 
+/**
+ * Definition object for a constant value of an encoding channel.
+ */
+export type ValueDef = {
+    /**
+     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
+     * `0` to `1` for opacity).
+     */
+    value: ConditionValue;
+};
+
 /**
  * X2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
  *
  * Y2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
- *
- * Definition object for a data field, its type and transformation of an encoding channel.
- *
- * Definition object for a constant value of an encoding channel.
  */
-export type X2Class = {
+export type X2 = FieldDef | ValueDef;
+
+/**
+ * A string describing the mark type (one of `"bar"`, `"circle"`, `"square"`, `"tick"`,
+ * `"line"`,
+ * * `"area"`, `"point"`, `"rule"`, `"geoshape"`, and `"text"`) or a [mark definition
+ * object](mark.html#mark-def).
+ */
+export type AnyMark = MarkDef | Mark;
+
+export type MarkDef = {
     /**
-     * Aggregation function for the field
-     * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
-     *
-     * __Default value:__ `undefined` (None)
+     * The horizontal alignment of the text. One of `"left"`, `"right"`, `"center"`.
      */
-    aggregate?: AggregateOp;
+    align?: HorizontalAlign;
     /**
-     * A flag for binning a `quantitative` field, or [an object defining binning
-     * parameters](bin.html#params).
-     * If `true`, default [binning parameters](bin.html) will be applied.
-     *
-     * __Default value:__ `false`
+     * The rotation angle of the text, in degrees.
      */
-    bin?: Bin;
+    angle?: number;
     /**
-     * __Required.__ A string defining the name of the field from which to pull a data value
-     * or an object defining iterated values from the [`repeat`](repeat.html) operator.
-     *
-     * __Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects
-     * (e.g., `"field": "foo.bar"` and `"field": "foo['bar']"`).
-     * If field names contain dots or brackets but are not nested, you can use `\\` to escape
-     * dots and brackets (e.g., `"a\\.b"` and `"a\\[0\\]"`).
-     * See more details about escaping in the [field documentation](field.html).
+     * The vertical alignment of the text. One of `"top"`, `"middle"`, `"bottom"`.
      *
-     * __Note:__ `field` is not required if `aggregate` is `count`.
+     * __Default value:__ `"middle"`
      */
-    field?: Field;
+    baseline?: VerticalAlign;
     /**
-     * Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.
-     * or [a temporal field that gets casted as ordinal](type.html#cast).
-     *
-     * __Default value:__ `undefined` (None)
+     * Whether a mark be clipped to the enclosing group’s width and height.
      */
-    timeUnit?: TimeUnit;
+    clip?: boolean;
     /**
-     * The encoded field's type of measurement (`"quantitative"`, `"temporal"`, `"ordinal"`, or
-     * `"nominal"`).
-     * It can also be a geo type (`"latitude"`, `"longitude"`, and `"geojson"`) when a
-     * [geographic projection](projection.html) is applied.
+     * Default color.  Note that `fill` and `stroke` have higher precedence than `color` and
+     * will override `color`.
+     *
+     * __Default value:__ <span style="color: #4682b4;">&#9632;</span> `"#4682b4"`
+     *
+     * __Note:__ This property cannot be used in a [style config](mark.html#style-config).
      */
-    type?: Type;
+    color?: string;
     /**
-     * A constant value in visual domain (e.g., `"red"` / "#0099ff" for color, values between
-     * `0` to `1` for opacity).
+     * The mouse cursor used over the mark. Any valid [CSS cursor
+     * type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.
      */
-    value?: ConditionalValueDefValue;
-};
-
-/**
- * An object that describes mappings between `row` and `column` channels and their field
- * definitions.
- */
-export type FacetMapping = {
+    cursor?: Cursor;
     /**
-     * Horizontal facets for trellis plots.
+     * The horizontal offset, in pixels, between the text label and its anchor point. The offset
+     * is applied after rotation by the _angle_ property.
      */
-    column?: FacetFieldDef;
+    dx?: number;
     /**
-     * Vertical facets for trellis plots.
+     * The vertical offset, in pixels, between the text label and its anchor point. The offset
+     * is applied after rotation by the _angle_ property.
      */
-    row?: FacetFieldDef;
-};
-
-/**
- * Unit spec that can have a composite mark.
- */
-export type Spec = {
-    /**
-     * An object describing the data source
-     */
-    data?: Data;
+    dy?: number;
     /**
-     * Description of this mark for commenting purpose.
+     * Default Fill Color.  This has higher precedence than config.color
+     *
+     * __Default value:__ (None)
      */
-    description?: string;
+    fill?: string;
     /**
-     * The height of a visualization.
+     * Whether the mark's color should be used as fill color instead of stroke color.
      *
-     * __Default value:__
-     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its y-channel has a
-     * [continuous scale](scale.html#continuous), the height will be the value of
-     * [`config.view.height`](spec.html#config).
-     * - For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
-     * value or unspecified, the height is [determined by the range step, paddings, and the
-     * cardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the
-     * `rangeStep` is `null`, the height will be the value of
-     * [`config.view.height`](spec.html#config).
-     * - If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.
+     * __Default value:__ `true` for all marks except `point` and `false` for `point`.
      *
-     * __Note__: For plots with [`row` and `column` channels](encoding.html#facet), this
-     * represents the height of a single view.
+     * __Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.
      *
-     * __See also:__ The documentation for [width and height](size.html) contains more examples.
+     * __Note:__ This property cannot be used in a [style config](mark.html#style-config).
      */
-    height?: number;
+    filled?: boolean;
     /**
-     * Layer or single view specifications to be layered.
+     * The fill opacity (value between [0,1]).
      *
-     * __Note__: Specifications inside `layer` cannot use `row` and `column` channels as
-     * layering facet specifications is not allowed.
+     * __Default value:__ `1`
      */
-    layer?: LayerSpec[];
+    fillOpacity?: number;
     /**
-     * Name of the visualization for later reference.
+     * The typeface to set the text in (e.g., `"Helvetica Neue"`).
      */
-    name?: string;
+    font?: string;
     /**
-     * Scale, axis, and legend resolutions for layers.
-     *
-     * Scale, axis, and legend resolutions for facets.
-     *
-     * Scale and legend resolutions for repeated charts.
-     *
-     * Scale, axis, and legend resolutions for vertically concatenated charts.
-     *
-     * Scale, axis, and legend resolutions for horizontally concatenated charts.
+     * The font size, in pixels.
      */
-    resolve?: Resolve;
+    fontSize?: number;
     /**
-     * Title for the plot.
+     * The font style (e.g., `"italic"`).
      */
-    title?: Title;
+    fontStyle?: FontStyle;
     /**
-     * An array of data transformations such as filter and new field calculation.
+     * The font weight (e.g., `"bold"`).
      */
-    transform?: Transform[];
+    fontWeight?: FontWeightUnion;
     /**
-     * The width of a visualization.
-     *
-     * __Default value:__ This will be determined by the following rules:
-     *
-     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its x-channel has a
-     * [continuous scale](scale.html#continuous), the width will be the value of
-     * [`config.view.width`](spec.html#config).
-     * - For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
-     * value or unspecified, the width is [determined by the range step, paddings, and the
-     * cardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the
-     * `rangeStep` is `null`, the width will be the value of
-     * [`config.view.width`](spec.html#config).
-     * - If no field is mapped to `x` channel, the `width` will be the value of
-     * [`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and
-     * the value of `rangeStep` for other marks.
-     *
-     * __Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this
-     * represents the width of a single view.
-     *
-     * __See also:__ The documentation for [width and height](size.html) contains more examples.
+     * A URL to load upon mouse click. If defined, the mark acts as a hyperlink.
      */
-    width?: number;
+    href?: string;
     /**
-     * A key-value mapping between encoding channels and definition of fields.
+     * The line interpolation method to use for line and area marks. One of the following:
+     * - `"linear"`: piecewise linear segments, as in a polyline.
+     * - `"linear-closed"`: close the linear segments to form a polygon.
+     * - `"step"`: alternate between horizontal and vertical segments, as in a step function.
+     * - `"step-before"`: alternate between vertical and horizontal segments, as in a step
+     * function.
+     * - `"step-after"`: alternate between horizontal and vertical segments, as in a step
+     * function.
+     * - `"basis"`: a B-spline, with control point duplication on the ends.
+     * - `"basis-open"`: an open B-spline; may not intersect the start or end.
+     * - `"basis-closed"`: a closed B-spline, as in a loop.
+     * - `"cardinal"`: a Cardinal spline, with control point duplication on the ends.
+     * - `"cardinal-open"`: an open Cardinal spline; may not intersect the start or end, but
+     * will intersect other control points.
+     * - `"cardinal-closed"`: a closed Cardinal spline, as in a loop.
+     * - `"bundle"`: equivalent to basis, except the tension parameter is used to straighten the
+     * spline.
+     * - `"monotone"`: cubic interpolation that preserves monotonicity in y.
      */
-    encoding?: Encoding;
+    interpolate?: Interpolate;
     /**
-     * A string describing the mark type (one of `"bar"`, `"circle"`, `"square"`, `"tick"`,
-     * `"line"`,
-     * * `"area"`, `"point"`, `"rule"`, `"geoshape"`, and `"text"`) or a [mark definition
-     * object](mark.html#mark-def).
+     * The maximum length of the text mark in pixels (default 0, indicating no limit). The text
+     * value will be automatically truncated if the rendered size exceeds the limit.
      */
-    mark?: AnyMark;
+    limit?: number;
     /**
-     * An object defining properties of geographic projection.
+     * The overall opacity (value between [0,1]).
      *
-     * Works with `"geoshape"` marks and `"point"` or `"line"` marks that have a channel (one or
-     * more of `"X"`, `"X2"`, `"Y"`, `"Y2"`) with type `"latitude"`, or `"longitude"`.
-     */
-    projection?: Projection;
-    /**
-     * A key-value mapping between selection names and definitions.
-     */
-    selection?: { [key: string]: SelectionDef };
-    /**
-     * An object that describes mappings between `row` and `column` channels and their field
-     * definitions.
+     * __Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or
+     * `square` marks or layered `bar` charts and `1` otherwise.
      */
-    facet?: FacetMapping;
+    opacity?: number;
     /**
-     * A specification of the view that gets faceted.
+     * The orientation of a non-stacked bar, tick, area, and line charts.
+     * The value is either horizontal (default) or vertical.
+     * - For bar, rule and tick, this determines whether the size of the bar and tick
+     * should be applied to x or y dimension.
+     * - For area, this property determines the orient property of the Vega output.
+     * - For line, this property determines the sort order of the points in the line
+     * if `config.sortLineBy` is not specified.
+     * For stacked charts, this is always determined by the orientation of the stack;
+     * therefore explicitly specified value will be ignored.
      */
-    spec?: Spec;
+    orient?: Orient;
     /**
-     * An object that describes what fields should be repeated into views that are laid out as a
-     * `row` or `column`.
+     * Polar coordinate radial offset, in pixels, of the text label from the origin determined
+     * by the `x` and `y` properties.
      */
-    repeat?: Repeat;
+    radius?: number;
     /**
-     * A list of views that should be concatenated and put into a column.
+     * The default symbol shape to use. One of: `"circle"` (default), `"square"`, `"cross"`,
+     * `"diamond"`, `"triangle-up"`, or `"triangle-down"`, or a custom SVG path.
+     *
+     * __Default value:__ `"circle"`
      */
-    vconcat?: Spec[];
+    shape?: string;
     /**
-     * A list of views that should be concatenated and put into a row.
+     * The pixel area each the point/circle/square.
+     * For example: in the case of circles, the radius is determined in part by the square root
+     * of the size value.
+     *
+     * __Default value:__ `30`
      */
-    hconcat?: Spec[];
-};
-
-/**
- * A key-value mapping between encoding channels and definition of fields.
- */
-export type Encoding = {
+    size?: number;
     /**
-     * Color of the marks – either fill or stroke color based on mark type.
-     * By default, `color` represents fill color for `"area"`, `"bar"`, `"tick"`,
-     * `"text"`, `"circle"`, and `"square"` / stroke color for `"line"` and `"point"`.
-     *
-     * __Default value:__ If undefined, the default color depends on [mark
-     * config](config.html#mark)'s `color` property.
+     * Default Stroke Color.  This has higher precedence than config.color
      *
-     * _Note:_ See the scale documentation for more information about customizing [color
-     * scheme](scale.html#scheme).
+     * __Default value:__ (None)
      */
-    color?: MarkPropDefWithCondition;
+    stroke?: string;
     /**
-     * Additional levels of detail for grouping data in aggregate views and
-     * in line and area marks without mapping data to a specific visual channel.
+     * An array of alternating stroke, space lengths for creating dashed or dotted lines.
      */
-    detail?: Detail;
+    strokeDash?: number[];
     /**
-     * A URL to load upon mouse click.
+     * The offset (in pixels) into which to begin drawing with the stroke dash array.
      */
-    href?: DefWithCondition;
+    strokeDashOffset?: number;
     /**
-     * Opacity of the marks – either can be a value or a range.
+     * The stroke opacity (value between [0,1]).
      *
-     * __Default value:__ If undefined, the default opacity depends on [mark
-     * config](config.html#mark)'s `opacity` property.
+     * __Default value:__ `1`
      */
-    opacity?: MarkPropDefWithCondition;
+    strokeOpacity?: number;
     /**
-     * Stack order for stacked marks or order of data points in line marks for connected scatter
-     * plots.
-     *
-     * __Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating
-     * additional aggregation grouping.
+     * The stroke width, in pixels.
      */
-    order?: Order;
+    strokeWidth?: number;
     /**
-     * For `point` marks the supported values are
-     * `"circle"` (default), `"square"`, `"cross"`, `"diamond"`, `"triangle-up"`,
-     * or `"triangle-down"`, or else a custom SVG path string.
-     * For `geoshape` marks it should be a field definition of the geojson data
+     * A string or array of strings indicating the name of custom styles to apply to the mark. A
+     * style is a named collection of mark property defaults defined within the [style
+     * configuration](mark.html#style-config). If style is an array, later styles will override
+     * earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within
+     * the `encoding` will override a style default.
      *
-     * __Default value:__ If undefined, the default shape depends on [mark
-     * config](config.html#point-config)'s `shape` property.
-     */
-    shape?: MarkPropDefWithCondition;
-    /**
-     * Size of the mark.
-     * - For `"point"`, `"square"` and `"circle"`, – the symbol size, or pixel area of the mark.
-     * - For `"bar"` and `"tick"` – the bar and tick's size.
-     * - For `"text"` – the text's font size.
-     * - Size is currently unsupported for `"line"`, `"area"`, and `"rect"`.
-     */
-    size?: MarkPropDefWithCondition;
-    /**
-     * Text of the `text` mark.
-     */
-    text?: TextDefWithCondition;
-    /**
-     * The tooltip text to show upon mouse hover.
+     * __Default value:__ The mark's name.  For example, a bar mark will have style `"bar"` by
+     * default.
+     * __Note:__ Any specified style will augment the default style. For example, a bar mark
+     * with `"style": "foo"` will receive from `config.style.bar` and `config.style.foo` (the
+     * specified style `"foo"` has higher precedence).
      */
-    tooltip?: TextDefWithCondition;
+    style?: Style;
     /**
-     * X coordinates of the marks, or width of horizontal `"bar"` and `"area"`.
+     * Depending on the interpolation type, sets the tension parameter (for line and area marks).
      */
-    x?: XClass;
+    tension?: number;
     /**
-     * X2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
+     * Placeholder text if the `text` channel is not specified
      */
-    x2?: X2Class;
+    text?: string;
     /**
-     * Y coordinates of the marks, or height of vertical `"bar"` and `"area"`.
+     * Polar coordinate angle, in radians, of the text label from the origin determined by the
+     * `x` and `y` properties. Values for `theta` follow the same convention of `arc` mark
+     * `startAngle` and `endAngle` properties: angles are measured in radians, with `0`
+     * indicating "north".
      */
-    y?: XClass;
+    theta?: number;
     /**
-     * Y2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
+     * The mark type.
+     * One of `"bar"`, `"circle"`, `"square"`, `"tick"`, `"line"`,
+     * `"area"`, `"point"`, `"geoshape"`, `"rule"`, and `"text"`.
      */
-    y2?: X2Class;
+    type: Mark;
 };
 
 /**
- * Unit spec that can have a composite mark.
- */
-export type LayerSpec = {
-    /**
-     * An object describing the data source
-     */
-    data?: Data;
-    /**
-     * Description of this mark for commenting purpose.
-     */
-    description?: string;
+ * A string or array of strings indicating the name of custom styles to apply to the mark. A
+ * style is a named collection of mark property defaults defined within the [style
+ * configuration](mark.html#style-config). If style is an array, later styles will override
+ * earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within
+ * the `encoding` will override a style default.
+ *
+ * __Default value:__ The mark's name.  For example, a bar mark will have style `"bar"` by
+ * default.
+ * __Note:__ Any specified style will augment the default style. For example, a bar mark
+ * with `"style": "foo"` will receive from `config.style.bar` and `config.style.foo` (the
+ * specified style `"foo"` has higher precedence).
+ *
+ * A [mark style property](config.html#style) to apply to the title text mark.
+ *
+ * __Default value:__ `"group-title"`.
+ *
+ * The field or fields for storing the computed formula value.
+ * If `from.fields` is specified, the transform will use the same names for `as`.
+ * If `from.fields` is not specified, `as` has to be a string and we put the whole object
+ * into the data under the specified name.
+ */
+export type Style = string[] | string;
+
+/**
+ * All types of primitive marks.
+ *
+ * The mark type.
+ * One of `"bar"`, `"circle"`, `"square"`, `"tick"`, `"line"`,
+ * `"area"`, `"point"`, `"geoshape"`, `"rule"`, and `"text"`.
+ */
+export type Mark =
+      "area"
+    | "bar"
+    | "line"
+    | "point"
+    | "text"
+    | "tick"
+    | "rect"
+    | "rule"
+    | "circle"
+    | "square"
+    | "geoshape";
+
+/**
+ * An object defining properties of geographic projection.
+ *
+ * Works with `"geoshape"` marks and `"point"` or `"line"` marks that have a channel (one or
+ * more of `"X"`, `"X2"`, `"Y"`, `"Y2"`) with type `"latitude"`, or `"longitude"`.
+ */
+export type Projection = {
+    /**
+     * Sets the projection’s center to the specified center, a two-element array of longitude
+     * and latitude in degrees.
+     *
+     * __Default value:__ `[0, 0]`
+     */
+    center?: number[];
+    /**
+     * Sets the projection’s clipping circle radius to the specified angle in degrees. If
+     * `null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather
+     * than small-circle clipping.
+     */
+    clipAngle?: number;
+    /**
+     * Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent
+     * bounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of
+     * the viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no
+     * viewport clipping is performed.
+     */
+    clipExtent?:  Array<number[]>;
+    coefficient?: number;
+    distance?:    number;
+    fraction?:    number;
+    lobes?:       number;
+    parallel?:    number;
+    /**
+     * Sets the threshold for the projection’s [adaptive
+     * resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This
+     * value corresponds to the [Douglas–Peucker
+     * distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
+     * If precision is not specified, returns the projection’s current resampling precision
+     * which defaults to `√0.5 ≅ 0.70710…`.
+     */
+    precision?: FluffyPrecision;
+    radius?:    number;
+    ratio?:     number;
+    /**
+     * Sets the projection’s three-axis rotation to the specified angles, which must be a two-
+     * or three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation
+     * angles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)
+     *
+     * __Default value:__ `[0, 0, 0]`
+     */
+    rotate?:  number[];
+    spacing?: number;
+    tilt?:    number;
+    /**
+     * The cartographic projection to use. This value is case-insensitive, for example
+     * `"albers"` and `"Albers"` indicate the same projection type. You can find all valid
+     * projection types [in the
+     * documentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).
+     *
+     * __Default value:__ `mercator`
+     */
+    type?: VGProjectionType;
+};
+
+/**
+ * Sets the threshold for the projection’s [adaptive
+ * resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This
+ * value corresponds to the [Douglas–Peucker
+ * distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
+ * If precision is not specified, returns the projection’s current resampling precision
+ * which defaults to `√0.5 ≅ 0.70710…`.
+ */
+export type FluffyPrecision = {
+    /**
+     * Returns the length of a String object.
+     */
+    length: number;
+    [property: string]: string;
+};
+
+export type SelectionDef = SingleSelection | MultiSelection | IntervalSelection;
+
+export type SingleSelection = {
+    /**
+     * Establish a two-way binding between a single selection and input elements
+     * (also known as dynamic query widgets). A binding takes the form of
+     * Vega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)
+     * or can be a mapping between projected field/encodings and binding definitions.
+     *
+     * See the [bind transform](bind.html) documentation for more information.
+     */
+    bind?: { [key: string]: VGBinding };
+    /**
+     * By default, all data values are considered to lie within an empty selection.
+     * When set to `none`, empty selections contain no data values.
+     */
+    empty?: Empty;
+    /**
+     * An array of encoding channels. The corresponding data field values
+     * must match for a data tuple to fall within the selection.
+     */
+    encodings?: SingleDefChannel[];
+    /**
+     * An array of field names whose values must match for a data tuple to
+     * fall within the selection.
+     */
+    fields?: string[];
+    /**
+     * When true, an invisible voronoi diagram is computed to accelerate discrete
+     * selection. The data value _nearest_ the mouse cursor is added to the selection.
+     *
+     * See the [nearest transform](nearest.html) documentation for more information.
+     */
+    nearest?: boolean;
+    /**
+     * A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or
+     * selector) that triggers the selection.
+     * For interval selections, the event stream must specify a [start and
+     * end](https://vega.github.io/vega/docs/event-streams/#between-filters).
+     */
+    on?: mixed;
+    /**
+     * With layered and multi-view displays, a strategy that determines how
+     * selections' data queries are resolved when applied in a filter transform,
+     * conditional encoding rule, or scale domain.
+     */
+    resolve?: SelectionResolution;
+    type:     StickyType;
+};
+
+export type StickyType =
+      "single";
+
+export type MultiSelection = {
+    /**
+     * By default, all data values are considered to lie within an empty selection.
+     * When set to `none`, empty selections contain no data values.
+     */
+    empty?: Empty;
+    /**
+     * An array of encoding channels. The corresponding data field values
+     * must match for a data tuple to fall within the selection.
+     */
+    encodings?: SingleDefChannel[];
+    /**
+     * An array of field names whose values must match for a data tuple to
+     * fall within the selection.
+     */
+    fields?: string[];
+    /**
+     * When true, an invisible voronoi diagram is computed to accelerate discrete
+     * selection. The data value _nearest_ the mouse cursor is added to the selection.
+     *
+     * See the [nearest transform](nearest.html) documentation for more information.
+     */
+    nearest?: boolean;
+    /**
+     * A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or
+     * selector) that triggers the selection.
+     * For interval selections, the event stream must specify a [start and
+     * end](https://vega.github.io/vega/docs/event-streams/#between-filters).
+     */
+    on?: mixed;
+    /**
+     * With layered and multi-view displays, a strategy that determines how
+     * selections' data queries are resolved when applied in a filter transform,
+     * conditional encoding rule, or scale domain.
+     */
+    resolve?: SelectionResolution;
+    /**
+     * Controls whether data values should be toggled or only ever inserted into
+     * multi selections. Can be `true`, `false` (for insertion only), or a
+     * [Vega expression](https://vega.github.io/vega/docs/expressions/).
+     *
+     * __Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,
+     * data values are toggled when a user interacts with the shift-key pressed).
+     *
+     * See the [toggle transform](toggle.html) documentation for more information.
+     */
+    toggle?: Translate;
+    type:    IndigoType;
+};
+
+export type IndigoType =
+      "multi";
+
+export type IntervalSelection = {
+    /**
+     * Establishes a two-way binding between the interval selection and the scales
+     * used within the same view. This allows a user to interactively pan and
+     * zoom the view.
+     */
+    bind?: Bind;
+    /**
+     * By default, all data values are considered to lie within an empty selection.
+     * When set to `none`, empty selections contain no data values.
+     */
+    empty?: Empty;
+    /**
+     * An array of encoding channels. The corresponding data field values
+     * must match for a data tuple to fall within the selection.
+     */
+    encodings?: SingleDefChannel[];
+    /**
+     * An array of field names whose values must match for a data tuple to
+     * fall within the selection.
+     */
+    fields?: string[];
+    /**
+     * An interval selection also adds a rectangle mark to depict the
+     * extents of the interval. The `mark` property can be used to customize the
+     * appearance of the mark.
+     */
+    mark?: BrushConfig;
+    /**
+     * A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or
+     * selector) that triggers the selection.
+     * For interval selections, the event stream must specify a [start and
+     * end](https://vega.github.io/vega/docs/event-streams/#between-filters).
+     */
+    on?: mixed;
+    /**
+     * With layered and multi-view displays, a strategy that determines how
+     * selections' data queries are resolved when applied in a filter transform,
+     * conditional encoding rule, or scale domain.
+     */
+    resolve?: SelectionResolution;
+    /**
+     * When truthy, allows a user to interactively move an interval selection
+     * back-and-forth. Can be `true`, `false` (to disable panning), or a
+     * [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)
+     * which must include a start and end event to trigger continuous panning.
+     *
+     * __Default value:__ `true`, which corresponds to
+     * `[mousedown, window:mouseup] > window:mousemove!` which corresponds to
+     * clicks and dragging within an interval selection to reposition it.
+     */
+    translate?: Translate;
+    type:       IndecentType;
+    /**
+     * When truthy, allows a user to interactively resize an interval selection.
+     * Can be `true`, `false` (to disable zooming), or a [Vega event stream
+     * definition](https://vega.github.io/vega/docs/event-streams/). Currently,
+     * only `wheel` events are supported.
+     *
+     *
+     * __Default value:__ `true`, which corresponds to `wheel!`.
+     */
+    zoom?: Translate;
+};
+
+export type IndecentType =
+      "interval";
+
+export type Title = TitleParams | string;
+
+export type TitleParams = {
+    /**
+     * The anchor position for placing the title. One of `"start"`, `"middle"`, or `"end"`. For
+     * example, with an orientation of top these anchor positions map to a left-, center-, or
+     * right-aligned title.
+     *
+     * __Default value:__ `"middle"` for [single](spec.html) and [layered](layer.html) views.
+     * `"start"` for other composite views.
+     *
+     * __Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only
+     * customizable only for [single](spec.html) and [layered](layer.html) views.  For other
+     * composite views, `anchor` is always `"start"`.
+     */
+    anchor?: Anchor;
+    /**
+     * The orthogonal offset in pixels by which to displace the title from its position along
+     * the edge of the chart.
+     */
+    offset?: number;
+    /**
+     * The orientation of the title relative to the chart. One of `"top"` (the default),
+     * `"bottom"`, `"left"`, or `"right"`.
+     */
+    orient?: TitleOrient;
+    /**
+     * A [mark style property](config.html#style) to apply to the title text mark.
+     *
+     * __Default value:__ `"group-title"`.
+     */
+    style?: Style;
+    /**
+     * The title text.
+     */
+    text: string;
+};
+
+export type Transform = FilterTransform | CalculateTransform | LookupTransform | BinTransform | TimeUnitTransform | AggregateTransform;
+
+export type FilterTransform = {
+    /**
+     * The `filter` property must be one of the predicate definitions:
+     * (1) an [expression](types.html#expression) string,
+     * where `datum` can be used to refer to the current data object;
+     * (2) one of the field predicates: [equal predicate](filter.html#equal-predicate);
+     * [range predicate](filter.html#range-predicate), [one-of
+     * predicate](filter.html#one-of-predicate);
+     * (3) a [selection predicate](filter.html#selection-predicate);
+     * or (4) a logical operand that combines (1), (2), or (3).
+     */
+    filter: LogicalOperandPredicate;
+};
+
+export type CalculateTransform = {
+    /**
+     * The field for storing the computed formula value.
+     */
+    as: string;
+    /**
+     * A [expression](types.html#expression) string. Use the variable `datum` to refer to the
+     * current data object.
+     */
+    calculate: string;
+};
+
+export type LookupTransform = {
+    /**
+     * The field or fields for storing the computed formula value.
+     * If `from.fields` is specified, the transform will use the same names for `as`.
+     * If `from.fields` is not specified, `as` has to be a string and we put the whole object
+     * into the data under the specified name.
+     */
+    as?: Style;
+    /**
+     * The default value to use if lookup fails.
+     *
+     * __Default value:__ `null`
+     */
+    default?: string;
+    /**
+     * Secondary data reference.
+     */
+    from: LookupData;
+    /**
+     * Key in primary data source.
+     */
+    lookup: string;
+};
+
+/**
+ * Secondary data reference.
+ */
+export type LookupData = {
+    /**
+     * Secondary data source to lookup in.
+     */
+    data: Data;
+    /**
+     * Fields in foreign data to lookup.
+     * If not specified, the entire object is queried.
+     */
+    fields?: string[];
+    /**
+     * Key in data to lookup.
+     */
+    key: string;
+};
+
+export type BinTransform = {
+    /**
+     * The output fields at which to write the start and end bin values.
+     */
+    as: string;
+    /**
+     * An object indicating bin properties, or simply `true` for using default bin parameters.
+     */
+    bin: Bin;
+    /**
+     * The data field to bin.
+     */
+    field: string;
+};
+
+export type TimeUnitTransform = {
+    /**
+     * The output field to write the timeUnit value.
+     */
+    as: string;
+    /**
+     * The data field to apply time unit.
+     */
+    field: string;
+    /**
+     * The timeUnit.
+     */
+    timeUnit: TimeUnit;
+};
+
+export type AggregateTransform = {
+    /**
+     * Array of objects that define fields to aggregate.
+     */
+    aggregate: AggregatedFieldDef[];
+    /**
+     * The data fields to group by. If not specified, a single group containing all data objects
+     * will be used.
+     */
+    groupby?: string[];
+};
+
+export type AggregatedFieldDef = {
+    /**
+     * The output field names to use for each aggregated field.
+     */
+    as: string;
+    /**
+     * The data field for which to compute aggregate function.
+     */
+    field: string;
+    /**
+     * The aggregation operations to apply to the fields, such as sum, average or count.
+     * See the [full list of supported aggregation
+     * operations](https://vega.github.io/vega-lite/docs/aggregate.html#ops)
+     * for more information.
+     */
+    op: AggregateOp;
+};
+
+export type TopLevelLayerSpec = {
+    /**
+     * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
+     * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
+     * Setting the `$schema` property allows automatic validation and autocomplete in editors
+     * that support JSON schema.
+     */
+    $schema?: string;
+    /**
+     * Sets how the visualization size should be determined. If a string, should be one of
+     * `"pad"`, `"fit"` or `"none"`.
+     * Object values can additionally specify parameters for content sizing and automatic
+     * resizing.
+     * `"fit"` is only supported for single and layered views that don't use `rangeStep`.
+     *
+     * __Default value__: `pad`
+     */
+    autosize?: Autosize;
+    /**
+     * CSS color property to use as the background of visualization.
+     *
+     * __Default value:__ none (transparent)
+     */
+    background?: string;
+    /**
+     * Vega-Lite configuration object.  This property can only be defined at the top-level of a
+     * specification.
+     */
+    config?: Config;
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
+    /**
+     * The height of a visualization.
+     *
+     * __Default value:__
+     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its y-channel has a
+     * [continuous scale](scale.html#continuous), the height will be the value of
+     * [`config.view.height`](spec.html#config).
+     * - For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
+     * value or unspecified, the height is [determined by the range step, paddings, and the
+     * cardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the
+     * `rangeStep` is `null`, the height will be the value of
+     * [`config.view.height`](spec.html#config).
+     * - If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.
+     *
+     * __Note__: For plots with [`row` and `column` channels](encoding.html#facet), this
+     * represents the height of a single view.
+     *
+     * __See also:__ The documentation for [width and height](size.html) contains more examples.
+     */
+    height?: number;
+    /**
+     * Layer or single view specifications to be layered.
+     *
+     * __Note__: Specifications inside `layer` cannot use `row` and `column` channels as
+     * layering facet specifications is not allowed.
+     */
+    layer: SpecElement[];
+    /**
+     * Name of the visualization for later reference.
+     */
+    name?: string;
+    /**
+     * The default visualization padding, in pixels, from the edge of the visualization canvas
+     * to the data rectangle.  If a number, specifies padding for all sides.
+     * If an object, the value should have the format `{"left": 5, "top": 5, "right": 5,
+     * "bottom": 5}` to specify padding for each side of the visualization.
+     *
+     * __Default value__: `5`
+     */
+    padding?: Padding;
+    /**
+     * Scale, axis, and legend resolutions for layers.
+     */
+    resolve?: Resolve;
+    /**
+     * Title for the plot.
+     */
+    title?: Title;
+    /**
+     * An array of data transformations such as filter and new field calculation.
+     */
+    transform?: Transform[];
+    /**
+     * The width of a visualization.
+     *
+     * __Default value:__ This will be determined by the following rules:
+     *
+     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its x-channel has a
+     * [continuous scale](scale.html#continuous), the width will be the value of
+     * [`config.view.width`](spec.html#config).
+     * - For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
+     * value or unspecified, the width is [determined by the range step, paddings, and the
+     * cardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the
+     * `rangeStep` is `null`, the width will be the value of
+     * [`config.view.width`](spec.html#config).
+     * - If no field is mapped to `x` channel, the `width` will be the value of
+     * [`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and
+     * the value of `rangeStep` for other marks.
+     *
+     * __Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this
+     * represents the width of a single view.
+     *
+     * __See also:__ The documentation for [width and height](size.html) contains more examples.
+     */
+    width?: number;
+};
+
+export type LayerSpec = {
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
     /**
      * The height of a visualization.
      *
@@ -5402,7 +6235,7 @@ export type LayerSpec = {
      * __Note__: Specifications inside `layer` cannot use `row` and `column` channels as
      * layering facet specifications is not allowed.
      */
-    layer?: LayerSpec[];
+    layer: SpecElement[];
     /**
      * Name of the visualization for later reference.
      */
@@ -5442,17 +6275,102 @@ export type LayerSpec = {
      * __See also:__ The documentation for [width and height](size.html) contains more examples.
      */
     width?: number;
+};
+
+export type SpecElement = LayerSpec | CompositeUnitSpecAlias;
+
+/**
+ * Scale, axis, and legend resolutions for layers.
+ *
+ * Defines how scales, axes, and legends from different specs should be combined. Resolve is
+ * a mapping from `scale`, `axis`, and `legend` to a mapping from channels to resolutions.
+ *
+ * Scale, axis, and legend resolutions for facets.
+ *
+ * Scale and legend resolutions for repeated charts.
+ *
+ * Scale, axis, and legend resolutions for vertically concatenated charts.
+ *
+ * Scale, axis, and legend resolutions for horizontally concatenated charts.
+ */
+export type Resolve = {
+    axis?:   AxisResolveMap;
+    legend?: LegendResolveMap;
+    scale?:  ScaleResolveMap;
+};
+
+export type AxisResolveMap = {
+    x?: ResolveMode;
+    y?: ResolveMode;
+};
+
+export type ResolveMode =
+      "independent"
+    | "shared";
+
+export type LegendResolveMap = {
+    color?:   ResolveMode;
+    opacity?: ResolveMode;
+    shape?:   ResolveMode;
+    size?:    ResolveMode;
+};
+
+export type ScaleResolveMap = {
+    color?:   ResolveMode;
+    opacity?: ResolveMode;
+    shape?:   ResolveMode;
+    size?:    ResolveMode;
+    x?:       ResolveMode;
+    y?:       ResolveMode;
+};
+
+/**
+ * Unit spec that can have a composite mark.
+ */
+export type CompositeUnitSpecAlias = {
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
     /**
      * A key-value mapping between encoding channels and definition of fields.
      */
-    encoding?: Encoding;
+    encoding: Encoding;
+    /**
+     * The height of a visualization.
+     *
+     * __Default value:__
+     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its y-channel has a
+     * [continuous scale](scale.html#continuous), the height will be the value of
+     * [`config.view.height`](spec.html#config).
+     * - For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
+     * value or unspecified, the height is [determined by the range step, paddings, and the
+     * cardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the
+     * `rangeStep` is `null`, the height will be the value of
+     * [`config.view.height`](spec.html#config).
+     * - If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.
+     *
+     * __Note__: For plots with [`row` and `column` channels](encoding.html#facet), this
+     * represents the height of a single view.
+     *
+     * __See also:__ The documentation for [width and height](size.html) contains more examples.
+     */
+    height?: number;
     /**
      * A string describing the mark type (one of `"bar"`, `"circle"`, `"square"`, `"tick"`,
      * `"line"`,
      * * `"area"`, `"point"`, `"rule"`, `"geoshape"`, and `"text"`) or a [mark definition
      * object](mark.html#mark-def).
      */
-    mark?: AnyMark;
+    mark: AnyMark;
+    /**
+     * Name of the visualization for later reference.
+     */
+    name?: string;
     /**
      * An object defining properties of geographic projection.
      *
@@ -5464,655 +6382,573 @@ export type LayerSpec = {
      * A key-value mapping between selection names and definitions.
      */
     selection?: { [key: string]: SelectionDef };
-};
-
-/**
- * A string describing the mark type (one of `"bar"`, `"circle"`, `"square"`, `"tick"`,
- * `"line"`,
- * * `"area"`, `"point"`, `"rule"`, `"geoshape"`, and `"text"`) or a [mark definition
- * object](mark.html#mark-def).
- */
-export type AnyMark = MarkDef | Mark;
-
-export type MarkDef = {
     /**
-     * The horizontal alignment of the text. One of `"left"`, `"right"`, `"center"`.
+     * Title for the plot.
      */
-    align?: HorizontalAlign;
+    title?: Title;
     /**
-     * The rotation angle of the text, in degrees.
+     * An array of data transformations such as filter and new field calculation.
      */
-    angle?: number;
+    transform?: Transform[];
     /**
-     * The vertical alignment of the text. One of `"top"`, `"middle"`, `"bottom"`.
+     * The width of a visualization.
      *
-     * __Default value:__ `"middle"`
-     */
-    baseline?: VerticalAlign;
-    /**
-     * Whether a mark be clipped to the enclosing group’s width and height.
-     */
-    clip?: boolean;
-    /**
-     * Default color.  Note that `fill` and `stroke` have higher precedence than `color` and
-     * will override `color`.
+     * __Default value:__ This will be determined by the following rules:
      *
-     * __Default value:__ <span style="color: #4682b4;">&#9632;</span> `"#4682b4"`
+     * - If a view's [`autosize`](size.html#autosize) type is `"fit"` or its x-channel has a
+     * [continuous scale](scale.html#continuous), the width will be the value of
+     * [`config.view.width`](spec.html#config).
+     * - For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric
+     * value or unspecified, the width is [determined by the range step, paddings, and the
+     * cardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the
+     * `rangeStep` is `null`, the width will be the value of
+     * [`config.view.width`](spec.html#config).
+     * - If no field is mapped to `x` channel, the `width` will be the value of
+     * [`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and
+     * the value of `rangeStep` for other marks.
      *
-     * __Note:__ This property cannot be used in a [style config](mark.html#style-config).
-     */
-    color?: string;
-    /**
-     * The mouse cursor used over the mark. Any valid [CSS cursor
-     * type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.
-     */
-    cursor?: Cursor;
-    /**
-     * The horizontal offset, in pixels, between the text label and its anchor point. The offset
-     * is applied after rotation by the _angle_ property.
+     * __Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this
+     * represents the width of a single view.
+     *
+     * __See also:__ The documentation for [width and height](size.html) contains more examples.
      */
-    dx?: number;
+    width?: number;
+};
+
+/**
+ * A key-value mapping between encoding channels and definition of fields.
+ */
+export type Encoding = {
     /**
-     * The vertical offset, in pixels, between the text label and its anchor point. The offset
-     * is applied after rotation by the _angle_ property.
+     * Color of the marks – either fill or stroke color based on mark type.
+     * By default, `color` represents fill color for `"area"`, `"bar"`, `"tick"`,
+     * `"text"`, `"circle"`, and `"square"` / stroke color for `"line"` and `"point"`.
+     *
+     * __Default value:__ If undefined, the default color depends on [mark
+     * config](config.html#mark)'s `color` property.
+     *
+     * _Note:_ See the scale documentation for more information about customizing [color
+     * scheme](scale.html#scheme).
      */
-    dy?: number;
+    color?: Color;
     /**
-     * Default Fill Color.  This has higher precedence than config.color
-     *
-     * __Default value:__ (None)
+     * Additional levels of detail for grouping data in aggregate views and
+     * in line and area marks without mapping data to a specific visual channel.
      */
-    fill?: string;
+    detail?: Detail;
     /**
-     * Whether the mark's color should be used as fill color instead of stroke color.
-     *
-     * __Default value:__ `true` for all marks except `point` and `false` for `point`.
-     *
-     * __Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.
-     *
-     * __Note:__ This property cannot be used in a [style config](mark.html#style-config).
+     * A URL to load upon mouse click.
      */
-    filled?: boolean;
+    href?: Href;
     /**
-     * The fill opacity (value between [0,1]).
+     * Opacity of the marks – either can be a value or a range.
      *
-     * __Default value:__ `1`
+     * __Default value:__ If undefined, the default opacity depends on [mark
+     * config](config.html#mark)'s `opacity` property.
      */
-    fillOpacity?: number;
+    opacity?: Color;
     /**
-     * The typeface to set the text in (e.g., `"Helvetica Neue"`).
+     * Stack order for stacked marks or order of data points in line marks for connected scatter
+     * plots.
+     *
+     * __Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating
+     * additional aggregation grouping.
      */
-    font?: string;
+    order?: Order;
     /**
-     * The font size, in pixels.
+     * For `point` marks the supported values are
+     * `"circle"` (default), `"square"`, `"cross"`, `"diamond"`, `"triangle-up"`,
+     * or `"triangle-down"`, or else a custom SVG path string.
+     * For `geoshape` marks it should be a field definition of the geojson data
+     *
+     * __Default value:__ If undefined, the default shape depends on [mark
+     * config](config.html#point-config)'s `shape` property.
      */
-    fontSize?: number;
+    shape?: Color;
     /**
-     * The font style (e.g., `"italic"`).
+     * Size of the mark.
+     * - For `"point"`, `"square"` and `"circle"`, – the symbol size, or pixel area of the mark.
+     * - For `"bar"` and `"tick"` – the bar and tick's size.
+     * - For `"text"` – the text's font size.
+     * - Size is currently unsupported for `"line"`, `"area"`, and `"rect"`.
      */
-    fontStyle?: FontStyle;
+    size?: Color;
     /**
-     * The font weight (e.g., `"bold"`).
+     * Text of the `text` mark.
      */
-    fontWeight?: FontWeightUnion;
+    text?: Text;
     /**
-     * A URL to load upon mouse click. If defined, the mark acts as a hyperlink.
+     * The tooltip text to show upon mouse hover.
      */
-    href?: string;
+    tooltip?: Text;
     /**
-     * The line interpolation method to use for line and area marks. One of the following:
-     * - `"linear"`: piecewise linear segments, as in a polyline.
-     * - `"linear-closed"`: close the linear segments to form a polygon.
-     * - `"step"`: alternate between horizontal and vertical segments, as in a step function.
-     * - `"step-before"`: alternate between vertical and horizontal segments, as in a step
-     * function.
-     * - `"step-after"`: alternate between horizontal and vertical segments, as in a step
-     * function.
-     * - `"basis"`: a B-spline, with control point duplication on the ends.
-     * - `"basis-open"`: an open B-spline; may not intersect the start or end.
-     * - `"basis-closed"`: a closed B-spline, as in a loop.
-     * - `"cardinal"`: a Cardinal spline, with control point duplication on the ends.
-     * - `"cardinal-open"`: an open Cardinal spline; may not intersect the start or end, but
-     * will intersect other control points.
-     * - `"cardinal-closed"`: a closed Cardinal spline, as in a loop.
-     * - `"bundle"`: equivalent to basis, except the tension parameter is used to straighten the
-     * spline.
-     * - `"monotone"`: cubic interpolation that preserves monotonicity in y.
+     * X coordinates of the marks, or width of horizontal `"bar"` and `"area"`.
      */
-    interpolate?: Interpolate;
+    x?: X;
     /**
-     * The maximum length of the text mark in pixels (default 0, indicating no limit). The text
-     * value will be automatically truncated if the rendered size exceeds the limit.
+     * X2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
      */
-    limit?: number;
+    x2?: X2;
     /**
-     * The overall opacity (value between [0,1]).
-     *
-     * __Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or
-     * `square` marks or layered `bar` charts and `1` otherwise.
+     * Y coordinates of the marks, or height of vertical `"bar"` and `"area"`.
      */
-    opacity?: number;
+    y?: X;
     /**
-     * The orientation of a non-stacked bar, tick, area, and line charts.
-     * The value is either horizontal (default) or vertical.
-     * - For bar, rule and tick, this determines whether the size of the bar and tick
-     * should be applied to x or y dimension.
-     * - For area, this property determines the orient property of the Vega output.
-     * - For line, this property determines the sort order of the points in the line
-     * if `config.sortLineBy` is not specified.
-     * For stacked charts, this is always determined by the orientation of the stack;
-     * therefore explicitly specified value will be ignored.
+     * Y2 coordinates for ranged  `"area"`, `"bar"`, `"rect"`, and  `"rule"`.
      */
-    orient?: Orient;
+    y2?: X2;
+};
+
+export type TopLevelFacetSpec = {
     /**
-     * Polar coordinate radial offset, in pixels, of the text label from the origin determined
-     * by the `x` and `y` properties.
+     * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
+     * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
+     * Setting the `$schema` property allows automatic validation and autocomplete in editors
+     * that support JSON schema.
      */
-    radius?: number;
+    $schema?: string;
     /**
-     * The default symbol shape to use. One of: `"circle"` (default), `"square"`, `"cross"`,
-     * `"diamond"`, `"triangle-up"`, or `"triangle-down"`, or a custom SVG path.
+     * Sets how the visualization size should be determined. If a string, should be one of
+     * `"pad"`, `"fit"` or `"none"`.
+     * Object values can additionally specify parameters for content sizing and automatic
+     * resizing.
+     * `"fit"` is only supported for single and layered views that don't use `rangeStep`.
      *
-     * __Default value:__ `"circle"`
+     * __Default value__: `pad`
      */
-    shape?: string;
+    autosize?: Autosize;
     /**
-     * The pixel area each the point/circle/square.
-     * For example: in the case of circles, the radius is determined in part by the square root
-     * of the size value.
+     * CSS color property to use as the background of visualization.
      *
-     * __Default value:__ `30`
+     * __Default value:__ none (transparent)
      */
-    size?: number;
+    background?: string;
     /**
-     * Default Stroke Color.  This has higher precedence than config.color
-     *
-     * __Default value:__ (None)
+     * Vega-Lite configuration object.  This property can only be defined at the top-level of a
+     * specification.
      */
-    stroke?: string;
+    config?: Config;
     /**
-     * An array of alternating stroke, space lengths for creating dashed or dotted lines.
+     * An object describing the data source
      */
-    strokeDash?: number[];
+    data?: Data;
     /**
-     * The offset (in pixels) into which to begin drawing with the stroke dash array.
+     * Description of this mark for commenting purpose.
      */
-    strokeDashOffset?: number;
+    description?: string;
     /**
-     * The stroke opacity (value between [0,1]).
-     *
-     * __Default value:__ `1`
+     * An object that describes mappings between `row` and `column` channels and their field
+     * definitions.
      */
-    strokeOpacity?: number;
+    facet: FacetMapping;
     /**
-     * The stroke width, in pixels.
+     * Name of the visualization for later reference.
      */
-    strokeWidth?: number;
+    name?: string;
     /**
-     * A string or array of strings indicating the name of custom styles to apply to the mark. A
-     * style is a named collection of mark property defaults defined within the [style
-     * configuration](mark.html#style-config). If style is an array, later styles will override
-     * earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within
-     * the `encoding` will override a style default.
+     * The default visualization padding, in pixels, from the edge of the visualization canvas
+     * to the data rectangle.  If a number, specifies padding for all sides.
+     * If an object, the value should have the format `{"left": 5, "top": 5, "right": 5,
+     * "bottom": 5}` to specify padding for each side of the visualization.
      *
-     * __Default value:__ The mark's name.  For example, a bar mark will have style `"bar"` by
-     * default.
-     * __Note:__ Any specified style will augment the default style. For example, a bar mark
-     * with `"style": "foo"` will receive from `config.style.bar` and `config.style.foo` (the
-     * specified style `"foo"` has higher precedence).
+     * __Default value__: `5`
      */
-    style?: Style;
+    padding?: Padding;
     /**
-     * Depending on the interpolation type, sets the tension parameter (for line and area marks).
+     * Scale, axis, and legend resolutions for facets.
      */
-    tension?: number;
+    resolve?: Resolve;
     /**
-     * Placeholder text if the `text` channel is not specified
+     * A specification of the view that gets faceted.
      */
-    text?: string;
+    spec: SpecElement;
     /**
-     * Polar coordinate angle, in radians, of the text label from the origin determined by the
-     * `x` and `y` properties. Values for `theta` follow the same convention of `arc` mark
-     * `startAngle` and `endAngle` properties: angles are measured in radians, with `0`
-     * indicating "north".
+     * Title for the plot.
      */
-    theta?: number;
+    title?: Title;
     /**
-     * The mark type.
-     * One of `"bar"`, `"circle"`, `"square"`, `"tick"`, `"line"`,
-     * `"area"`, `"point"`, `"geoshape"`, `"rule"`, and `"text"`.
+     * An array of data transformations such as filter and new field calculation.
      */
-    type: Mark;
+    transform?: Transform[];
 };
 
 /**
- * A string or array of strings indicating the name of custom styles to apply to the mark. A
- * style is a named collection of mark property defaults defined within the [style
- * configuration](mark.html#style-config). If style is an array, later styles will override
- * earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within
- * the `encoding` will override a style default.
- *
- * __Default value:__ The mark's name.  For example, a bar mark will have style `"bar"` by
- * default.
- * __Note:__ Any specified style will augment the default style. For example, a bar mark
- * with `"style": "foo"` will receive from `config.style.bar` and `config.style.foo` (the
- * specified style `"foo"` has higher precedence).
- *
- * A [mark style property](config.html#style) to apply to the title text mark.
- *
- * __Default value:__ `"group-title"`.
- */
-export type Style = string[] | string;
-
-/**
- * All types of primitive marks.
- *
- * The mark type.
- * One of `"bar"`, `"circle"`, `"square"`, `"tick"`, `"line"`,
- * `"area"`, `"point"`, `"geoshape"`, `"rule"`, and `"text"`.
+ * An object that describes mappings between `row` and `column` channels and their field
+ * definitions.
  */
-export type Mark =
-      "area"
-    | "bar"
-    | "line"
-    | "point"
-    | "text"
-    | "tick"
-    | "rect"
-    | "rule"
-    | "circle"
-    | "square"
-    | "geoshape";
+export type FacetMapping = {
+    /**
+     * Horizontal facets for trellis plots.
+     */
+    column?: FacetFieldDef;
+    /**
+     * Vertical facets for trellis plots.
+     */
+    row?: FacetFieldDef;
+};
 
-/**
- * An object defining properties of geographic projection.
- *
- * Works with `"geoshape"` marks and `"point"` or `"line"` marks that have a channel (one or
- * more of `"X"`, `"X2"`, `"Y"`, `"Y2"`) with type `"latitude"`, or `"longitude"`.
- */
-export type Projection = {
+export type TopLevelRepeatSpec = {
     /**
-     * Sets the projection’s center to the specified center, a two-element array of longitude
-     * and latitude in degrees.
+     * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
+     * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
+     * Setting the `$schema` property allows automatic validation and autocomplete in editors
+     * that support JSON schema.
+     */
+    $schema?: string;
+    /**
+     * Sets how the visualization size should be determined. If a string, should be one of
+     * `"pad"`, `"fit"` or `"none"`.
+     * Object values can additionally specify parameters for content sizing and automatic
+     * resizing.
+     * `"fit"` is only supported for single and layered views that don't use `rangeStep`.
      *
-     * __Default value:__ `[0, 0]`
+     * __Default value__: `pad`
+     */
+    autosize?: Autosize;
+    /**
+     * CSS color property to use as the background of visualization.
+     *
+     * __Default value:__ none (transparent)
+     */
+    background?: string;
+    /**
+     * Vega-Lite configuration object.  This property can only be defined at the top-level of a
+     * specification.
+     */
+    config?: Config;
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
+    /**
+     * Name of the visualization for later reference.
      */
-    center?: number[];
+    name?: string;
     /**
-     * Sets the projection’s clipping circle radius to the specified angle in degrees. If
-     * `null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather
-     * than small-circle clipping.
+     * The default visualization padding, in pixels, from the edge of the visualization canvas
+     * to the data rectangle.  If a number, specifies padding for all sides.
+     * If an object, the value should have the format `{"left": 5, "top": 5, "right": 5,
+     * "bottom": 5}` to specify padding for each side of the visualization.
+     *
+     * __Default value__: `5`
      */
-    clipAngle?: number;
+    padding?: Padding;
     /**
-     * Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent
-     * bounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of
-     * the viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no
-     * viewport clipping is performed.
+     * An object that describes what fields should be repeated into views that are laid out as a
+     * `row` or `column`.
      */
-    clipExtent?:  Array<number[]>;
-    coefficient?: number;
-    distance?:    number;
-    fraction?:    number;
-    lobes?:       number;
-    parallel?:    number;
+    repeat: Repeat;
     /**
-     * Sets the threshold for the projection’s [adaptive
-     * resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This
-     * value corresponds to the [Douglas–Peucker
-     * distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
-     * If precision is not specified, returns the projection’s current resampling precision
-     * which defaults to `√0.5 ≅ 0.70710…`.
+     * Scale and legend resolutions for repeated charts.
      */
-    precision?: FluffyPrecision;
-    radius?:    number;
-    ratio?:     number;
+    resolve?: Resolve;
+    spec:     Spec;
     /**
-     * Sets the projection’s three-axis rotation to the specified angles, which must be a two-
-     * or three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation
-     * angles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)
-     *
-     * __Default value:__ `[0, 0, 0]`
+     * Title for the plot.
      */
-    rotate?:  number[];
-    spacing?: number;
-    tilt?:    number;
+    title?: Title;
     /**
-     * The cartographic projection to use. This value is case-insensitive, for example
-     * `"albers"` and `"Albers"` indicate the same projection type. You can find all valid
-     * projection types [in the
-     * documentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).
-     *
-     * __Default value:__ `mercator`
+     * An array of data transformations such as filter and new field calculation.
      */
-    type?: VGProjectionType;
+    transform?: Transform[];
 };
 
 /**
- * Sets the threshold for the projection’s [adaptive
- * resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This
- * value corresponds to the [Douglas–Peucker
- * distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
- * If precision is not specified, returns the projection’s current resampling precision
- * which defaults to `√0.5 ≅ 0.70710…`.
+ * An object that describes what fields should be repeated into views that are laid out as a
+ * `row` or `column`.
  */
-export type FluffyPrecision = {
+export type Repeat = {
     /**
-     * Returns the length of a String object.
+     * Horizontal repeated views.
      */
-    length: number;
-    [property: string]: string;
-};
-
-/**
- * Scale, axis, and legend resolutions for layers.
- *
- * Defines how scales, axes, and legends from different specs should be combined. Resolve is
- * a mapping from `scale`, `axis`, and `legend` to a mapping from channels to resolutions.
- *
- * Scale, axis, and legend resolutions for facets.
- *
- * Scale and legend resolutions for repeated charts.
- *
- * Scale, axis, and legend resolutions for vertically concatenated charts.
- *
- * Scale, axis, and legend resolutions for horizontally concatenated charts.
- */
-export type Resolve = {
-    axis?:   AxisResolveMap;
-    legend?: LegendResolveMap;
-    scale?:  ScaleResolveMap;
-};
-
-export type AxisResolveMap = {
-    x?: ResolveMode;
-    y?: ResolveMode;
-};
-
-export type ResolveMode =
-      "independent"
-    | "shared";
-
-export type LegendResolveMap = {
-    color?:   ResolveMode;
-    opacity?: ResolveMode;
-    shape?:   ResolveMode;
-    size?:    ResolveMode;
+    column?: string[];
+    /**
+     * Vertical repeated views.
+     */
+    row?: string[];
 };
 
-export type ScaleResolveMap = {
-    color?:   ResolveMode;
-    opacity?: ResolveMode;
-    shape?:   ResolveMode;
-    size?:    ResolveMode;
-    x?:       ResolveMode;
-    y?:       ResolveMode;
+export type HConcatSpec = {
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
+    /**
+     * A list of views that should be concatenated and put into a row.
+     */
+    hconcat: Spec[];
+    /**
+     * Name of the visualization for later reference.
+     */
+    name?: string;
+    /**
+     * Scale, axis, and legend resolutions for horizontally concatenated charts.
+     */
+    resolve?: Resolve;
+    /**
+     * Title for the plot.
+     */
+    title?: Title;
+    /**
+     * An array of data transformations such as filter and new field calculation.
+     */
+    transform?: Transform[];
 };
 
-export type SelectionDef = {
+export type VConcatSpec = {
     /**
-     * Establish a two-way binding between a single selection and input elements
-     * (also known as dynamic query widgets). A binding takes the form of
-     * Vega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)
-     * or can be a mapping between projected field/encodings and binding definitions.
-     *
-     * See the [bind transform](bind.html) documentation for more information.
-     *
-     * Establishes a two-way binding between the interval selection and the scales
-     * used within the same view. This allows a user to interactively pan and
-     * zoom the view.
+     * An object describing the data source
      */
-    bind?: BindUnion;
+    data?: Data;
     /**
-     * By default, all data values are considered to lie within an empty selection.
-     * When set to `none`, empty selections contain no data values.
+     * Description of this mark for commenting purpose.
      */
-    empty?: Empty;
+    description?: string;
     /**
-     * An array of encoding channels. The corresponding data field values
-     * must match for a data tuple to fall within the selection.
+     * Name of the visualization for later reference.
      */
-    encodings?: SingleDefChannel[];
+    name?: string;
     /**
-     * An array of field names whose values must match for a data tuple to
-     * fall within the selection.
+     * Scale, axis, and legend resolutions for vertically concatenated charts.
      */
-    fields?: string[];
+    resolve?: Resolve;
     /**
-     * When true, an invisible voronoi diagram is computed to accelerate discrete
-     * selection. The data value _nearest_ the mouse cursor is added to the selection.
-     *
-     * See the [nearest transform](nearest.html) documentation for more information.
+     * Title for the plot.
      */
-    nearest?: boolean;
+    title?: Title;
     /**
-     * A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or
-     * selector) that triggers the selection.
-     * For interval selections, the event stream must specify a [start and
-     * end](https://vega.github.io/vega/docs/event-streams/#between-filters).
+     * An array of data transformations such as filter and new field calculation.
      */
-    on?: mixed;
+    transform?: Transform[];
     /**
-     * With layered and multi-view displays, a strategy that determines how
-     * selections' data queries are resolved when applied in a filter transform,
-     * conditional encoding rule, or scale domain.
+     * A list of views that should be concatenated and put into a column.
      */
-    resolve?: SelectionResolution;
-    type:     SelectionDefType;
+    vconcat: Spec[];
+};
+
+export type RepeatSpec = {
     /**
-     * Controls whether data values should be toggled or only ever inserted into
-     * multi selections. Can be `true`, `false` (for insertion only), or a
-     * [Vega expression](https://vega.github.io/vega/docs/expressions/).
-     *
-     * __Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,
-     * data values are toggled when a user interacts with the shift-key pressed).
-     *
-     * See the [toggle transform](toggle.html) documentation for more information.
+     * An object describing the data source
      */
-    toggle?: Translate;
+    data?: Data;
     /**
-     * An interval selection also adds a rectangle mark to depict the
-     * extents of the interval. The `mark` property can be used to customize the
-     * appearance of the mark.
+     * Description of this mark for commenting purpose.
      */
-    mark?: BrushConfig;
+    description?: string;
     /**
-     * When truthy, allows a user to interactively move an interval selection
-     * back-and-forth. Can be `true`, `false` (to disable panning), or a
-     * [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)
-     * which must include a start and end event to trigger continuous panning.
-     *
-     * __Default value:__ `true`, which corresponds to
-     * `[mousedown, window:mouseup] > window:mousemove!` which corresponds to
-     * clicks and dragging within an interval selection to reposition it.
+     * Name of the visualization for later reference.
      */
-    translate?: Translate;
+    name?: string;
     /**
-     * When truthy, allows a user to interactively resize an interval selection.
-     * Can be `true`, `false` (to disable zooming), or a [Vega event stream
-     * definition](https://vega.github.io/vega/docs/event-streams/). Currently,
-     * only `wheel` events are supported.
-     *
-     *
-     * __Default value:__ `true`, which corresponds to `wheel!`.
+     * An object that describes what fields should be repeated into views that are laid out as a
+     * `row` or `column`.
+     */
+    repeat: Repeat;
+    /**
+     * Scale and legend resolutions for repeated charts.
+     */
+    resolve?: Resolve;
+    spec:     Spec;
+    /**
+     * Title for the plot.
+     */
+    title?: Title;
+    /**
+     * An array of data transformations such as filter and new field calculation.
+     */
+    transform?: Transform[];
+};
+
+export type Spec = CompositeUnitSpecAlias | LayerSpec | FacetSpec | RepeatSpec | VConcatSpec | HConcatSpec;
+
+export type FacetSpec = {
+    /**
+     * An object describing the data source
+     */
+    data?: Data;
+    /**
+     * Description of this mark for commenting purpose.
+     */
+    description?: string;
+    /**
+     * An object that describes mappings between `row` and `column` channels and their field
+     * definitions.
      */
-    zoom?: Translate;
-};
-
-export type BindUnion = BindEnum | { [key: string]: VGBinding };
-
-export type SelectionDefType =
-      "single"
-    | "multi"
-    | "interval";
-
-export type Title = TitleParams | string;
-
-export type TitleParams = {
+    facet: FacetMapping;
     /**
-     * The anchor position for placing the title. One of `"start"`, `"middle"`, or `"end"`. For
-     * example, with an orientation of top these anchor positions map to a left-, center-, or
-     * right-aligned title.
-     *
-     * __Default value:__ `"middle"` for [single](spec.html) and [layered](layer.html) views.
-     * `"start"` for other composite views.
-     *
-     * __Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only
-     * customizable only for [single](spec.html) and [layered](layer.html) views.  For other
-     * composite views, `anchor` is always `"start"`.
+     * Name of the visualization for later reference.
      */
-    anchor?: Anchor;
+    name?: string;
     /**
-     * The orthogonal offset in pixels by which to displace the title from its position along
-     * the edge of the chart.
+     * Scale, axis, and legend resolutions for facets.
      */
-    offset?: number;
+    resolve?: Resolve;
     /**
-     * The orientation of the title relative to the chart. One of `"top"` (the default),
-     * `"bottom"`, `"left"`, or `"right"`.
+     * A specification of the view that gets faceted.
      */
-    orient?: TitleOrient;
+    spec: SpecElement;
     /**
-     * A [mark style property](config.html#style) to apply to the title text mark.
-     *
-     * __Default value:__ `"group-title"`.
+     * Title for the plot.
      */
-    style?: Style;
+    title?: Title;
     /**
-     * The title text.
+     * An array of data transformations such as filter and new field calculation.
      */
-    text: string;
+    transform?: Transform[];
 };
 
-export type Transform = {
+export type TopLevelVConcatSpec = {
     /**
-     * The `filter` property must be one of the predicate definitions:
-     * (1) an [expression](types.html#expression) string,
-     * where `datum` can be used to refer to the current data object;
-     * (2) one of the field predicates: [equal predicate](filter.html#equal-predicate);
-     * [range predicate](filter.html#range-predicate), [one-of
-     * predicate](filter.html#one-of-predicate);
-     * (3) a [selection predicate](filter.html#selection-predicate);
-     * or (4) a logical operand that combines (1), (2), or (3).
+     * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
+     * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
+     * Setting the `$schema` property allows automatic validation and autocomplete in editors
+     * that support JSON schema.
      */
-    filter?: LogicalOperandPredicate;
+    $schema?: string;
     /**
-     * The field for storing the computed formula value.
-     *
-     * The field or fields for storing the computed formula value.
-     * If `from.fields` is specified, the transform will use the same names for `as`.
-     * If `from.fields` is not specified, `as` has to be a string and we put the whole object
-     * into the data under the specified name.
-     *
-     * The output fields at which to write the start and end bin values.
+     * Sets how the visualization size should be determined. If a string, should be one of
+     * `"pad"`, `"fit"` or `"none"`.
+     * Object values can additionally specify parameters for content sizing and automatic
+     * resizing.
+     * `"fit"` is only supported for single and layered views that don't use `rangeStep`.
      *
-     * The output field to write the timeUnit value.
+     * __Default value__: `pad`
      */
-    as?: Style;
+    autosize?: Autosize;
     /**
-     * A [expression](types.html#expression) string. Use the variable `datum` to refer to the
-     * current data object.
+     * CSS color property to use as the background of visualization.
+     *
+     * __Default value:__ none (transparent)
      */
-    calculate?: string;
+    background?: string;
     /**
-     * The default value to use if lookup fails.
-     *
-     * __Default value:__ `null`
+     * Vega-Lite configuration object.  This property can only be defined at the top-level of a
+     * specification.
      */
-    default?: string;
+    config?: Config;
     /**
-     * Secondary data reference.
+     * An object describing the data source
      */
-    from?: LookupData;
+    data?: Data;
     /**
-     * Key in primary data source.
+     * Description of this mark for commenting purpose.
      */
-    lookup?: string;
+    description?: string;
     /**
-     * An object indicating bin properties, or simply `true` for using default bin parameters.
+     * Name of the visualization for later reference.
      */
-    bin?: Bin;
+    name?: string;
     /**
-     * The data field to bin.
+     * The default visualization padding, in pixels, from the edge of the visualization canvas
+     * to the data rectangle.  If a number, specifies padding for all sides.
+     * If an object, the value should have the format `{"left": 5, "top": 5, "right": 5,
+     * "bottom": 5}` to specify padding for each side of the visualization.
      *
-     * The data field to apply time unit.
+     * __Default value__: `5`
      */
-    field?: string;
+    padding?: Padding;
     /**
-     * The timeUnit.
+     * Scale, axis, and legend resolutions for vertically concatenated charts.
      */
-    timeUnit?: TimeUnit;
+    resolve?: Resolve;
     /**
-     * Array of objects that define fields to aggregate.
+     * Title for the plot.
+     */
+    title?: Title;
+    /**
+     * An array of data transformations such as filter and new field calculation.
      */
-    aggregate?: AggregatedFieldDef[];
+    transform?: Transform[];
     /**
-     * The data fields to group by. If not specified, a single group containing all data objects
-     * will be used.
+     * A list of views that should be concatenated and put into a column.
      */
-    groupby?: string[];
+    vconcat: Spec[];
 };
 
-export type AggregatedFieldDef = {
+export type TopLevelHConcatSpec = {
     /**
-     * The output field names to use for each aggregated field.
+     * URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you
+     * have a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.
+     * Setting the `$schema` property allows automatic validation and autocomplete in editors
+     * that support JSON schema.
      */
-    as: string;
+    $schema?: string;
     /**
-     * The data field for which to compute aggregate function.
+     * Sets how the visualization size should be determined. If a string, should be one of
+     * `"pad"`, `"fit"` or `"none"`.
+     * Object values can additionally specify parameters for content sizing and automatic
+     * resizing.
+     * `"fit"` is only supported for single and layered views that don't use `rangeStep`.
+     *
+     * __Default value__: `pad`
      */
-    field: string;
+    autosize?: Autosize;
     /**
-     * The aggregation operations to apply to the fields, such as sum, average or count.
-     * See the [full list of supported aggregation
-     * operations](https://vega.github.io/vega-lite/docs/aggregate.html#ops)
-     * for more information.
+     * CSS color property to use as the background of visualization.
+     *
+     * __Default value:__ none (transparent)
      */
-    op: AggregateOp;
-};
-
-/**
- * Secondary data reference.
- */
-export type LookupData = {
+    background?: string;
     /**
-     * Secondary data source to lookup in.
+     * Vega-Lite configuration object.  This property can only be defined at the top-level of a
+     * specification.
      */
-    data: Data;
+    config?: Config;
     /**
-     * Fields in foreign data to lookup.
-     * If not specified, the entire object is queried.
+     * An object describing the data source
      */
-    fields?: string[];
+    data?: Data;
     /**
-     * Key in data to lookup.
+     * Description of this mark for commenting purpose.
      */
-    key: string;
-};
-
-/**
- * An object that describes what fields should be repeated into views that are laid out as a
- * `row` or `column`.
- */
-export type Repeat = {
+    description?: string;
     /**
-     * Horizontal repeated views.
+     * A list of views that should be concatenated and put into a row.
      */
-    column?: string[];
+    hconcat: Spec[];
     /**
-     * Vertical repeated views.
+     * Name of the visualization for later reference.
      */
-    row?: string[];
+    name?: string;
+    /**
+     * The default visualization padding, in pixels, from the edge of the visualization canvas
+     * to the data rectangle.  If a number, specifies padding for all sides.
+     * If an object, the value should have the format `{"left": 5, "top": 5, "right": 5,
+     * "bottom": 5}` to specify padding for each side of the visualization.
+     *
+     * __Default value__: `5`
+     */
+    padding?: Padding;
+    /**
+     * Scale, axis, and legend resolutions for horizontally concatenated charts.
+     */
+    resolve?: Resolve;
+    /**
+     * Title for the plot.
+     */
+    title?: Title;
+    /**
+     * An array of data transformations such as filter and new field calculation.
+     */
+    transform?: Transform[];
 };
 
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json: string): TopLevel {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("TopLevelFacetedUnitSpec"), r("TopLevelLayerSpec"), r("TopLevelFacetSpec"), r("TopLevelRepeatSpec"), r("TopLevelVConcatSpec"), r("TopLevelHConcatSpec")));
 }
 
 function topLevelToJson(value: TopLevel): string {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("TopLevelFacetedUnitSpec"), r("TopLevelLayerSpec"), r("TopLevelFacetSpec"), r("TopLevelRepeatSpec"), r("TopLevelVConcatSpec"), r("TopLevelHConcatSpec"))), null, 2);
 }
 
 function invalidValue(typ: any, val: any, key: any, parent: any = '') {
@@ -6269,30 +7105,23 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
+    "TopLevelFacetedUnitSpec": o([
         { json: "$schema", js: "$schema", typ: u(undefined, "") },
         { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
         { json: "background", js: "background", typ: u(undefined, "") },
         { json: "config", js: "config", typ: u(undefined, r("Config")) },
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
         { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("EncodingWithFacet")) },
+        { json: "encoding", js: "encoding", typ: r("EncodingWithFacet") },
         { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
+        { json: "mark", js: "mark", typ: u(r("MarkDef"), r("Mark")) },
         { json: "name", js: "name", typ: u(undefined, "") },
         { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
         { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
+        { json: "selection", js: "selection", typ: u(undefined, m(u(r("SingleSelection"), r("MultiSelection"), r("IntervalSelection")))) },
         { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
         { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "facet", js: "facet", typ: u(undefined, r("FacetMapping")) },
-        { json: "spec", js: "spec", typ: u(undefined, r("Spec")) },
-        { json: "repeat", js: "repeat", typ: u(undefined, r("Repeat")) },
-        { json: "vconcat", js: "vconcat", typ: u(undefined, a(r("Spec"))) },
-        { json: "hconcat", js: "hconcat", typ: u(undefined, a(r("Spec"))) },
     ], false),
     "AutoSizeParams": o([
         { json: "contains", js: "contains", typ: u(undefined, r("Contains")) },
@@ -6551,23 +7380,20 @@ const typeMap: any = {
         { json: "length", js: "length", typ: 3.14 },
     ], ""),
     "RangeConfig": o([
-        { json: "category", js: "category", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "diverging", js: "diverging", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "heatmap", js: "heatmap", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "ordinal", js: "ordinal", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "ramp", js: "ramp", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
+        { json: "category", js: "category", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "diverging", js: "diverging", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "heatmap", js: "heatmap", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "ordinal", js: "ordinal", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "ramp", js: "ramp", typ: u(undefined, u(a(""), r("VGScheme"))) },
         { json: "symbol", js: "symbol", typ: u(undefined, a("")) },
-    ], u(a(u(3.14, "")), r("RangeConfigValueVGScheme"))),
-    "CategoryVGScheme": o([
+    ], u(a(u(3.14, "")), r("VGScheme"), r("RangeConfigValueClass"))),
+    "VGScheme": o([
         { json: "count", js: "count", typ: u(undefined, 3.14) },
         { json: "extent", js: "extent", typ: u(undefined, a(3.14)) },
         { json: "scheme", js: "scheme", typ: "" },
     ], false),
-    "RangeConfigValueVGScheme": o([
-        { json: "count", js: "count", typ: u(undefined, 3.14) },
-        { json: "extent", js: "extent", typ: u(undefined, a(3.14)) },
-        { json: "scheme", js: "scheme", typ: u(undefined, "") },
-        { json: "step", js: "step", typ: u(undefined, 3.14) },
+    "RangeConfigValueClass": o([
+        { json: "step", js: "step", typ: 3.14 },
     ], false),
     "ScaleConfig": o([
         { json: "bandPaddingInner", js: "bandPaddingInner", typ: u(undefined, 3.14) },
@@ -6596,7 +7422,7 @@ const typeMap: any = {
         { json: "single", js: "single", typ: u(undefined, r("SingleSelectionConfig")) },
     ], false),
     "IntervalSelectionConfig": o([
-        { json: "bind", js: "bind", typ: u(undefined, r("BindEnum")) },
+        { json: "bind", js: "bind", typ: u(undefined, r("Bind")) },
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
@@ -6625,7 +7451,7 @@ const typeMap: any = {
         { json: "toggle", js: "toggle", typ: u(undefined, u(true, "")) },
     ], false),
     "SingleSelectionConfig": o([
-        { json: "bind", js: "bind", typ: u(undefined, m(r("VGBinding"))) },
+        { json: "bind", js: "bind", typ: u(undefined, m(u(r("VGCheckboxBinding"), r("VGRadioBinding"), r("VGSelectBinding"), r("VGRangeBinding"), r("VGGenericBinding")))) },
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
@@ -6633,14 +7459,31 @@ const typeMap: any = {
         { json: "on", js: "on", typ: u(undefined, "any") },
         { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
     ], false),
-    "VGBinding": o([
+    "VGCheckboxBinding": o([
         { json: "element", js: "element", typ: u(undefined, "") },
-        { json: "input", js: "input", typ: "" },
-        { json: "options", js: "options", typ: u(undefined, a("")) },
+        { json: "input", js: "input", typ: r("PurpleInput") },
+    ], false),
+    "VGRadioBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("FluffyInput") },
+        { json: "options", js: "options", typ: a("") },
+    ], false),
+    "VGSelectBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("TentacledInput") },
+        { json: "options", js: "options", typ: a("") },
+    ], false),
+    "VGRangeBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("StickyInput") },
         { json: "max", js: "max", typ: u(undefined, 3.14) },
         { json: "min", js: "min", typ: u(undefined, 3.14) },
         { json: "step", js: "step", typ: u(undefined, 3.14) },
     ], false),
+    "VGGenericBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: "" },
+    ], false),
     "VGMarkConfig": o([
         { json: "align", js: "align", typ: u(undefined, r("HorizontalAlign")) },
         { json: "angle", js: "angle", typ: u(undefined, 3.14) },
@@ -6762,47 +7605,60 @@ const typeMap: any = {
         { json: "strokeWidth", js: "strokeWidth", typ: u(undefined, 3.14) },
         { json: "width", js: "width", typ: u(undefined, 3.14) },
     ], false),
-    "Data": o([
-        { json: "format", js: "format", typ: u(undefined, r("DataFormat")) },
-        { json: "url", js: "url", typ: u(undefined, "") },
-        { json: "values", js: "values", typ: u(undefined, u(a(u(true, 3.14, m("any"), "")), m("any"), "")) },
-        { json: "name", js: "name", typ: u(undefined, "") },
+    "URLData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "url", js: "url", typ: "" },
+    ], false),
+    "CSVDataFormat": o([
+        { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
+        { json: "type", js: "type", typ: u(undefined, r("PurpleType")) },
     ], false),
-    "DataFormat": o([
+    "JSONDataFormat": o([
         { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
-        { json: "type", js: "type", typ: u(undefined, r("DataFormatType")) },
         { json: "property", js: "property", typ: u(undefined, "") },
+        { json: "type", js: "type", typ: u(undefined, r("FluffyType")) },
+    ], false),
+    "TopoDataFormat": o([
         { json: "feature", js: "feature", typ: u(undefined, "") },
         { json: "mesh", js: "mesh", typ: u(undefined, "") },
+        { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
+        { json: "type", js: "type", typ: u(undefined, r("TentacledType")) },
+    ], false),
+    "InlineData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "values", js: "values", typ: u(a(u(true, 3.14, m("any"), "")), m("any"), "") },
+    ], false),
+    "NamedData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "name", js: "name", typ: "" },
     ], false),
     "EncodingWithFacet": o([
-        { json: "color", js: "color", typ: u(undefined, r("MarkPropDefWithCondition")) },
+        { json: "color", js: "color", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
         { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
         { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
-        { json: "href", js: "href", typ: u(undefined, r("DefWithCondition")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("MarkPropDefWithCondition")) },
+        { json: "href", js: "href", typ: u(undefined, u(r("FieldDefWithCondition"), r("ValueDefWithCondition"))) },
+        { json: "opacity", js: "opacity", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
         { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
         { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "size", js: "size", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "text", js: "text", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "tooltip", js: "tooltip", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "x", js: "x", typ: u(undefined, r("XClass")) },
-        { json: "x2", js: "x2", typ: u(undefined, r("X2Class")) },
-        { json: "y", js: "y", typ: u(undefined, r("XClass")) },
-        { json: "y2", js: "y2", typ: u(undefined, r("X2Class")) },
+        { json: "shape", js: "shape", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "size", js: "size", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "text", js: "text", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "tooltip", js: "tooltip", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "x", js: "x", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "x2", js: "x2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+        { json: "y", js: "y", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "y2", js: "y2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
     ], false),
-    "MarkPropDefWithCondition": o([
+    "MarkPropFieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateMarkPropFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
         { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "BinParams": o([
         { json: "base", js: "base", typ: u(undefined, 3.14) },
@@ -6814,26 +7670,23 @@ const typeMap: any = {
         { json: "step", js: "step", typ: u(undefined, 3.14) },
         { json: "steps", js: "steps", typ: u(undefined, a(3.14)) },
     ], false),
-    "ConditionalValueDef": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "ConditionalPredicateValueDef": o([
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
         { json: "value", js: "value", typ: u(true, 3.14, "") },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
     ], false),
-    "Selection": o([
-        { json: "not", js: "not", typ: u(undefined, u(r("Selection"), "")) },
-        { json: "and", js: "and", typ: u(undefined, a(u(r("Selection"), ""))) },
-        { json: "or", js: "or", typ: u(undefined, a(u(r("Selection"), ""))) },
+    "LogicalOrPredicate": o([
+        { json: "or", js: "or", typ: a(u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "")) },
     ], false),
-    "Predicate": o([
-        { json: "not", js: "not", typ: u(undefined, u(r("Predicate"), "")) },
-        { json: "and", js: "and", typ: u(undefined, a(u(r("Predicate"), ""))) },
-        { json: "or", js: "or", typ: u(undefined, a(u(r("Predicate"), ""))) },
-        { json: "equal", js: "equal", typ: u(undefined, u(true, r("DateTime"), 3.14, "")) },
-        { json: "field", js: "field", typ: u(undefined, "") },
+    "LogicalAndPredicate": o([
+        { json: "and", js: "and", typ: a(u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "")) },
+    ], false),
+    "LogicalNotPredicate": o([
+        { json: "not", js: "not", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+    ], false),
+    "FieldEqualPredicate": o([
+        { json: "equal", js: "equal", typ: u(true, r("DateTime"), 3.14, "") },
+        { json: "field", js: "field", typ: "" },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "range", js: "range", typ: u(undefined, a(u(r("DateTime"), 3.14, null))) },
-        { json: "oneOf", js: "oneOf", typ: u(undefined, a(u(true, r("DateTime"), 3.14, ""))) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
     ], false),
     "DateTime": o([
         { json: "date", js: "date", typ: u(undefined, 3.14) },
@@ -6847,18 +7700,31 @@ const typeMap: any = {
         { json: "utc", js: "utc", typ: u(undefined, true) },
         { json: "year", js: "year", typ: u(undefined, 3.14) },
     ], false),
-    "ConditionalPredicateMarkPropFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
-        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
-        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+    "FieldRangePredicate": o([
+        { json: "field", js: "field", typ: "" },
+        { json: "range", js: "range", typ: a(u(r("DateTime"), 3.14, null)) },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+    ], false),
+    "FieldOneOfPredicate": o([
+        { json: "field", js: "field", typ: "" },
+        { json: "oneOf", js: "oneOf", typ: a(u(true, r("DateTime"), 3.14, "")) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+    ], false),
+    "SelectionPredicate": o([
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+    ], false),
+    "SelectionOr": o([
+        { json: "or", js: "or", typ: a(u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "")) },
+    ], false),
+    "SelectionAnd": o([
+        { json: "and", js: "and", typ: a(u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "")) },
+    ], false),
+    "SelectionNot": o([
+        { json: "not", js: "not", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+    ], false),
+    "ConditionalSelectionValueDef": o([
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+        { json: "value", js: "value", typ: u(true, 3.14, "") },
     ], false),
     "RepeatRef": o([
         { json: "repeat", js: "repeat", typ: r("RepeatEnum") },
@@ -6878,7 +7744,7 @@ const typeMap: any = {
     "Scale": o([
         { json: "base", js: "base", typ: u(undefined, 3.14) },
         { json: "clamp", js: "clamp", typ: u(undefined, true) },
-        { json: "domain", js: "domain", typ: u(undefined, u(a(u(true, r("DateTime"), 3.14, "")), r("DomainClass"), r("Domain"))) },
+        { json: "domain", js: "domain", typ: u(undefined, u(a(u(true, r("DateTime"), 3.14, "")), r("PurpleSelectionDomain"), r("FluffySelectionDomain"), r("Domain"))) },
         { json: "exponent", js: "exponent", typ: u(undefined, 3.14) },
         { json: "interpolate", js: "interpolate", typ: u(undefined, u(r("InterpolateParams"), r("Interpolate"))) },
         { json: "nice", js: "nice", typ: u(undefined, u(true, r("NiceClass"), 3.14, r("NiceTime"))) },
@@ -6892,10 +7758,13 @@ const typeMap: any = {
         { json: "type", js: "type", typ: u(undefined, r("ScaleType")) },
         { json: "zero", js: "zero", typ: u(undefined, true) },
     ], false),
-    "DomainClass": o([
+    "PurpleSelectionDomain": o([
         { json: "field", js: "field", typ: u(undefined, "") },
         { json: "selection", js: "selection", typ: "" },
+    ], false),
+    "FluffySelectionDomain": o([
         { json: "encoding", js: "encoding", typ: u(undefined, "") },
+        { json: "selection", js: "selection", typ: "" },
     ], false),
     "InterpolateParams": o([
         { json: "gamma", js: "gamma", typ: u(undefined, 3.14) },
@@ -6909,17 +7778,43 @@ const typeMap: any = {
         { json: "extent", js: "extent", typ: u(undefined, a(3.14)) },
         { json: "name", js: "name", typ: "" },
     ], false),
-    "SortField": o([
+    "SortField": o([
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "op", js: "op", typ: r("AggregateOp") },
+        { json: "order", js: "order", typ: u(undefined, u(r("SortOrderEnum"), null)) },
+    ], false),
+    "MarkPropValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateMarkPropFieldDef"), r("ConditionalSelectionMarkPropFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
+        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+    ], false),
+    "ConditionalPredicateMarkPropFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
+        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionMarkPropFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "op", js: "op", typ: r("AggregateOp") },
-        { json: "order", js: "order", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
+        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "FacetFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "header", js: "header", typ: u(undefined, r("Header")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
@@ -6935,65 +7830,83 @@ const typeMap: any = {
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "DefWithCondition": o([
+    "FieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "ConditionalPredicateFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "ValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateFieldDef"), r("ConditionalSelectionFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
+    ], false),
+    "ConditionalPredicateFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "OrderFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "TextDefWithCondition": o([
+    "TextFieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateTextFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "format", js: "format", typ: u(undefined, "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "ConditionalPredicateTextFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "TextValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateTextFieldDef"), r("ConditionalSelectionTextFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
+    ], false),
+    "ConditionalPredicateTextFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "format", js: "format", typ: u(undefined, "") },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionTextFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "format", js: "format", typ: u(undefined, "") },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "XClass": o([
+    "PositionFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "axis", js: "axis", typ: u(undefined, u(r("Axis"), null)) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
         { json: "stack", js: "stack", typ: u(undefined, u(r("StackOffset"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "Axis": o([
         { json: "domain", js: "domain", typ: u(undefined, true) },
@@ -7019,67 +7932,8 @@ const typeMap: any = {
         { json: "values", js: "values", typ: u(undefined, a(u(r("DateTime"), 3.14))) },
         { json: "zindex", js: "zindex", typ: u(undefined, 3.14) },
     ], false),
-    "X2Class": o([
-        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-    ], false),
-    "FacetMapping": o([
-        { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
-        { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
-    ], false),
-    "Spec": o([
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
-        { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "name", js: "name", typ: u(undefined, "") },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
-        { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("Encoding")) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
-        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
-        { json: "facet", js: "facet", typ: u(undefined, r("FacetMapping")) },
-        { json: "spec", js: "spec", typ: u(undefined, r("Spec")) },
-        { json: "repeat", js: "repeat", typ: u(undefined, r("Repeat")) },
-        { json: "vconcat", js: "vconcat", typ: u(undefined, a(r("Spec"))) },
-        { json: "hconcat", js: "hconcat", typ: u(undefined, a(r("Spec"))) },
-    ], false),
-    "Encoding": o([
-        { json: "color", js: "color", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
-        { json: "href", js: "href", typ: u(undefined, r("DefWithCondition")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
-        { json: "shape", js: "shape", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "size", js: "size", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "text", js: "text", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "tooltip", js: "tooltip", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "x", js: "x", typ: u(undefined, r("XClass")) },
-        { json: "x2", js: "x2", typ: u(undefined, r("X2Class")) },
-        { json: "y", js: "y", typ: u(undefined, r("XClass")) },
-        { json: "y2", js: "y2", typ: u(undefined, r("X2Class")) },
-    ], false),
-    "LayerSpec": o([
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
-        { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "name", js: "name", typ: u(undefined, "") },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
-        { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("Encoding")) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
-        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
+    "ValueDef": o([
+        { json: "value", js: "value", typ: u(true, 3.14, "") },
     ], false),
     "MarkDef": o([
         { json: "align", js: "align", typ: u(undefined, r("HorizontalAlign")) },
@@ -7136,41 +7990,36 @@ const typeMap: any = {
     "FluffyPrecision": o([
         { json: "length", js: "length", typ: 3.14 },
     ], ""),
-    "Resolve": o([
-        { json: "axis", js: "axis", typ: u(undefined, r("AxisResolveMap")) },
-        { json: "legend", js: "legend", typ: u(undefined, r("LegendResolveMap")) },
-        { json: "scale", js: "scale", typ: u(undefined, r("ScaleResolveMap")) },
-    ], false),
-    "AxisResolveMap": o([
-        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
-        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
-    ], false),
-    "LegendResolveMap": o([
-        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
-        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
-    ], false),
-    "ScaleResolveMap": o([
-        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
-        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
-        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
-        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    "SingleSelection": o([
+        { json: "bind", js: "bind", typ: u(undefined, m(u(r("VGCheckboxBinding"), r("VGRadioBinding"), r("VGSelectBinding"), r("VGRangeBinding"), r("VGGenericBinding")))) },
+        { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
+        { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
+        { json: "nearest", js: "nearest", typ: u(undefined, true) },
+        { json: "on", js: "on", typ: u(undefined, "any") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
+        { json: "type", js: "type", typ: r("StickyType") },
     ], false),
-    "SelectionDef": o([
-        { json: "bind", js: "bind", typ: u(undefined, u(r("BindEnum"), m(r("VGBinding")))) },
+    "MultiSelection": o([
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
         { json: "nearest", js: "nearest", typ: u(undefined, true) },
         { json: "on", js: "on", typ: u(undefined, "any") },
         { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
-        { json: "type", js: "type", typ: r("SelectionDefType") },
         { json: "toggle", js: "toggle", typ: u(undefined, u(true, "")) },
+        { json: "type", js: "type", typ: r("IndigoType") },
+    ], false),
+    "IntervalSelection": o([
+        { json: "bind", js: "bind", typ: u(undefined, r("Bind")) },
+        { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
+        { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
         { json: "mark", js: "mark", typ: u(undefined, r("BrushConfig")) },
+        { json: "on", js: "on", typ: u(undefined, "any") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
         { json: "translate", js: "translate", typ: u(undefined, u(true, "")) },
+        { json: "type", js: "type", typ: r("IndecentType") },
         { json: "zoom", js: "zoom", typ: u(undefined, u(true, "")) },
     ], false),
     "TitleParams": o([
@@ -7180,17 +8029,36 @@ const typeMap: any = {
         { json: "style", js: "style", typ: u(undefined, u(a(""), "")) },
         { json: "text", js: "text", typ: "" },
     ], false),
-    "Transform": o([
-        { json: "filter", js: "filter", typ: u(undefined, u(r("Predicate"), "")) },
+    "FilterTransform": o([
+        { json: "filter", js: "filter", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+    ], false),
+    "CalculateTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "calculate", js: "calculate", typ: "" },
+    ], false),
+    "LookupTransform": o([
         { json: "as", js: "as", typ: u(undefined, u(a(""), "")) },
-        { json: "calculate", js: "calculate", typ: u(undefined, "") },
         { json: "default", js: "default", typ: u(undefined, "") },
-        { json: "from", js: "from", typ: u(undefined, r("LookupData")) },
-        { json: "lookup", js: "lookup", typ: u(undefined, "") },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, "") },
-        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "aggregate", js: "aggregate", typ: u(undefined, a(r("AggregatedFieldDef"))) },
+        { json: "from", js: "from", typ: r("LookupData") },
+        { json: "lookup", js: "lookup", typ: "" },
+    ], false),
+    "LookupData": o([
+        { json: "data", js: "data", typ: u(r("URLData"), r("InlineData"), r("NamedData")) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
+        { json: "key", js: "key", typ: "" },
+    ], false),
+    "BinTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "bin", js: "bin", typ: u(true, r("BinParams")) },
+        { json: "field", js: "field", typ: "" },
+    ], false),
+    "TimeUnitTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "field", js: "field", typ: "" },
+        { json: "timeUnit", js: "timeUnit", typ: r("TimeUnit") },
+    ], false),
+    "AggregateTransform": o([
+        { json: "aggregate", js: "aggregate", typ: a(r("AggregatedFieldDef")) },
         { json: "groupby", js: "groupby", typ: u(undefined, a("")) },
     ], false),
     "AggregatedFieldDef": o([
@@ -7198,15 +8066,188 @@ const typeMap: any = {
         { json: "field", js: "field", typ: "" },
         { json: "op", js: "op", typ: r("AggregateOp") },
     ], false),
-    "LookupData": o([
-        { json: "data", js: "data", typ: r("Data") },
-        { json: "fields", js: "fields", typ: u(undefined, a("")) },
-        { json: "key", js: "key", typ: "" },
+    "TopLevelLayerSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "layer", js: "layer", typ: a(u(r("LayerSpec"), r("CompositeUnitSpecAlias"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "LayerSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "layer", js: "layer", typ: a(u(r("LayerSpec"), r("CompositeUnitSpecAlias"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "Resolve": o([
+        { json: "axis", js: "axis", typ: u(undefined, r("AxisResolveMap")) },
+        { json: "legend", js: "legend", typ: u(undefined, r("LegendResolveMap")) },
+        { json: "scale", js: "scale", typ: u(undefined, r("ScaleResolveMap")) },
+    ], false),
+    "AxisResolveMap": o([
+        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
+        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "LegendResolveMap": o([
+        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
+        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
+        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
+        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "ScaleResolveMap": o([
+        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
+        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
+        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
+        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
+        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
+        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "CompositeUnitSpecAlias": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "encoding", js: "encoding", typ: r("Encoding") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "mark", js: "mark", typ: u(r("MarkDef"), r("Mark")) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
+        { json: "selection", js: "selection", typ: u(undefined, m(u(r("SingleSelection"), r("MultiSelection"), r("IntervalSelection")))) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "Encoding": o([
+        { json: "color", js: "color", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
+        { json: "href", js: "href", typ: u(undefined, u(r("FieldDefWithCondition"), r("ValueDefWithCondition"))) },
+        { json: "opacity", js: "opacity", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
+        { json: "shape", js: "shape", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "size", js: "size", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "text", js: "text", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "tooltip", js: "tooltip", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "x", js: "x", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "x2", js: "x2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+        { json: "y", js: "y", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "y2", js: "y2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+    ], false),
+    "TopLevelFacetSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "facet", js: "facet", typ: r("FacetMapping") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("LayerSpec"), r("CompositeUnitSpecAlias")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "FacetMapping": o([
+        { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
+        { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
+    ], false),
+    "TopLevelRepeatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "repeat", js: "repeat", typ: r("Repeat") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
     ], false),
     "Repeat": o([
         { json: "column", js: "column", typ: u(undefined, a("")) },
         { json: "row", js: "row", typ: u(undefined, a("")) },
     ], false),
+    "HConcatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "hconcat", js: "hconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "VConcatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "vconcat", js: "vconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+    ], false),
+    "RepeatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "repeat", js: "repeat", typ: r("Repeat") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "FacetSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "facet", js: "facet", typ: r("FacetMapping") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("LayerSpec"), r("CompositeUnitSpecAlias")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "TopLevelVConcatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "vconcat", js: "vconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+    ], false),
+    "TopLevelHConcatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "hconcat", js: "hconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
     "Contains": [
         "content",
         "padding",
@@ -7327,7 +8368,7 @@ const typeMap: any = {
         "stereographic",
         "transverseMercator",
     ],
-    "BindEnum": [
+    "Bind": [
         "scales",
     ],
     "Empty": [
@@ -7354,6 +8395,18 @@ const typeMap: any = {
         "union",
         "intersect",
     ],
+    "PurpleInput": [
+        "checkbox",
+    ],
+    "FluffyInput": [
+        "radio",
+    ],
+    "TentacledInput": [
+        "select",
+    ],
+    "StickyInput": [
+        "range",
+    ],
     "StackOffset": [
         "zero",
         "center",
@@ -7373,10 +8426,14 @@ const typeMap: any = {
     "ParseEnum": [
         "auto",
     ],
-    "DataFormatType": [
+    "PurpleType": [
         "csv",
         "tsv",
+    ],
+    "FluffyType": [
         "json",
+    ],
+    "TentacledType": [
         "topojson",
     ],
     "AggregateOp": [
@@ -7487,7 +8544,7 @@ const typeMap: any = {
         "point",
         "band",
     ],
-    "SortEnum": [
+    "SortOrderEnum": [
         "ascending",
         "descending",
     ],
@@ -7513,15 +8570,19 @@ const typeMap: any = {
         "square",
         "geoshape",
     ],
-    "ResolveMode": [
-        "independent",
-        "shared",
-    ],
-    "SelectionDefType": [
+    "StickyType": [
         "single",
+    ],
+    "IndigoType": [
         "multi",
+    ],
+    "IndecentType": [
         "interval",
     ],
+    "ResolveMode": [
+        "independent",
+        "shared",
+    ],
 };
 
 module.exports = {
diff --git a/head/schema-golang/test/inputs/schema/one-of-objects.schema/default/quicktype.go b/head/schema-golang/test/inputs/schema/one-of-objects.schema/default/quicktype.go
new file mode 100644
index 0000000..f647d5b
--- /dev/null
+++ b/head/schema-golang/test/inputs/schema/one-of-objects.schema/default/quicktype.go
@@ -0,0 +1,30 @@
+// Code generated from JSON Schema using quicktype. DO NOT EDIT.
+// To parse and unparse this JSON data, add this code to your project and do:
+//
+//    topLevel, err := UnmarshalTopLevel(bytes)
+//    bytes, err = topLevel.Marshal()
+
+package main
+
+import "encoding/json"
+
+func UnmarshalTopLevel(data []byte) (TopLevel, error) {
+	var r TopLevel
+	err := json.Unmarshal(data, &r)
+	return r, err
+}
+
+func (r *TopLevel) Marshal() ([]byte, error) {
+	return json.Marshal(r)
+}
+
+type TopLevel struct {
+	Items []Item `json:"items"`
+}
+
+type Item struct {
+	Aa *string `json:"aa,omitempty"`
+	Bb *string `json:"bb,omitempty"`
+	Cc *string `json:"cc,omitempty"`
+	DD *string `json:"dd,omitempty"`
+}
diff --git a/head/schema-haskell/test/inputs/schema/one-of-objects.schema/default/QuickType.hs b/head/schema-haskell/test/inputs/schema/one-of-objects.schema/default/QuickType.hs
new file mode 100644
index 0000000..e4ec47f
--- /dev/null
+++ b/head/schema-haskell/test/inputs/schema/one-of-objects.schema/default/QuickType.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE StrictData #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module QuickType
+    ( QuickType (..)
+    , Item (..)
+    , decodeTopLevel
+    ) where
+
+import Data.Aeson
+import Data.Aeson.Types (emptyObject)
+import Data.ByteString.Lazy (ByteString)
+import Data.HashMap.Strict (HashMap)
+import Data.Text (Text)
+
+data QuickType = QuickType
+    { itemsQuickType :: [Item]
+    } deriving (Show)
+
+data Item = Item
+    { aaItem :: Maybe Text
+    , bbItem :: Maybe Text
+    , ccItem :: Maybe Text
+    , ddItem :: Maybe Text
+    } deriving (Show)
+
+decodeTopLevel :: ByteString -> Maybe QuickType
+decodeTopLevel = decode
+
+instance ToJSON QuickType where
+    toJSON (QuickType itemsQuickType) =
+        object
+        [ "items" .= itemsQuickType
+        ]
+
+instance FromJSON QuickType where
+    parseJSON (Object v) = QuickType
+        <$> v .: "items"
+
+instance ToJSON Item where
+    toJSON (Item aaItem bbItem ccItem ddItem) =
+        object
+        [ "aa" .= aaItem
+        , "bb" .= bbItem
+        , "cc" .= ccItem
+        , "dd" .= ddItem
+        ]
+
+instance FromJSON Item where
+    parseJSON (Object v) = Item
+        <$> v .:? "aa"
+        <*> v .:? "bb"
+        <*> v .:? "cc"
+        <*> v .:? "dd"
diff --git a/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
new file mode 100644
index 0000000..a8eb236
--- /dev/null
+++ b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
@@ -0,0 +1,101 @@
+// To use this code, add the following Maven dependency to your project:
+//
+//
+//     com.fasterxml.jackson.core     : jackson-databind          : 2.9.0
+//     com.fasterxml.jackson.datatype : jackson-datatype-jsr310   : 2.9.0
+//
+// Import this package:
+//
+//     import io.quicktype.Converter;
+//
+// Then you can deserialize a JSON string with
+//
+//     TopLevel data = Converter.fromJsonString(jsonString);
+
+package io.quicktype;
+
+import java.io.IOException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.*;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.ChronoField;
+
+public class Converter {
+    // Date-time helpers
+
+    private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
+            .appendOptional(DateTimeFormatter.ISO_DATE_TIME)
+            .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
+            .appendOptional(DateTimeFormatter.ISO_INSTANT)
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
+            .toFormatter()
+            .withZone(ZoneOffset.UTC);
+
+    public static OffsetDateTime parseDateTimeString(String str) {
+        return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();
+    }
+
+    private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()
+            .appendOptional(DateTimeFormatter.ISO_TIME)
+            .appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)
+            .parseDefaulting(ChronoField.YEAR, 2020)
+            .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
+            .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
+            .toFormatter()
+            .withZone(ZoneOffset.UTC);
+
+    public static OffsetTime parseTimeString(String str) {
+        return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();
+    }
+    // Serialize/deserialize helpers
+
+    public static TopLevel fromJsonString(String json) throws IOException {
+        return getObjectReader().readValue(json);
+    }
+
+    public static String toJsonString(TopLevel obj) throws JsonProcessingException {
+        return getObjectWriter().writeValueAsString(obj);
+    }
+
+    private static ObjectReader reader;
+    private static ObjectWriter writer;
+
+    private static void instantiateMapper() {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.findAndRegisterModules();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        SimpleModule module = new SimpleModule();
+        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
+            @Override
+            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                String value = jsonParser.getText();
+                return Converter.parseDateTimeString(value);
+            }
+        });
+        mapper.registerModule(module);
+        reader = mapper.readerFor(TopLevel.class);
+        writer = mapper.writerFor(TopLevel.class);
+    }
+
+    private static ObjectReader getObjectReader() {
+        if (reader == null) instantiateMapper();
+        return reader;
+    }
+
+    private static ObjectWriter getObjectWriter() {
+        if (writer == null) instantiateMapper();
+        return writer;
+    }
+}
diff --git a/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
new file mode 100644
index 0000000..d0de7ab
--- /dev/null
+++ b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
@@ -0,0 +1,30 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+
+public class Item {
+    private String aa;
+    private String bb;
+    private String cc;
+    private String dd;
+
+    @JsonProperty("aa")
+    public String getAa() { return aa; }
+    @JsonProperty("aa")
+    public void setAa(String value) { this.aa = value; }
+
+    @JsonProperty("bb")
+    public String getBb() { return bb; }
+    @JsonProperty("bb")
+    public void setBb(String value) { this.bb = value; }
+
+    @JsonProperty("cc")
+    public String getCc() { return cc; }
+    @JsonProperty("cc")
+    public void setCc(String value) { this.cc = value; }
+
+    @JsonProperty("dd")
+    public String getDD() { return dd; }
+    @JsonProperty("dd")
+    public void setDD(String value) { this.dd = value; }
+}
diff --git a/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
new file mode 100644
index 0000000..5243fee
--- /dev/null
+++ b/head/schema-java/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
@@ -0,0 +1,13 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+import java.util.List;
+
+public class TopLevel {
+    private List<Item> items;
+
+    @JsonProperty("items")
+    public List<Item> getItems() { return items; }
+    @JsonProperty("items")
+    public void setItems(List<Item> value) { this.items = value; }
+}
diff --git a/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
new file mode 100644
index 0000000..7d4811b
--- /dev/null
+++ b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
@@ -0,0 +1,121 @@
+// To use this code, add the following Maven dependency to your project:
+//
+//
+//     com.fasterxml.jackson.core     : jackson-databind          : 2.9.0
+//
+//
+// Import this package:
+//
+//     import io.quicktype.Converter;
+//
+// Then you can deserialize a JSON string with
+//
+//     TopLevel data = Converter.fromJsonString(jsonString);
+
+package io.quicktype;
+
+import java.io.IOException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.*;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+
+public class Converter {
+    // Date-time helpers
+
+    private static final String[] DATE_TIME_FORMATS = {
+            "yyyy-MM-dd'T'HH:mm:ss.SX",
+            "yyyy-MM-dd'T'HH:mm:ss.S",
+            "yyyy-MM-dd'T'HH:mm:ssX",
+            "yyyy-MM-dd'T'HH:mm:ss",
+            "yyyy-MM-dd HH:mm:ss.SX",
+            "yyyy-MM-dd HH:mm:ss.S",
+            "yyyy-MM-dd HH:mm:ssX",
+            "yyyy-MM-dd HH:mm:ss",
+            "HH:mm:ss.SZ",
+            "HH:mm:ss.S",
+            "HH:mm:ssZ",
+            "HH:mm:ss",
+            "yyyy-MM-dd",
+    };
+
+    public static Date parseAllDateTimeString(String str) {
+        for (String format : DATE_TIME_FORMATS) {
+            try {
+                return new SimpleDateFormat(format).parse(str);
+            } catch (Exception ex) {
+                // Ignored
+            }
+        }
+        return null;
+    }
+
+    public static String serializeDateTime(Date datetime) {
+        return new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").format(datetime);
+    }
+
+    public static String serializeDate(Date datetime) {
+        return new SimpleDateFormat("yyyy-MM-dd").format(datetime);
+    }
+
+    public static String serializeTime(Date datetime) {
+        return new SimpleDateFormat("hh:mm:ssZ").format(datetime);
+    }
+    // Serialize/deserialize helpers
+
+    public static TopLevel fromJsonString(String json) throws IOException {
+        return getObjectReader().readValue(json);
+    }
+
+    public static String toJsonString(TopLevel obj) throws JsonProcessingException {
+        return getObjectWriter().writeValueAsString(obj);
+    }
+
+    private static ObjectReader reader;
+    private static ObjectWriter writer;
+
+    private static void instantiateMapper() {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.findAndRegisterModules();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        SimpleModule module = new SimpleModule();
+        module.addDeserializer(Date.class, new JsonDeserializer<Date>() {
+            @Override
+            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                String value = jsonParser.getText();
+                return Converter.parseAllDateTimeString(value);
+            }
+        });
+        module.addDeserializer(Date.class, new JsonDeserializer<Date>() {
+            @Override
+            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                String value = jsonParser.getText();
+                return Converter.parseAllDateTimeString(value);
+            }
+        });
+        module.addDeserializer(Date.class, new JsonDeserializer<Date>() {
+            @Override
+            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                String value = jsonParser.getText();
+                return Converter.parseAllDateTimeString(value);
+            }
+        });
+        mapper.registerModule(module);
+        reader = mapper.readerFor(TopLevel.class);
+        writer = mapper.writerFor(TopLevel.class);
+    }
+
+    private static ObjectReader getObjectReader() {
+        if (reader == null) instantiateMapper();
+        return reader;
+    }
+
+    private static ObjectWriter getObjectWriter() {
+        if (writer == null) instantiateMapper();
+        return writer;
+    }
+}
diff --git a/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
new file mode 100644
index 0000000..d0de7ab
--- /dev/null
+++ b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
@@ -0,0 +1,30 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+
+public class Item {
+    private String aa;
+    private String bb;
+    private String cc;
+    private String dd;
+
+    @JsonProperty("aa")
+    public String getAa() { return aa; }
+    @JsonProperty("aa")
+    public void setAa(String value) { this.aa = value; }
+
+    @JsonProperty("bb")
+    public String getBb() { return bb; }
+    @JsonProperty("bb")
+    public void setBb(String value) { this.bb = value; }
+
+    @JsonProperty("cc")
+    public String getCc() { return cc; }
+    @JsonProperty("cc")
+    public void setCc(String value) { this.cc = value; }
+
+    @JsonProperty("dd")
+    public String getDD() { return dd; }
+    @JsonProperty("dd")
+    public void setDD(String value) { this.dd = value; }
+}
diff --git a/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
new file mode 100644
index 0000000..5243fee
--- /dev/null
+++ b/head/schema-java-datetime-legacy/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
@@ -0,0 +1,13 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+import java.util.List;
+
+public class TopLevel {
+    private List<Item> items;
+
+    @JsonProperty("items")
+    public List<Item> getItems() { return items; }
+    @JsonProperty("items")
+    public void setItems(List<Item> value) { this.items = value; }
+}
diff --git a/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
new file mode 100644
index 0000000..a8eb236
--- /dev/null
+++ b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Converter.java
@@ -0,0 +1,101 @@
+// To use this code, add the following Maven dependency to your project:
+//
+//
+//     com.fasterxml.jackson.core     : jackson-databind          : 2.9.0
+//     com.fasterxml.jackson.datatype : jackson-datatype-jsr310   : 2.9.0
+//
+// Import this package:
+//
+//     import io.quicktype.Converter;
+//
+// Then you can deserialize a JSON string with
+//
+//     TopLevel data = Converter.fromJsonString(jsonString);
+
+package io.quicktype;
+
+import java.io.IOException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.util.*;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.ChronoField;
+
+public class Converter {
+    // Date-time helpers
+
+    private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
+            .appendOptional(DateTimeFormatter.ISO_DATE_TIME)
+            .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
+            .appendOptional(DateTimeFormatter.ISO_INSTANT)
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))
+            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
+            .toFormatter()
+            .withZone(ZoneOffset.UTC);
+
+    public static OffsetDateTime parseDateTimeString(String str) {
+        return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();
+    }
+
+    private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()
+            .appendOptional(DateTimeFormatter.ISO_TIME)
+            .appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)
+            .parseDefaulting(ChronoField.YEAR, 2020)
+            .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
+            .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
+            .toFormatter()
+            .withZone(ZoneOffset.UTC);
+
+    public static OffsetTime parseTimeString(String str) {
+        return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();
+    }
+    // Serialize/deserialize helpers
+
+    public static TopLevel fromJsonString(String json) throws IOException {
+        return getObjectReader().readValue(json);
+    }
+
+    public static String toJsonString(TopLevel obj) throws JsonProcessingException {
+        return getObjectWriter().writeValueAsString(obj);
+    }
+
+    private static ObjectReader reader;
+    private static ObjectWriter writer;
+
+    private static void instantiateMapper() {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.findAndRegisterModules();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        SimpleModule module = new SimpleModule();
+        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
+            @Override
+            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+                String value = jsonParser.getText();
+                return Converter.parseDateTimeString(value);
+            }
+        });
+        mapper.registerModule(module);
+        reader = mapper.readerFor(TopLevel.class);
+        writer = mapper.writerFor(TopLevel.class);
+    }
+
+    private static ObjectReader getObjectReader() {
+        if (reader == null) instantiateMapper();
+        return reader;
+    }
+
+    private static ObjectWriter getObjectWriter() {
+        if (writer == null) instantiateMapper();
+        return writer;
+    }
+}
diff --git a/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
new file mode 100644
index 0000000..d0de7ab
--- /dev/null
+++ b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/Item.java
@@ -0,0 +1,30 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+
+public class Item {
+    private String aa;
+    private String bb;
+    private String cc;
+    private String dd;
+
+    @JsonProperty("aa")
+    public String getAa() { return aa; }
+    @JsonProperty("aa")
+    public void setAa(String value) { this.aa = value; }
+
+    @JsonProperty("bb")
+    public String getBb() { return bb; }
+    @JsonProperty("bb")
+    public void setBb(String value) { this.bb = value; }
+
+    @JsonProperty("cc")
+    public String getCc() { return cc; }
+    @JsonProperty("cc")
+    public void setCc(String value) { this.cc = value; }
+
+    @JsonProperty("dd")
+    public String getDD() { return dd; }
+    @JsonProperty("dd")
+    public void setDD(String value) { this.dd = value; }
+}
diff --git a/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
new file mode 100644
index 0000000..5243fee
--- /dev/null
+++ b/head/schema-java-lombok/test/inputs/schema/one-of-objects.schema/default/src/main/java/io/quicktype/TopLevel.java
@@ -0,0 +1,13 @@
+package io.quicktype;
+
+import com.fasterxml.jackson.annotation.*;
+import java.util.List;
+
+public class TopLevel {
+    private List<Item> items;
+
+    @JsonProperty("items")
+    public List<Item> getItems() { return items; }
+    @JsonProperty("items")
+    public void setItems(List<Item> value) { this.items = value; }
+}
diff --git a/base/schema-javascript/test/inputs/schema/class-map-union.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/class-map-union.schema/default/TopLevel.js
index ad7f196..5d2dbed 100644
--- a/base/schema-javascript/test/inputs/schema/class-map-union.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/class-map-union.schema/default/TopLevel.js
@@ -172,13 +172,15 @@ function r(name) {
 
 const typeMap = {
     "TopLevel": o([
-        { json: "union", js: "union", typ: u(undefined, r("TopLevelUnion")) },
+        { json: "union", js: "union", typ: u(undefined, u(r("PurpleUnion"), r("FluffyUnion"), m(true), m(r("UnionValue")))) },
     ], false),
-    "TopLevelUnion": o([
-        { json: "foo", js: "foo", typ: u(undefined, u(true, 3.14, r("BarObject"))) },
-        { json: "bar", js: "bar", typ: u(undefined, u(true, r("BarObject"), "")) },
-    ], u(true, r("BarObject"))),
-    "BarObject": o([
+    "PurpleUnion": o([
+        { json: "foo", js: "foo", typ: u(undefined, 3.14) },
+    ], false),
+    "FluffyUnion": o([
+        { json: "bar", js: "bar", typ: u(undefined, "") },
+    ], false),
+    "UnionValue": o([
         { json: "quux", js: "quux", typ: u(undefined, 0) },
     ], "any"),
 };
diff --git a/base/schema-javascript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
index 9569316..a8a689e 100644
--- a/base/schema-javascript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.js
@@ -172,13 +172,17 @@ function r(name) {
 
 const typeMap = {
     "TopLevel": o([
-        { json: "input", js: "input", typ: a(r("Item")) },
+        { json: "input", js: "input", typ: a(u(r("Message"), r("FunctionOutput"), r("ReasoningItem"))) },
     ], false),
-    "Item": o([
-        { json: "content", js: "content", typ: u(undefined, "") },
-        { json: "id", js: "id", typ: u(undefined, "") },
-        { json: "output", js: "output", typ: u(undefined, "") },
-        { json: "summary", js: "summary", typ: u(undefined, "") },
+    "Message": o([
+        { json: "content", js: "content", typ: "" },
+    ], "any"),
+    "FunctionOutput": o([
+        { json: "id", js: "id", typ: "" },
+        { json: "output", js: "output", typ: "" },
+    ], "any"),
+    "ReasoningItem": o([
+        { json: "summary", js: "summary", typ: "" },
     ], "any"),
 };
 
diff --git a/base/schema-javascript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
index eab286e..e1b8897 100644
--- a/base/schema-javascript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.js
@@ -10,11 +10,11 @@
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json) {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("One"), r("Two")));
 }
 
 function topLevelToJson(value) {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("One"), r("Two"))), null, 2);
 }
 
 function invalidValue(typ, val, key, parent = '') {
@@ -171,12 +171,18 @@ function r(name) {
 }
 
 const typeMap = {
-    "TopLevel": o([
+    "One": o([
+        { json: "b", js: "b", typ: u(null, "") },
+        { json: "kind", js: "kind", typ: r("PurpleKind") },
+    ], "any"),
+    "Two": o([
         { json: "b", js: "b", typ: u(undefined, u(null, "")) },
-        { json: "kind", js: "kind", typ: r("Kind") },
+        { json: "kind", js: "kind", typ: r("FluffyKind") },
     ], "any"),
-    "Kind": [
+    "PurpleKind": [
         "one",
+    ],
+    "FluffyKind": [
         "two",
     ],
 };
diff --git a/head/schema-javascript/test/inputs/schema/one-of-objects.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/one-of-objects.schema/default/TopLevel.js
new file mode 100644
index 0000000..569cef9
--- /dev/null
+++ b/head/schema-javascript/test/inputs/schema/one-of-objects.schema/default/TopLevel.js
@@ -0,0 +1,190 @@
+// To parse this data:
+//
+//   const Convert = require("./TopLevel");
+//
+//   const topLevel = Convert.toTopLevel(json);
+//
+// These functions will throw an error if the JSON doesn't
+// match the expected interface, even if the JSON is valid.
+
+// Converts JSON strings to/from your types
+// and asserts the results of JSON.parse at runtime
+function toTopLevel(json) {
+    return cast(JSON.parse(json), r("TopLevel"));
+}
+
+function topLevelToJson(value) {
+    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+}
+
+function invalidValue(typ, val, key, parent = '') {
+    const prettyTyp = prettyTypeName(typ);
+    const parentText = parent ? ` on ${parent}` : '';
+    const keyText = key ? ` for key "${key}"` : '';
+    throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);
+}
+
+function prettyTypeName(typ) {
+    if (Array.isArray(typ)) {
+        if (typ.length === 2 && typ[0] === undefined) {
+            return `an optional ${prettyTypeName(typ[1])}`;
+        } else {
+            return `one of [${typ.map(a => { return prettyTypeName(a); }).join(", ")}]`;
+        }
+    } else if (typeof typ === "object" && typ.literal !== undefined) {
+        return typ.literal;
+    } else {
+        return typeof typ;
+    }
+}
+
+function jsonToJSProps(typ) {
+    if (typ.jsonToJS === undefined) {
+        const map = {};
+        typ.props.forEach((p) => map[p.json] = { key: p.js, typ: p.typ });
+        typ.jsonToJS = map;
+    }
+    return typ.jsonToJS;
+}
+
+function jsToJSONProps(typ) {
+    if (typ.jsToJSON === undefined) {
+        const map = {};
+        typ.props.forEach((p) => map[p.js] = { key: p.json, typ: p.typ });
+        typ.jsToJSON = map;
+    }
+    return typ.jsToJSON;
+}
+
+function transform(val, typ, getProps, key = '', parent = '') {
+    function transformPrimitive(typ, val) {
+        if (typeof typ === typeof val) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+
+    function transformUnion(typs, val) {
+        // val must validate against one typ in typs
+        const l = typs.length;
+        for (let i = 0; i < l; i++) {
+            const typ = typs[i];
+            try {
+                return transform(val, typ, getProps);
+            } catch (_) {}
+        }
+        return invalidValue(typs, val, key, parent);
+    }
+
+    function transformEnum(cases, val) {
+        if (cases.indexOf(val) !== -1) return val;
+        return invalidValue(cases.map(a => { return l(a); }), val, key, parent);
+    }
+
+    function transformArray(typ, val) {
+        // val must be an array with no invalid elements
+        if (!Array.isArray(val)) return invalidValue(l("array"), val, key, parent);
+        return val.map(el => transform(el, typ, getProps));
+    }
+
+    function transformDate(val) {
+        if (val === null) {
+            return null;
+        }
+        const d = new Date(val);
+        if (isNaN(d.valueOf())) {
+            return invalidValue(l("Date"), val, key, parent);
+        }
+        return d;
+    }
+
+    function transformObject(props, additional, val) {
+        if (val === null || typeof val !== "object" || Array.isArray(val)) {
+            return invalidValue(l(ref || "object"), val, key, parent);
+        }
+        const result = {};
+        Object.getOwnPropertyNames(props).forEach(key => {
+            const prop = props[key];
+            const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;
+            result[prop.key] = transform(v, prop.typ, getProps, key, ref);
+        });
+        Object.getOwnPropertyNames(val).forEach(key => {
+            if (!Object.prototype.hasOwnProperty.call(props, key)) {
+                result[key] = transform(val[key], additional, getProps, key, ref);
+            }
+        });
+        return result;
+    }
+
+    if (typ === "any") return val;
+    if (typ === null) {
+        if (val === null) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+    if (typ === false) return invalidValue(typ, val, key, parent);
+    let ref = undefined;
+    while (typeof typ === "object" && typ.ref !== undefined) {
+        ref = typ.ref;
+        typ = typeMap[typ.ref];
+    }
+    if (Array.isArray(typ)) return transformEnum(typ, val);
+    if (typeof typ === "object") {
+        return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val)
+            : typ.hasOwnProperty("arrayItems")    ? transformArray(typ.arrayItems, val)
+            : typ.hasOwnProperty("props")         ? transformObject(getProps(typ), typ.additional, val)
+            : invalidValue(typ, val, key, parent);
+    }
+    // Numbers can be parsed by Date but shouldn't be.
+    if (typ === Date && typeof val !== "number") return transformDate(val);
+    return transformPrimitive(typ, val);
+}
+
+function cast(val, typ) {
+    return transform(val, typ, jsonToJSProps);
+}
+
+function uncast(val, typ) {
+    return transform(val, typ, jsToJSONProps);
+}
+
+function l(typ) {
+    return { literal: typ };
+}
+
+function a(typ) {
+    return { arrayItems: typ };
+}
+
+function u(...typs) {
+    return { unionMembers: typs };
+}
+
+function o(props, additional) {
+    return { props, additional };
+}
+
+function m(additional) {
+    const props = [];
+    return { props, additional };
+}
+
+function r(name) {
+    return { ref: name };
+}
+
+const typeMap = {
+    "TopLevel": o([
+        { json: "items", js: "items", typ: a(u(r("PurpleItem"), r("FluffyItem"))) },
+    ], false),
+    "PurpleItem": o([
+        { json: "aa", js: "aa", typ: u(undefined, "") },
+        { json: "bb", js: "bb", typ: u(undefined, "") },
+    ], false),
+    "FluffyItem": o([
+        { json: "cc", js: "cc", typ: u(undefined, "") },
+        { json: "dd", js: "dd", typ: u(undefined, "") },
+    ], false),
+};
+
+module.exports = {
+    "topLevelToJson": topLevelToJson,
+    "toTopLevel": toTopLevel,
+};
diff --git a/base/schema-javascript/test/inputs/schema/postman-collection.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/postman-collection.schema/default/TopLevel.js
index 96a033b..94e58c8 100644
--- a/base/schema-javascript/test/inputs/schema/postman-collection.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/postman-collection.schema/default/TopLevel.js
@@ -10,11 +10,11 @@
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json) {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("Group"), r("Item")));
 }
 
 function topLevelToJson(value) {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("Group"), r("Item"))), null, 2);
 }
 
 function invalidValue(typ, val, key, parent = '') {
@@ -171,8 +171,10 @@ function r(name) {
 }
 
 const typeMap = {
-    "TopLevel": o([
-        { json: "item", js: "item", typ: u(undefined, a(r("TopLevel"))) },
+    "Group": o([
+        { json: "item", js: "item", typ: u(undefined, a(u(r("Group"), r("Item")))) },
+    ], "any"),
+    "Item": o([
         { json: "name", js: "name", typ: u(undefined, "") },
         { json: "response", js: "response", typ: u(undefined, a(r("Response"))) },
     ], "any"),
diff --git a/base/schema-javascript/test/inputs/schema/union.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/union.schema/default/TopLevel.js
index dca09fe..594a96d 100644
--- a/base/schema-javascript/test/inputs/schema/union.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/union.schema/default/TopLevel.js
@@ -10,11 +10,11 @@
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json) {
-    return cast(JSON.parse(json), a(r("TopLevel")));
+    return cast(JSON.parse(json), a(u(r("PurpleTopLevel"), r("FluffyTopLevel"))));
 }
 
 function topLevelToJson(value) {
-    return JSON.stringify(uncast(value, a(r("TopLevel"))), null, 2);
+    return JSON.stringify(uncast(value, a(u(r("PurpleTopLevel"), r("FluffyTopLevel")))), null, 2);
 }
 
 function invalidValue(typ, val, key, parent = '') {
@@ -171,10 +171,13 @@ function r(name) {
 }
 
 const typeMap = {
-    "TopLevel": o([
-        { json: "one", js: "one", typ: u(undefined, 0) },
+    "PurpleTopLevel": o([
+        { json: "one", js: "one", typ: 0 },
+        { json: "two", js: "two", typ: true },
+    ], "any"),
+    "FluffyTopLevel": o([
+        { json: "three", js: "three", typ: 3.14 },
         { json: "two", js: "two", typ: true },
-        { json: "three", js: "three", typ: u(undefined, 3.14) },
     ], "any"),
 };
 
diff --git a/base/schema-javascript/test/inputs/schema/vega-lite.schema/default/TopLevel.js b/head/schema-javascript/test/inputs/schema/vega-lite.schema/default/TopLevel.js
index 06dcc21..d1d5adb 100644
--- a/base/schema-javascript/test/inputs/schema/vega-lite.schema/default/TopLevel.js
+++ b/head/schema-javascript/test/inputs/schema/vega-lite.schema/default/TopLevel.js
@@ -10,11 +10,11 @@
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 function toTopLevel(json) {
-    return cast(JSON.parse(json), r("TopLevel"));
+    return cast(JSON.parse(json), u(r("TopLevelFacetedUnitSpec"), r("TopLevelLayerSpec"), r("TopLevelFacetSpec"), r("TopLevelRepeatSpec"), r("TopLevelVConcatSpec"), r("TopLevelHConcatSpec")));
 }
 
 function topLevelToJson(value) {
-    return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    return JSON.stringify(uncast(value, u(r("TopLevelFacetedUnitSpec"), r("TopLevelLayerSpec"), r("TopLevelFacetSpec"), r("TopLevelRepeatSpec"), r("TopLevelVConcatSpec"), r("TopLevelHConcatSpec"))), null, 2);
 }
 
 function invalidValue(typ, val, key, parent = '') {
@@ -171,30 +171,23 @@ function r(name) {
 }
 
 const typeMap = {
-    "TopLevel": o([
+    "TopLevelFacetedUnitSpec": o([
         { json: "$schema", js: "$schema", typ: u(undefined, "") },
         { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
         { json: "background", js: "background", typ: u(undefined, "") },
         { json: "config", js: "config", typ: u(undefined, r("Config")) },
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
         { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("EncodingWithFacet")) },
+        { json: "encoding", js: "encoding", typ: r("EncodingWithFacet") },
         { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
+        { json: "mark", js: "mark", typ: u(r("MarkDef"), r("Mark")) },
         { json: "name", js: "name", typ: u(undefined, "") },
         { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
         { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
+        { json: "selection", js: "selection", typ: u(undefined, m(u(r("SingleSelection"), r("MultiSelection"), r("IntervalSelection")))) },
         { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
         { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "facet", js: "facet", typ: u(undefined, r("FacetMapping")) },
-        { json: "spec", js: "spec", typ: u(undefined, r("Spec")) },
-        { json: "repeat", js: "repeat", typ: u(undefined, r("Repeat")) },
-        { json: "vconcat", js: "vconcat", typ: u(undefined, a(r("Spec"))) },
-        { json: "hconcat", js: "hconcat", typ: u(undefined, a(r("Spec"))) },
     ], false),
     "AutoSizeParams": o([
         { json: "contains", js: "contains", typ: u(undefined, r("Contains")) },
@@ -453,23 +446,20 @@ const typeMap = {
         { json: "length", js: "length", typ: 3.14 },
     ], ""),
     "RangeConfig": o([
-        { json: "category", js: "category", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "diverging", js: "diverging", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "heatmap", js: "heatmap", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "ordinal", js: "ordinal", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
-        { json: "ramp", js: "ramp", typ: u(undefined, u(a(""), r("CategoryVGScheme"))) },
+        { json: "category", js: "category", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "diverging", js: "diverging", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "heatmap", js: "heatmap", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "ordinal", js: "ordinal", typ: u(undefined, u(a(""), r("VGScheme"))) },
+        { json: "ramp", js: "ramp", typ: u(undefined, u(a(""), r("VGScheme"))) },
         { json: "symbol", js: "symbol", typ: u(undefined, a("")) },
-    ], u(a(u(3.14, "")), r("RangeConfigValueVGScheme"))),
-    "CategoryVGScheme": o([
+    ], u(a(u(3.14, "")), r("VGScheme"), r("RangeConfigValueClass"))),
+    "VGScheme": o([
         { json: "count", js: "count", typ: u(undefined, 3.14) },
         { json: "extent", js: "extent", typ: u(undefined, a(3.14)) },
         { json: "scheme", js: "scheme", typ: "" },
     ], false),
-    "RangeConfigValueVGScheme": o([
-        { json: "count", js: "count", typ: u(undefined, 3.14) },
-        { json: "extent", js: "extent", typ: u(undefined, a(3.14)) },
-        { json: "scheme", js: "scheme", typ: u(undefined, "") },
-        { json: "step", js: "step", typ: u(undefined, 3.14) },
+    "RangeConfigValueClass": o([
+        { json: "step", js: "step", typ: 3.14 },
     ], false),
     "ScaleConfig": o([
         { json: "bandPaddingInner", js: "bandPaddingInner", typ: u(undefined, 3.14) },
@@ -498,7 +488,7 @@ const typeMap = {
         { json: "single", js: "single", typ: u(undefined, r("SingleSelectionConfig")) },
     ], false),
     "IntervalSelectionConfig": o([
-        { json: "bind", js: "bind", typ: u(undefined, r("BindEnum")) },
+        { json: "bind", js: "bind", typ: u(undefined, r("Bind")) },
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
@@ -527,7 +517,7 @@ const typeMap = {
         { json: "toggle", js: "toggle", typ: u(undefined, u(true, "")) },
     ], false),
     "SingleSelectionConfig": o([
-        { json: "bind", js: "bind", typ: u(undefined, m(r("VGBinding"))) },
+        { json: "bind", js: "bind", typ: u(undefined, m(u(r("VGCheckboxBinding"), r("VGRadioBinding"), r("VGSelectBinding"), r("VGRangeBinding"), r("VGGenericBinding")))) },
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
@@ -535,14 +525,31 @@ const typeMap = {
         { json: "on", js: "on", typ: u(undefined, "any") },
         { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
     ], false),
-    "VGBinding": o([
+    "VGCheckboxBinding": o([
         { json: "element", js: "element", typ: u(undefined, "") },
-        { json: "input", js: "input", typ: "" },
-        { json: "options", js: "options", typ: u(undefined, a("")) },
+        { json: "input", js: "input", typ: r("PurpleInput") },
+    ], false),
+    "VGRadioBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("FluffyInput") },
+        { json: "options", js: "options", typ: a("") },
+    ], false),
+    "VGSelectBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("TentacledInput") },
+        { json: "options", js: "options", typ: a("") },
+    ], false),
+    "VGRangeBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: r("StickyInput") },
         { json: "max", js: "max", typ: u(undefined, 3.14) },
         { json: "min", js: "min", typ: u(undefined, 3.14) },
         { json: "step", js: "step", typ: u(undefined, 3.14) },
     ], false),
+    "VGGenericBinding": o([
+        { json: "element", js: "element", typ: u(undefined, "") },
+        { json: "input", js: "input", typ: "" },
+    ], false),
     "VGMarkConfig": o([
         { json: "align", js: "align", typ: u(undefined, r("HorizontalAlign")) },
         { json: "angle", js: "angle", typ: u(undefined, 3.14) },
@@ -664,47 +671,60 @@ const typeMap = {
         { json: "strokeWidth", js: "strokeWidth", typ: u(undefined, 3.14) },
         { json: "width", js: "width", typ: u(undefined, 3.14) },
     ], false),
-    "Data": o([
-        { json: "format", js: "format", typ: u(undefined, r("DataFormat")) },
-        { json: "url", js: "url", typ: u(undefined, "") },
-        { json: "values", js: "values", typ: u(undefined, u(a(u(true, 3.14, m("any"), "")), m("any"), "")) },
-        { json: "name", js: "name", typ: u(undefined, "") },
+    "URLData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "url", js: "url", typ: "" },
+    ], false),
+    "CSVDataFormat": o([
+        { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
+        { json: "type", js: "type", typ: u(undefined, r("PurpleType")) },
     ], false),
-    "DataFormat": o([
+    "JSONDataFormat": o([
         { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
-        { json: "type", js: "type", typ: u(undefined, r("DataFormatType")) },
         { json: "property", js: "property", typ: u(undefined, "") },
+        { json: "type", js: "type", typ: u(undefined, r("FluffyType")) },
+    ], false),
+    "TopoDataFormat": o([
         { json: "feature", js: "feature", typ: u(undefined, "") },
         { json: "mesh", js: "mesh", typ: u(undefined, "") },
+        { json: "parse", js: "parse", typ: u(undefined, u(r("ParseEnum"), m("any"))) },
+        { json: "type", js: "type", typ: u(undefined, r("TentacledType")) },
+    ], false),
+    "InlineData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "values", js: "values", typ: u(a(u(true, 3.14, m("any"), "")), m("any"), "") },
+    ], false),
+    "NamedData": o([
+        { json: "format", js: "format", typ: u(undefined, u(r("CSVDataFormat"), r("JSONDataFormat"), r("TopoDataFormat"))) },
+        { json: "name", js: "name", typ: "" },
     ], false),
     "EncodingWithFacet": o([
-        { json: "color", js: "color", typ: u(undefined, r("MarkPropDefWithCondition")) },
+        { json: "color", js: "color", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
         { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
         { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
-        { json: "href", js: "href", typ: u(undefined, r("DefWithCondition")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("MarkPropDefWithCondition")) },
+        { json: "href", js: "href", typ: u(undefined, u(r("FieldDefWithCondition"), r("ValueDefWithCondition"))) },
+        { json: "opacity", js: "opacity", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
         { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
         { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "size", js: "size", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "text", js: "text", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "tooltip", js: "tooltip", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "x", js: "x", typ: u(undefined, r("XClass")) },
-        { json: "x2", js: "x2", typ: u(undefined, r("X2Class")) },
-        { json: "y", js: "y", typ: u(undefined, r("XClass")) },
-        { json: "y2", js: "y2", typ: u(undefined, r("X2Class")) },
-    ], false),
-    "MarkPropDefWithCondition": o([
+        { json: "shape", js: "shape", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "size", js: "size", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "text", js: "text", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "tooltip", js: "tooltip", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "x", js: "x", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "x2", js: "x2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+        { json: "y", js: "y", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "y2", js: "y2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+    ], false),
+    "MarkPropFieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateMarkPropFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
         { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "BinParams": o([
         { json: "base", js: "base", typ: u(undefined, 3.14) },
@@ -716,26 +736,23 @@ const typeMap = {
         { json: "step", js: "step", typ: u(undefined, 3.14) },
         { json: "steps", js: "steps", typ: u(undefined, a(3.14)) },
     ], false),
-    "ConditionalValueDef": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "ConditionalPredicateValueDef": o([
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
         { json: "value", js: "value", typ: u(true, 3.14, "") },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
-    ], false),
-    "Selection": o([
-        { json: "not", js: "not", typ: u(undefined, u(r("Selection"), "")) },
-        { json: "and", js: "and", typ: u(undefined, a(u(r("Selection"), ""))) },
-        { json: "or", js: "or", typ: u(undefined, a(u(r("Selection"), ""))) },
-    ], false),
-    "Predicate": o([
-        { json: "not", js: "not", typ: u(undefined, u(r("Predicate"), "")) },
-        { json: "and", js: "and", typ: u(undefined, a(u(r("Predicate"), ""))) },
-        { json: "or", js: "or", typ: u(undefined, a(u(r("Predicate"), ""))) },
-        { json: "equal", js: "equal", typ: u(undefined, u(true, r("DateTime"), 3.14, "")) },
-        { json: "field", js: "field", typ: u(undefined, "") },
+    ], false),
+    "LogicalOrPredicate": o([
+        { json: "or", js: "or", typ: a(u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "")) },
+    ], false),
+    "LogicalAndPredicate": o([
+        { json: "and", js: "and", typ: a(u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "")) },
+    ], false),
+    "LogicalNotPredicate": o([
+        { json: "not", js: "not", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+    ], false),
+    "FieldEqualPredicate": o([
+        { json: "equal", js: "equal", typ: u(true, r("DateTime"), 3.14, "") },
+        { json: "field", js: "field", typ: "" },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "range", js: "range", typ: u(undefined, a(u(r("DateTime"), 3.14, null))) },
-        { json: "oneOf", js: "oneOf", typ: u(undefined, a(u(true, r("DateTime"), 3.14, ""))) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
     ], false),
     "DateTime": o([
         { json: "date", js: "date", typ: u(undefined, 3.14) },
@@ -749,18 +766,31 @@ const typeMap = {
         { json: "utc", js: "utc", typ: u(undefined, true) },
         { json: "year", js: "year", typ: u(undefined, 3.14) },
     ], false),
-    "ConditionalPredicateMarkPropFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
-        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
-        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+    "FieldRangePredicate": o([
+        { json: "field", js: "field", typ: "" },
+        { json: "range", js: "range", typ: a(u(r("DateTime"), 3.14, null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+    ], false),
+    "FieldOneOfPredicate": o([
+        { json: "field", js: "field", typ: "" },
+        { json: "oneOf", js: "oneOf", typ: a(u(true, r("DateTime"), 3.14, "")) },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+    ], false),
+    "SelectionPredicate": o([
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+    ], false),
+    "SelectionOr": o([
+        { json: "or", js: "or", typ: a(u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "")) },
+    ], false),
+    "SelectionAnd": o([
+        { json: "and", js: "and", typ: a(u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "")) },
+    ], false),
+    "SelectionNot": o([
+        { json: "not", js: "not", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+    ], false),
+    "ConditionalSelectionValueDef": o([
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+        { json: "value", js: "value", typ: u(true, 3.14, "") },
     ], false),
     "RepeatRef": o([
         { json: "repeat", js: "repeat", typ: r("RepeatEnum") },
@@ -780,7 +810,7 @@ const typeMap = {
     "Scale": o([
         { json: "base", js: "base", typ: u(undefined, 3.14) },
         { json: "clamp", js: "clamp", typ: u(undefined, true) },
-        { json: "domain", js: "domain", typ: u(undefined, u(a(u(true, r("DateTime"), 3.14, "")), r("DomainClass"), r("Domain"))) },
+        { json: "domain", js: "domain", typ: u(undefined, u(a(u(true, r("DateTime"), 3.14, "")), r("PurpleSelectionDomain"), r("FluffySelectionDomain"), r("Domain"))) },
         { json: "exponent", js: "exponent", typ: u(undefined, 3.14) },
         { json: "interpolate", js: "interpolate", typ: u(undefined, u(r("InterpolateParams"), r("Interpolate"))) },
         { json: "nice", js: "nice", typ: u(undefined, u(true, r("NiceClass"), 3.14, r("NiceTime"))) },
@@ -794,10 +824,13 @@ const typeMap = {
         { json: "type", js: "type", typ: u(undefined, r("ScaleType")) },
         { json: "zero", js: "zero", typ: u(undefined, true) },
     ], false),
-    "DomainClass": o([
+    "PurpleSelectionDomain": o([
         { json: "field", js: "field", typ: u(undefined, "") },
         { json: "selection", js: "selection", typ: "" },
+    ], false),
+    "FluffySelectionDomain": o([
         { json: "encoding", js: "encoding", typ: u(undefined, "") },
+        { json: "selection", js: "selection", typ: "" },
     ], false),
     "InterpolateParams": o([
         { json: "gamma", js: "gamma", typ: u(undefined, 3.14) },
@@ -814,14 +847,40 @@ const typeMap = {
     "SortField": o([
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "op", js: "op", typ: r("AggregateOp") },
-        { json: "order", js: "order", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "order", js: "order", typ: u(undefined, u(r("SortOrderEnum"), null)) },
+    ], false),
+    "MarkPropValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateMarkPropFieldDef"), r("ConditionalSelectionMarkPropFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
+        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+    ], false),
+    "ConditionalPredicateMarkPropFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
+        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionMarkPropFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "legend", js: "legend", typ: u(undefined, u(r("Legend"), null)) },
+        { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "FacetFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "header", js: "header", typ: u(undefined, r("Header")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
@@ -837,65 +896,83 @@ const typeMap = {
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "DefWithCondition": o([
+    "FieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "ConditionalPredicateFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "ValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateFieldDef"), r("ConditionalSelectionFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
+    ], false),
+    "ConditionalPredicateFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "OrderFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortOrderEnum"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
         { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "TextDefWithCondition": o([
+    "TextFieldDefWithCondition": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "condition", js: "condition", typ: u(undefined, u(a(r("ConditionalValueDef")), r("ConditionalPredicateTextFieldDefClass"))) },
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "format", js: "format", typ: u(undefined, "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "ConditionalPredicateTextFieldDefClass": o([
-        { json: "test", js: "test", typ: u(undefined, u(r("Predicate"), "")) },
+    "TextValueDefWithCondition": o([
+        { json: "condition", js: "condition", typ: u(undefined, u(a(u(r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))), r("ConditionalPredicateTextFieldDef"), r("ConditionalSelectionTextFieldDef"), r("ConditionalPredicateValueDef"), r("ConditionalSelectionValueDef"))) },
         { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-        { json: "selection", js: "selection", typ: u(undefined, u(r("Selection"), "")) },
+    ], false),
+    "ConditionalPredicateTextFieldDef": o([
+        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
+        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
+        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
+        { json: "format", js: "format", typ: u(undefined, "") },
+        { json: "test", js: "test", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
+        { json: "type", js: "type", typ: r("Type") },
+    ], false),
+    "ConditionalSelectionTextFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "format", js: "format", typ: u(undefined, "") },
+        { json: "selection", js: "selection", typ: u(r("SelectionNot"), r("SelectionAnd"), r("SelectionOr"), "") },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
-    "XClass": o([
+    "PositionFieldDef": o([
         { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
         { json: "axis", js: "axis", typ: u(undefined, u(r("Axis"), null)) },
         { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
         { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
         { json: "scale", js: "scale", typ: u(undefined, r("Scale")) },
-        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortEnum"), null)) },
+        { json: "sort", js: "sort", typ: u(undefined, u(r("SortField"), r("SortOrderEnum"), null)) },
         { json: "stack", js: "stack", typ: u(undefined, u(r("StackOffset"), null)) },
         { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
+        { json: "type", js: "type", typ: r("Type") },
     ], false),
     "Axis": o([
         { json: "domain", js: "domain", typ: u(undefined, true) },
@@ -921,67 +998,8 @@ const typeMap = {
         { json: "values", js: "values", typ: u(undefined, a(u(r("DateTime"), 3.14))) },
         { json: "zindex", js: "zindex", typ: u(undefined, 3.14) },
     ], false),
-    "X2Class": o([
-        { json: "aggregate", js: "aggregate", typ: u(undefined, r("AggregateOp")) },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, u(r("RepeatRef"), "")) },
-        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "type", js: "type", typ: u(undefined, r("Type")) },
-        { json: "value", js: "value", typ: u(undefined, u(true, 3.14, "")) },
-    ], false),
-    "FacetMapping": o([
-        { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
-        { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
-    ], false),
-    "Spec": o([
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
-        { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "name", js: "name", typ: u(undefined, "") },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
-        { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("Encoding")) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
-        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
-        { json: "facet", js: "facet", typ: u(undefined, r("FacetMapping")) },
-        { json: "spec", js: "spec", typ: u(undefined, r("Spec")) },
-        { json: "repeat", js: "repeat", typ: u(undefined, r("Repeat")) },
-        { json: "vconcat", js: "vconcat", typ: u(undefined, a(r("Spec"))) },
-        { json: "hconcat", js: "hconcat", typ: u(undefined, a(r("Spec"))) },
-    ], false),
-    "Encoding": o([
-        { json: "color", js: "color", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
-        { json: "href", js: "href", typ: u(undefined, r("DefWithCondition")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
-        { json: "shape", js: "shape", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "size", js: "size", typ: u(undefined, r("MarkPropDefWithCondition")) },
-        { json: "text", js: "text", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "tooltip", js: "tooltip", typ: u(undefined, r("TextDefWithCondition")) },
-        { json: "x", js: "x", typ: u(undefined, r("XClass")) },
-        { json: "x2", js: "x2", typ: u(undefined, r("X2Class")) },
-        { json: "y", js: "y", typ: u(undefined, r("XClass")) },
-        { json: "y2", js: "y2", typ: u(undefined, r("X2Class")) },
-    ], false),
-    "LayerSpec": o([
-        { json: "data", js: "data", typ: u(undefined, r("Data")) },
-        { json: "description", js: "description", typ: u(undefined, "") },
-        { json: "height", js: "height", typ: u(undefined, 3.14) },
-        { json: "layer", js: "layer", typ: u(undefined, a(r("LayerSpec"))) },
-        { json: "name", js: "name", typ: u(undefined, "") },
-        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
-        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
-        { json: "transform", js: "transform", typ: u(undefined, a(r("Transform"))) },
-        { json: "width", js: "width", typ: u(undefined, 3.14) },
-        { json: "encoding", js: "encoding", typ: u(undefined, r("Encoding")) },
-        { json: "mark", js: "mark", typ: u(undefined, u(r("MarkDef"), r("Mark"))) },
-        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
-        { json: "selection", js: "selection", typ: u(undefined, m(r("SelectionDef"))) },
+    "ValueDef": o([
+        { json: "value", js: "value", typ: u(true, 3.14, "") },
     ], false),
     "MarkDef": o([
         { json: "align", js: "align", typ: u(undefined, r("HorizontalAlign")) },
@@ -1038,41 +1056,36 @@ const typeMap = {
     "FluffyPrecision": o([
         { json: "length", js: "length", typ: 3.14 },
     ], ""),
-    "Resolve": o([
-        { json: "axis", js: "axis", typ: u(undefined, r("AxisResolveMap")) },
-        { json: "legend", js: "legend", typ: u(undefined, r("LegendResolveMap")) },
-        { json: "scale", js: "scale", typ: u(undefined, r("ScaleResolveMap")) },
-    ], false),
-    "AxisResolveMap": o([
-        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
-        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
-    ], false),
-    "LegendResolveMap": o([
-        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
-        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
-    ], false),
-    "ScaleResolveMap": o([
-        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
-        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
-        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
-        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
-        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
-        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    "SingleSelection": o([
+        { json: "bind", js: "bind", typ: u(undefined, m(u(r("VGCheckboxBinding"), r("VGRadioBinding"), r("VGSelectBinding"), r("VGRangeBinding"), r("VGGenericBinding")))) },
+        { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
+        { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
+        { json: "nearest", js: "nearest", typ: u(undefined, true) },
+        { json: "on", js: "on", typ: u(undefined, "any") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
+        { json: "type", js: "type", typ: r("StickyType") },
     ], false),
-    "SelectionDef": o([
-        { json: "bind", js: "bind", typ: u(undefined, u(r("BindEnum"), m(r("VGBinding")))) },
+    "MultiSelection": o([
         { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
         { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
         { json: "fields", js: "fields", typ: u(undefined, a("")) },
         { json: "nearest", js: "nearest", typ: u(undefined, true) },
         { json: "on", js: "on", typ: u(undefined, "any") },
         { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
-        { json: "type", js: "type", typ: r("SelectionDefType") },
         { json: "toggle", js: "toggle", typ: u(undefined, u(true, "")) },
+        { json: "type", js: "type", typ: r("IndigoType") },
+    ], false),
+    "IntervalSelection": o([
+        { json: "bind", js: "bind", typ: u(undefined, r("Bind")) },
+        { json: "empty", js: "empty", typ: u(undefined, r("Empty")) },
+        { json: "encodings", js: "encodings", typ: u(undefined, a(r("SingleDefChannel"))) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
         { json: "mark", js: "mark", typ: u(undefined, r("BrushConfig")) },
+        { json: "on", js: "on", typ: u(undefined, "any") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("SelectionResolution")) },
         { json: "translate", js: "translate", typ: u(undefined, u(true, "")) },
+        { json: "type", js: "type", typ: r("IndecentType") },
         { json: "zoom", js: "zoom", typ: u(undefined, u(true, "")) },
     ], false),
     "TitleParams": o([
@@ -1082,17 +1095,36 @@ const typeMap = {
         { json: "style", js: "style", typ: u(undefined, u(a(""), "")) },
         { json: "text", js: "text", typ: "" },
     ], false),
-    "Transform": o([
-        { json: "filter", js: "filter", typ: u(undefined, u(r("Predicate"), "")) },
+    "FilterTransform": o([
+        { json: "filter", js: "filter", typ: u(r("LogicalNotPredicate"), r("LogicalAndPredicate"), r("LogicalOrPredicate"), r("FieldEqualPredicate"), r("FieldRangePredicate"), r("FieldOneOfPredicate"), r("SelectionPredicate"), "") },
+    ], false),
+    "CalculateTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "calculate", js: "calculate", typ: "" },
+    ], false),
+    "LookupTransform": o([
         { json: "as", js: "as", typ: u(undefined, u(a(""), "")) },
-        { json: "calculate", js: "calculate", typ: u(undefined, "") },
         { json: "default", js: "default", typ: u(undefined, "") },
-        { json: "from", js: "from", typ: u(undefined, r("LookupData")) },
-        { json: "lookup", js: "lookup", typ: u(undefined, "") },
-        { json: "bin", js: "bin", typ: u(undefined, u(true, r("BinParams"))) },
-        { json: "field", js: "field", typ: u(undefined, "") },
-        { json: "timeUnit", js: "timeUnit", typ: u(undefined, r("TimeUnit")) },
-        { json: "aggregate", js: "aggregate", typ: u(undefined, a(r("AggregatedFieldDef"))) },
+        { json: "from", js: "from", typ: r("LookupData") },
+        { json: "lookup", js: "lookup", typ: "" },
+    ], false),
+    "LookupData": o([
+        { json: "data", js: "data", typ: u(r("URLData"), r("InlineData"), r("NamedData")) },
+        { json: "fields", js: "fields", typ: u(undefined, a("")) },
+        { json: "key", js: "key", typ: "" },
+    ], false),
+    "BinTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "bin", js: "bin", typ: u(true, r("BinParams")) },
+        { json: "field", js: "field", typ: "" },
+    ], false),
+    "TimeUnitTransform": o([
+        { json: "as", js: "as", typ: "" },
+        { json: "field", js: "field", typ: "" },
+        { json: "timeUnit", js: "timeUnit", typ: r("TimeUnit") },
+    ], false),
+    "AggregateTransform": o([
+        { json: "aggregate", js: "aggregate", typ: a(r("AggregatedFieldDef")) },
         { json: "groupby", js: "groupby", typ: u(undefined, a("")) },
     ], false),
     "AggregatedFieldDef": o([
@@ -1100,15 +1132,188 @@ const typeMap = {
         { json: "field", js: "field", typ: "" },
         { json: "op", js: "op", typ: r("AggregateOp") },
     ], false),
-    "LookupData": o([
-        { json: "data", js: "data", typ: r("Data") },
-        { json: "fields", js: "fields", typ: u(undefined, a("")) },
-        { json: "key", js: "key", typ: "" },
+    "TopLevelLayerSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "layer", js: "layer", typ: a(u(r("LayerSpec"), r("CompositeUnitSpecAlias"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "LayerSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "layer", js: "layer", typ: a(u(r("LayerSpec"), r("CompositeUnitSpecAlias"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "Resolve": o([
+        { json: "axis", js: "axis", typ: u(undefined, r("AxisResolveMap")) },
+        { json: "legend", js: "legend", typ: u(undefined, r("LegendResolveMap")) },
+        { json: "scale", js: "scale", typ: u(undefined, r("ScaleResolveMap")) },
+    ], false),
+    "AxisResolveMap": o([
+        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
+        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "LegendResolveMap": o([
+        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
+        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
+        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
+        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "ScaleResolveMap": o([
+        { json: "color", js: "color", typ: u(undefined, r("ResolveMode")) },
+        { json: "opacity", js: "opacity", typ: u(undefined, r("ResolveMode")) },
+        { json: "shape", js: "shape", typ: u(undefined, r("ResolveMode")) },
+        { json: "size", js: "size", typ: u(undefined, r("ResolveMode")) },
+        { json: "x", js: "x", typ: u(undefined, r("ResolveMode")) },
+        { json: "y", js: "y", typ: u(undefined, r("ResolveMode")) },
+    ], false),
+    "CompositeUnitSpecAlias": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "encoding", js: "encoding", typ: r("Encoding") },
+        { json: "height", js: "height", typ: u(undefined, 3.14) },
+        { json: "mark", js: "mark", typ: u(r("MarkDef"), r("Mark")) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "projection", js: "projection", typ: u(undefined, r("Projection")) },
+        { json: "selection", js: "selection", typ: u(undefined, m(u(r("SingleSelection"), r("MultiSelection"), r("IntervalSelection")))) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "width", js: "width", typ: u(undefined, 3.14) },
+    ], false),
+    "Encoding": o([
+        { json: "color", js: "color", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "detail", js: "detail", typ: u(undefined, u(a(r("FieldDef")), r("FieldDef"))) },
+        { json: "href", js: "href", typ: u(undefined, u(r("FieldDefWithCondition"), r("ValueDefWithCondition"))) },
+        { json: "opacity", js: "opacity", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "order", js: "order", typ: u(undefined, u(a(r("OrderFieldDef")), r("OrderFieldDef"))) },
+        { json: "shape", js: "shape", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "size", js: "size", typ: u(undefined, u(r("MarkPropFieldDefWithCondition"), r("MarkPropValueDefWithCondition"))) },
+        { json: "text", js: "text", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "tooltip", js: "tooltip", typ: u(undefined, u(r("TextFieldDefWithCondition"), r("TextValueDefWithCondition"))) },
+        { json: "x", js: "x", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "x2", js: "x2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+        { json: "y", js: "y", typ: u(undefined, u(r("PositionFieldDef"), r("ValueDef"))) },
+        { json: "y2", js: "y2", typ: u(undefined, u(r("FieldDef"), r("ValueDef"))) },
+    ], false),
+    "TopLevelFacetSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "facet", js: "facet", typ: r("FacetMapping") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("LayerSpec"), r("CompositeUnitSpecAlias")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "FacetMapping": o([
+        { json: "column", js: "column", typ: u(undefined, r("FacetFieldDef")) },
+        { json: "row", js: "row", typ: u(undefined, r("FacetFieldDef")) },
+    ], false),
+    "TopLevelRepeatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "repeat", js: "repeat", typ: r("Repeat") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
     ], false),
     "Repeat": o([
         { json: "column", js: "column", typ: u(undefined, a("")) },
         { json: "row", js: "row", typ: u(undefined, a("")) },
     ], false),
+    "HConcatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "hconcat", js: "hconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "VConcatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "vconcat", js: "vconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+    ], false),
+    "RepeatSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "repeat", js: "repeat", typ: r("Repeat") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "FacetSpec": o([
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "facet", js: "facet", typ: r("FacetMapping") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "spec", js: "spec", typ: u(r("LayerSpec"), r("CompositeUnitSpecAlias")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
+    "TopLevelVConcatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+        { json: "vconcat", js: "vconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+    ], false),
+    "TopLevelHConcatSpec": o([
+        { json: "$schema", js: "$schema", typ: u(undefined, "") },
+        { json: "autosize", js: "autosize", typ: u(undefined, u(r("AutoSizeParams"), r("AutosizeType"))) },
+        { json: "background", js: "background", typ: u(undefined, "") },
+        { json: "config", js: "config", typ: u(undefined, r("Config")) },
+        { json: "data", js: "data", typ: u(undefined, u(r("URLData"), r("InlineData"), r("NamedData"))) },
+        { json: "description", js: "description", typ: u(undefined, "") },
+        { json: "hconcat", js: "hconcat", typ: a(u(r("CompositeUnitSpecAlias"), r("LayerSpec"), r("FacetSpec"), r("RepeatSpec"), r("VConcatSpec"), r("HConcatSpec"))) },
+        { json: "name", js: "name", typ: u(undefined, "") },
+        { json: "padding", js: "padding", typ: u(undefined, u(r("PaddingClass"), 3.14)) },
+        { json: "resolve", js: "resolve", typ: u(undefined, r("Resolve")) },
+        { json: "title", js: "title", typ: u(undefined, u(r("TitleParams"), "")) },
+        { json: "transform", js: "transform", typ: u(undefined, a(u(r("FilterTransform"), r("CalculateTransform"), r("LookupTransform"), r("BinTransform"), r("TimeUnitTransform"), r("AggregateTransform")))) },
+    ], false),
     "Contains": [
         "content",
         "padding",
@@ -1229,7 +1434,7 @@ const typeMap = {
         "stereographic",
         "transverseMercator",
     ],
-    "BindEnum": [
+    "Bind": [
         "scales",
     ],
     "Empty": [
@@ -1256,6 +1461,18 @@ const typeMap = {
         "union",
         "intersect",
     ],
+    "PurpleInput": [
+        "checkbox",
+    ],
+    "FluffyInput": [
+        "radio",
+    ],
+    "TentacledInput": [
+        "select",
+    ],
+    "StickyInput": [
+        "range",
+    ],
     "StackOffset": [
         "zero",
         "center",
@@ -1275,10 +1492,14 @@ const typeMap = {
     "ParseEnum": [
         "auto",
     ],
-    "DataFormatType": [
+    "PurpleType": [
         "csv",
         "tsv",
+    ],
+    "FluffyType": [
         "json",
+    ],
+    "TentacledType": [
         "topojson",
     ],
     "AggregateOp": [
@@ -1389,7 +1610,7 @@ const typeMap = {
         "point",
         "band",
     ],
-    "SortEnum": [
+    "SortOrderEnum": [
         "ascending",
         "descending",
     ],
@@ -1415,15 +1636,19 @@ const typeMap = {
         "square",
         "geoshape",
     ],
-    "ResolveMode": [
-        "independent",
-        "shared",
-    ],
-    "SelectionDefType": [
+    "StickyType": [
         "single",
+    ],
+    "IndigoType": [
         "multi",
+    ],
+    "IndecentType": [
         "interval",
     ],
+    "ResolveMode": [
+        "independent",
+        "shared",
+    ],
 };
 
 module.exports = {
diff --git a/head/schema-kotlin/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt b/head/schema-kotlin/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
new file mode 100644
index 0000000..e7931c2
--- /dev/null
+++ b/head/schema-kotlin/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
@@ -0,0 +1,26 @@
+// To parse the JSON, install Klaxon and do:
+//
+//   val topLevel = TopLevel.fromJson(jsonString)
+
+package quicktype
+
+import com.beust.klaxon.*
+
+private val klaxon = Klaxon()
+
+data class TopLevel (
+    val items: List<Item>
+) {
+    public fun toJson() = klaxon.toJsonString(this)
+
+    companion object {
+        public fun fromJson(json: String) = klaxon.parse<TopLevel>(json)
+    }
+}
+
+data class Item (
+    val aa: String? = null,
+    val bb: String? = null,
+    val cc: String? = null,
+    val dd: String? = null
+)
diff --git a/head/schema-kotlin-jackson/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt b/head/schema-kotlin-jackson/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
new file mode 100644
index 0000000..6b0e62c
--- /dev/null
+++ b/head/schema-kotlin-jackson/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
@@ -0,0 +1,37 @@
+// To parse the JSON, install jackson-module-kotlin and do:
+//
+//   val topLevel = TopLevel.fromJson(jsonString)
+
+package quicktype
+
+import com.fasterxml.jackson.annotation.*
+import com.fasterxml.jackson.core.*
+import com.fasterxml.jackson.databind.*
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer
+import com.fasterxml.jackson.databind.module.SimpleModule
+import com.fasterxml.jackson.databind.node.*
+import com.fasterxml.jackson.databind.ser.std.StdSerializer
+import com.fasterxml.jackson.module.kotlin.*
+
+val mapper = jacksonObjectMapper().apply {
+    propertyNamingStrategy = PropertyNamingStrategy.LOWER_CAMEL_CASE
+    setSerializationInclusion(JsonInclude.Include.NON_NULL)
+}
+
+data class TopLevel (
+    @get:JsonProperty(required=true)@field:JsonProperty(required=true)
+    val items: List<Item>
+) {
+    fun toJson() = mapper.writeValueAsString(this)
+
+    companion object {
+        fun fromJson(json: String) = mapper.readValue<TopLevel>(json)
+    }
+}
+
+data class Item (
+    val aa: String? = null,
+    val bb: String? = null,
+    val cc: String? = null,
+    val dd: String? = null
+)
diff --git a/head/schema-kotlinx/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt b/head/schema-kotlinx/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
new file mode 100644
index 0000000..c81ad42
--- /dev/null
+++ b/head/schema-kotlinx/test/inputs/schema/one-of-objects.schema/default/TopLevel.kt
@@ -0,0 +1,24 @@
+// To parse the JSON, install kotlin's serialization plugin and do:
+//
+// val json     = Json { allowStructuredMapKeys = true }
+// val topLevel = json.parse(TopLevel.serializer(), jsonString)
+
+package quicktype
+
+import kotlinx.serialization.*
+import kotlinx.serialization.json.*
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.*
+
+@Serializable
+data class TopLevel (
+    val items: List<Item>
+)
+
+@Serializable
+data class Item (
+    val aa: String? = null,
+    val bb: String? = null,
+    val cc: String? = null,
+    val dd: String? = null
+)
diff --git a/head/schema-php/test/inputs/schema/one-of-objects.schema/default/TopLevel.php b/head/schema-php/test/inputs/schema/one-of-objects.schema/default/TopLevel.php
new file mode 100644
index 0000000..d2a7327
--- /dev/null
+++ b/head/schema-php/test/inputs/schema/one-of-objects.schema/default/TopLevel.php
@@ -0,0 +1,412 @@
+<?php
+declare(strict_types=1);
+
+// This is an autogenerated file:TopLevel
+
+class TopLevel {
+    private array $items; // json:items Required
+
+    /**
+     * @param array $items
+     */
+    public function __construct(array $items) {
+        $this->items = $items;
+    }
+
+    /**
+     * @param array $value
+     * @throws Exception
+     * @return array
+     */
+    public static function fromItems(array $value): array {
+        return  array_map(function ($value) {
+            return Item::from($value); /*class*/
+        }, $value);
+    }
+
+    /**
+     * @throws Exception
+     * @return array
+     */
+    public function toItems(): array {
+        if (TopLevel::validateItems($this->items))  {
+            return array_map(function ($value) {
+                return $value->to(); /*class*/
+            }, $this->items);
+        }
+        throw new Exception('never get to this TopLevel::items');
+    }
+
+    /**
+     * @param array
+     * @return bool
+     * @throws Exception
+     */
+    public static function validateItems(array $value): bool {
+        if (!is_array($value)) {
+            throw new Exception("Attribute Error:TopLevel::items");
+        }
+        array_walk($value, function($value_v) {
+            $value_v->validate();
+        });
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @return array
+     */
+    public function getItems(): array {
+        if (TopLevel::validateItems($this->items))  {
+            return $this->items;
+        }
+        throw new Exception('never get to getItems TopLevel::items');
+    }
+
+    /**
+     * @return array
+     */
+    public static function sampleItems(): array {
+        return  array(
+            Item::sample() /*31:*/
+        ); /* 31:items*/
+    }
+
+    /**
+     * @throws Exception
+     * @return bool
+     */
+    public function validate(): bool {
+        return TopLevel::validateItems($this->items);
+    }
+
+    /**
+     * @return stdClass
+     * @throws Exception
+     */
+    public function to(): stdClass  {
+        $out = new stdClass();
+        $out->{'items'} = $this->toItems();
+        return $out;
+    }
+
+    /**
+     * @param stdClass $obj
+     * @return TopLevel
+     * @throws Exception
+     */
+    public static function from(stdClass $obj): TopLevel {
+        return new TopLevel(
+         TopLevel::fromItems($obj->{'items'})
+        );
+    }
+
+    /**
+     * @return TopLevel
+     */
+    public static function sample(): TopLevel {
+        return new TopLevel(
+         TopLevel::sampleItems()
+        );
+    }
+}
+
+// This is an autogenerated file:Item
+
+class Item {
+    private ?string $aa; // json:aa Optional
+    private ?string $bb; // json:bb Optional
+    private ?string $cc; // json:cc Optional
+    private ?string $dd; // json:dd Optional
+
+    /**
+     * @param string|null $aa
+     * @param string|null $bb
+     * @param string|null $cc
+     * @param string|null $dd
+     */
+    public function __construct(?string $aa, ?string $bb, ?string $cc, ?string $dd) {
+        $this->aa = $aa;
+        $this->bb = $bb;
+        $this->cc = $cc;
+        $this->dd = $dd;
+    }
+
+    /**
+     * @param ?string $value
+     * @throws Exception
+     * @return ?string
+     */
+    public static function fromAa(?string $value): ?string {
+        if (!is_null($value)) {
+            return $value; /*string*/
+        } else {
+            return  null;
+        }
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function toAa(): ?string {
+        if (Item::validateAa($this->aa))  {
+            if (!is_null($this->aa)) {
+                return $this->aa; /*string*/
+            } else {
+                return  null;
+            }
+        }
+        throw new Exception('never get to this Item::aa');
+    }
+
+    /**
+     * @param string|null
+     * @return bool
+     * @throws Exception
+     */
+    public static function validateAa(?string $value): bool {
+        if (!is_null($value)) {
+        }
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function getAa(): ?string {
+        if (Item::validateAa($this->aa))  {
+            return $this->aa;
+        }
+        throw new Exception('never get to getAa Item::aa');
+    }
+
+    /**
+     * @return ?string
+     */
+    public static function sampleAa(): ?string {
+        return 'Item::aa::31'; /*31:aa*/
+    }
+
+    /**
+     * @param ?string $value
+     * @throws Exception
+     * @return ?string
+     */
+    public static function fromBb(?string $value): ?string {
+        if (!is_null($value)) {
+            return $value; /*string*/
+        } else {
+            return  null;
+        }
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function toBb(): ?string {
+        if (Item::validateBb($this->bb))  {
+            if (!is_null($this->bb)) {
+                return $this->bb; /*string*/
+            } else {
+                return  null;
+            }
+        }
+        throw new Exception('never get to this Item::bb');
+    }
+
+    /**
+     * @param string|null
+     * @return bool
+     * @throws Exception
+     */
+    public static function validateBb(?string $value): bool {
+        if (!is_null($value)) {
+        }
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function getBb(): ?string {
+        if (Item::validateBb($this->bb))  {
+            return $this->bb;
+        }
+        throw new Exception('never get to getBb Item::bb');
+    }
+
+    /**
+     * @return ?string
+     */
+    public static function sampleBb(): ?string {
+        return 'Item::bb::32'; /*32:bb*/
+    }
+
+    /**
+     * @param ?string $value
+     * @throws Exception
+     * @return ?string
+     */
+    public static function fromCc(?string $value): ?string {
+        if (!is_null($value)) {
+            return $value; /*string*/
+        } else {
+            return  null;
+        }
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function toCc(): ?string {
+        if (Item::validateCc($this->cc))  {
+            if (!is_null($this->cc)) {
+                return $this->cc; /*string*/
+            } else {
+                return  null;
+            }
+        }
+        throw new Exception('never get to this Item::cc');
+    }
+
+    /**
+     * @param string|null
+     * @return bool
+     * @throws Exception
+     */
+    public static function validateCc(?string $value): bool {
+        if (!is_null($value)) {
+        }
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function getCc(): ?string {
+        if (Item::validateCc($this->cc))  {
+            return $this->cc;
+        }
+        throw new Exception('never get to getCc Item::cc');
+    }
+
+    /**
+     * @return ?string
+     */
+    public static function sampleCc(): ?string {
+        return 'Item::cc::33'; /*33:cc*/
+    }
+
+    /**
+     * @param ?string $value
+     * @throws Exception
+     * @return ?string
+     */
+    public static function fromDD(?string $value): ?string {
+        if (!is_null($value)) {
+            return $value; /*string*/
+        } else {
+            return  null;
+        }
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function toDD(): ?string {
+        if (Item::validateDD($this->dd))  {
+            if (!is_null($this->dd)) {
+                return $this->dd; /*string*/
+            } else {
+                return  null;
+            }
+        }
+        throw new Exception('never get to this Item::dd');
+    }
+
+    /**
+     * @param string|null
+     * @return bool
+     * @throws Exception
+     */
+    public static function validateDD(?string $value): bool {
+        if (!is_null($value)) {
+        }
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @return ?string
+     */
+    public function getDD(): ?string {
+        if (Item::validateDD($this->dd))  {
+            return $this->dd;
+        }
+        throw new Exception('never get to getDD Item::dd');
+    }
+
+    /**
+     * @return ?string
+     */
+    public static function sampleDD(): ?string {
+        return 'Item::dd::34'; /*34:dd*/
+    }
+
+    /**
+     * @throws Exception
+     * @return bool
+     */
+    public function validate(): bool {
+        return Item::validateAa($this->aa)
+        || Item::validateBb($this->bb)
+        || Item::validateCc($this->cc)
+        || Item::validateDD($this->dd);
+    }
+
+    /**
+     * @return stdClass
+     * @throws Exception
+     */
+    public function to(): stdClass  {
+        $out = new stdClass();
+        $out->{'aa'} = $this->toAa();
+        $out->{'bb'} = $this->toBb();
+        $out->{'cc'} = $this->toCc();
+        $out->{'dd'} = $this->toDD();
+        return $out;
+    }
+
+    /**
+     * @param stdClass $obj
+     * @return Item
+     * @throws Exception
+     */
+    public static function from(stdClass $obj): Item {
+        return new Item(
+         Item::fromAa($obj->{'aa'})
+        ,Item::fromBb($obj->{'bb'})
+        ,Item::fromCc($obj->{'cc'})
+        ,Item::fromDD($obj->{'dd'})
+        );
+    }
+
+    /**
+     * @return Item
+     */
+    public static function sample(): Item {
+        return new Item(
+         Item::sampleAa()
+        ,Item::sampleBb()
+        ,Item::sampleCc()
+        ,Item::sampleDD()
+        );
+    }
+}
diff --git a/head/schema-pike/test/inputs/schema/one-of-objects.schema/default/TopLevel.pmod b/head/schema-pike/test/inputs/schema/one-of-objects.schema/default/TopLevel.pmod
new file mode 100644
index 0000000..161fba4
--- /dev/null
+++ b/head/schema-pike/test/inputs/schema/one-of-objects.schema/default/TopLevel.pmod
@@ -0,0 +1,62 @@
+// This source has been automatically generated by quicktype.
+// ( https://github.com/quicktype/quicktype )
+//
+// To use this code, simply import it into your project as a Pike module.
+// To JSON-encode your object, you can pass it to `Standards.JSON.encode`
+// or call `encode_json` on it.
+//
+// To decode a JSON string, first pass it to `Standards.JSON.decode`,
+// and then pass the result to `<YourClass>_from_JSON`.
+// It will return an instance of <YourClass>.
+// Bear in mind that these functions have unexpected behavior,
+// and will likely throw an error, if the JSON string does not
+// match the expected interface, even if the JSON itself is valid.
+
+class TopLevel {
+    array(Item) items; // json: "items"
+
+    string encode_json() {
+        mapping(string:mixed) json = ([
+            "items" : items,
+        ]);
+
+        return Standards.JSON.encode(json);
+    }
+}
+
+TopLevel TopLevel_from_JSON(mixed json) {
+    TopLevel retval = TopLevel();
+
+    retval.items = json["items"];
+
+    return retval;
+}
+
+class Item {
+    mixed|string aa; // json: "aa"
+    mixed|string bb; // json: "bb"
+    mixed|string cc; // json: "cc"
+    mixed|string dd; // json: "dd"
+
+    string encode_json() {
+        mapping(string:mixed) json = ([
+            "aa" : aa,
+            "bb" : bb,
+            "cc" : cc,
+            "dd" : dd,
+        ]);
+
+        return Standards.JSON.encode(json);
+    }
+}
+
+Item Item_from_JSON(mixed json) {
+    Item retval = Item();
+
+    retval.aa = json["aa"];
+    retval.bb = json["bb"];
+    retval.cc = json["cc"];
+    retval.dd = json["dd"];
+
+    return retval;
+}
diff --git a/head/schema-python/test/inputs/schema/one-of-objects.schema/default/quicktype.py b/head/schema-python/test/inputs/schema/one-of-objects.schema/default/quicktype.py
new file mode 100644
index 0000000..cb8acdb
--- /dev/null
+++ b/head/schema-python/test/inputs/schema/one-of-objects.schema/default/quicktype.py
@@ -0,0 +1,87 @@
+from dataclasses import dataclass
+from typing import Any, TypeVar, Callable, Type, cast
+
+
+T = TypeVar("T")
+
+
+def from_str(x: Any) -> str:
+    assert isinstance(x, str)
+    return x
+
+
+def from_none(x: Any) -> Any:
+    assert x is None
+    return x
+
+
+def from_union(fs, x):
+    for f in fs:
+        try:
+            return f(x)
+        except:
+            pass
+    assert False
+
+
+def from_list(f: Callable[[Any], T], x: Any) -> list[T]:
+    assert isinstance(x, list)
+    return [f(y) for y in x]
+
+
+def to_class(c: Type[T], x: Any) -> dict:
+    assert isinstance(x, c)
+    return cast(Any, x).to_dict()
+
+
+@dataclass
+class Item:
+    aa: str | None = None
+    bb: str | None = None
+    cc: str | None = None
+    dd: str | None = None
+
+    @staticmethod
+    def from_dict(obj: Any) -> 'Item':
+        assert isinstance(obj, dict)
+        aa = from_union([from_str, from_none], obj.get("aa"))
+        bb = from_union([from_str, from_none], obj.get("bb"))
+        cc = from_union([from_str, from_none], obj.get("cc"))
+        dd = from_union([from_str, from_none], obj.get("dd"))
+        return Item(aa, bb, cc, dd)
+
+    def to_dict(self) -> dict:
+        result: dict = {}
+        if self.aa is not None:
+            result["aa"] = from_union([from_str, from_none], self.aa)
+        if self.bb is not None:
+            result["bb"] = from_union([from_str, from_none], self.bb)
+        if self.cc is not None:
+            result["cc"] = from_union([from_str, from_none], self.cc)
+        if self.dd is not None:
+            result["dd"] = from_union([from_str, from_none], self.dd)
+        return result
+
+
+@dataclass
+class TopLevel:
+    items: list[Item]
+
+    @staticmethod
+    def from_dict(obj: Any) -> 'TopLevel':
+        assert isinstance(obj, dict)
+        items = from_list(Item.from_dict, obj.get("items"))
+        return TopLevel(items)
+
+    def to_dict(self) -> dict:
+        result: dict = {}
+        result["items"] = from_list(lambda x: to_class(Item, x), self.items)
+        return result
+
+
+def top_level_from_dict(s: Any) -> TopLevel:
+    return TopLevel.from_dict(s)
+
+
+def top_level_to_dict(x: TopLevel) -> Any:
+    return to_class(TopLevel, x)
diff --git a/head/schema-ruby/test/inputs/schema/one-of-objects.schema/default/TopLevel.rb b/head/schema-ruby/test/inputs/schema/one-of-objects.schema/default/TopLevel.rb
new file mode 100644
index 0000000..60228a7
--- /dev/null
+++ b/head/schema-ruby/test/inputs/schema/one-of-objects.schema/default/TopLevel.rb
@@ -0,0 +1,79 @@
+# This code may look unusually verbose for Ruby (and it is), but
+# it performs some subtle and complex validation of JSON data.
+#
+# To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:
+#
+#   top_level = TopLevel.from_json! "{…}"
+#   puts top_level.items.first.aa
+#
+# If from_json! succeeds, the value returned matches the schema.
+
+require 'json'
+require 'dry-types'
+require 'dry-struct'
+
+module Types
+  include Dry.Types(default: :nominal)
+
+  Hash   = Strict::Hash
+  String = Strict::String
+end
+
+class Item < Dry::Struct
+  attribute :aa, Types::String.optional
+  attribute :bb, Types::String.optional
+  attribute :cc, Types::String.optional
+  attribute :dd, Types::String.optional
+
+  def self.from_dynamic!(d)
+    d = Types::Hash[d]
+    new(
+      aa: d["aa"],
+      bb: d["bb"],
+      cc: d["cc"],
+      dd: d["dd"],
+    )
+  end
+
+  def self.from_json!(json)
+    from_dynamic!(JSON.parse(json))
+  end
+
+  def to_dynamic
+    {
+      "aa" => aa,
+      "bb" => bb,
+      "cc" => cc,
+      "dd" => dd,
+    }
+  end
+
+  def to_json(options = nil)
+    JSON.generate(to_dynamic, options)
+  end
+end
+
+class TopLevel < Dry::Struct
+  attribute :items, Types.Array(Item)
+
+  def self.from_dynamic!(d)
+    d = Types::Hash[d]
+    new(
+      items: d.fetch("items").map { |x| Item.from_dynamic!(x) },
+    )
+  end
+
+  def self.from_json!(json)
+    from_dynamic!(JSON.parse(json))
+  end
+
+  def to_dynamic
+    {
+      "items" => items.map { |x| x.to_dynamic },
+    }
+  end
+
+  def to_json(options = nil)
+    JSON.generate(to_dynamic, options)
+  end
+end
diff --git a/head/schema-rust/test/inputs/schema/one-of-objects.schema/default/module_under_test.rs b/head/schema-rust/test/inputs/schema/one-of-objects.schema/default/module_under_test.rs
new file mode 100644
index 0000000..15963eb
--- /dev/null
+++ b/head/schema-rust/test/inputs/schema/one-of-objects.schema/default/module_under_test.rs
@@ -0,0 +1,30 @@
+// Example code that deserializes and serializes the model.
+// extern crate serde;
+// #[macro_use]
+// extern crate serde_derive;
+// extern crate serde_json;
+//
+// use generated_module::TopLevel;
+//
+// fn main() {
+//     let json = r#"{"answer": 42}"#;
+//     let model: TopLevel = serde_json::from_str(&json).unwrap();
+// }
+
+use serde::{Serialize, Deserialize};
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct TopLevel {
+    pub items: Vec<Item>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct Item {
+    pub aa: Option<String>,
+
+    pub bb: Option<String>,
+
+    pub cc: Option<String>,
+
+    pub dd: Option<String>,
+}
diff --git a/head/schema-scala3/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala b/head/schema-scala3/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala
new file mode 100644
index 0000000..27f5ab5
--- /dev/null
+++ b/head/schema-scala3/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala
@@ -0,0 +1,19 @@
+package quicktype
+
+import io.circe.syntax._
+import io.circe._
+import cats.syntax.functor._
+
+// If a union has a null in, then we'll need this too... 
+type NullValue = None.type
+
+case class TopLevel (
+    val items : Seq[Item]
+) derives Encoder.AsObject, Decoder
+
+case class Item (
+    val aa : Option[String] = None,
+    val bb : Option[String] = None,
+    val cc : Option[String] = None,
+    val dd : Option[String] = None
+) derives Encoder.AsObject, Decoder
diff --git a/head/schema-scala3-upickle/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala b/head/schema-scala3-upickle/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala
new file mode 100644
index 0000000..e7fddbf
--- /dev/null
+++ b/head/schema-scala3-upickle/test/inputs/schema/one-of-objects.schema/default/TopLevel.scala
@@ -0,0 +1,77 @@
+package quicktype
+
+// Custom pickler so that missing keys and JSON nulls both read as None,
+// and None is left out when writing (upickle's default for Option is a
+// JSON array).
+object OptionPickler extends upickle.AttributeTagged:
+    import upickle.default.Writer
+    import upickle.default.Reader
+    override implicit def OptionWriter[T: Writer]: Writer[Option[T]] =
+        implicitly[Writer[T]].comap[Option[T]] {
+            case None => null.asInstanceOf[T]
+            case Some(x) => x
+        }
+
+    override implicit def OptionReader[T: Reader]: Reader[Option[T]] = {
+        new Reader.Delegate[Any, Option[T]](implicitly[Reader[T]].map(Some(_))){
+        override def visitNull(index: Int) = None
+        }
+    }
+end OptionPickler
+
+// If a union has a null in, then we'll need this too...
+type NullValue = None.type
+given OptionPickler.ReadWriter[NullValue] = OptionPickler.readwriter[ujson.Value].bimap[NullValue](
+    _ => ujson.Null,
+    json => if json.isNull then None else throw new upickle.core.Abort("not null")
+)
+
+object JsonExt:
+    val valueReader = OptionPickler.readwriter[ujson.Value]
+
+    // upickle's built-in primitive readers are lenient -- the numeric and
+    // boolean readers accept strings, and the string reader accepts
+    // numbers and booleans -- so untagged unions need strict readers to
+    // pick the right member.
+    val strictString: OptionPickler.Reader[String] = valueReader.map {
+        case ujson.Str(s) => s
+        case json => throw new upickle.core.Abort("expected string, got " + json)
+    }
+    val strictLong: OptionPickler.Reader[Long] = valueReader.map {
+        case ujson.Num(n) if n.isWhole => n.toLong
+        case json => throw new upickle.core.Abort("expected integer, got " + json)
+    }
+    val strictDouble: OptionPickler.Reader[Double] = valueReader.map {
+        case ujson.Num(n) => n
+        case json => throw new upickle.core.Abort("expected number, got " + json)
+    }
+    val strictBoolean: OptionPickler.Reader[Boolean] = valueReader.map {
+        case ujson.Bool(b) => b
+        case json => throw new upickle.core.Abort("expected boolean, got " + json)
+    }
+
+    def badMerge[T](r1: => OptionPickler.Reader[?], rest: OptionPickler.Reader[?]*): OptionPickler.Reader[T] = valueReader.map { json =>
+        var t: T | Null = null
+        val stack       = Vector.newBuilder[Throwable]
+        (r1 +: rest).foreach { reader =>
+            if t == null then
+            try
+                t = OptionPickler.read[T](json, trace = true)(using reader.asInstanceOf[OptionPickler.Reader[T]])
+            catch
+                case exc => stack += exc
+        }
+        if t != null then t.nn else throw new Exception(json.toString(), stack.result().headOption.getOrElse(null))
+    }
+end JsonExt
+
+
+case class TopLevel (
+    val items : Seq[Item]
+) derives OptionPickler.ReadWriter
+
+case class Item (
+    val aa : Option[String] = None,
+    val bb : Option[String] = None,
+    val cc : Option[String] = None,
+    val dd : Option[String] = None
+) derives OptionPickler.ReadWriter
diff --git a/base/schema-schema/test/inputs/schema/class-map-union.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/class-map-union.schema/default/TopLevel.schema
index adf2b6e..47c14fd 100644
--- a/base/schema-schema/test/inputs/schema/class-map-union.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/class-map-union.schema/default/TopLevel.schema
@@ -13,23 +13,29 @@
             "required": [],
             "title": "TopLevel"
         },
-        "TopLevelUnion": {
+        "PurpleUnion": {
             "type": "object",
-            "additionalProperties": {
-                "$ref": "#/definitions/UnionValue"
-            },
+            "additionalProperties": false,
             "properties": {
                 "foo": {
-                    "$ref": "#/definitions/Foo"
-                },
+                    "type": "number"
+                }
+            },
+            "required": [],
+            "title": "PurpleUnion"
+        },
+        "FluffyUnion": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
                 "bar": {
-                    "$ref": "#/definitions/Bar"
+                    "type": "string"
                 }
             },
             "required": [],
-            "title": "TopLevelUnion"
+            "title": "FluffyUnion"
         },
-        "BarObject": {
+        "UnionValue": {
             "type": "object",
             "additionalProperties": {},
             "properties": {
@@ -38,46 +44,30 @@
                 }
             },
             "required": [],
-            "title": "BarObject"
-        },
-        "Bar": {
-            "anyOf": [
-                {
-                    "type": "boolean"
-                },
-                {
-                    "$ref": "#/definitions/BarObject"
-                },
-                {
-                    "type": "string"
-                }
-            ],
-            "title": "Bar"
+            "title": "UnionValue"
         },
-        "Foo": {
+        "TopLevelUnion": {
             "anyOf": [
                 {
-                    "type": "boolean"
+                    "$ref": "#/definitions/PurpleUnion"
                 },
                 {
-                    "type": "number"
+                    "$ref": "#/definitions/FluffyUnion"
                 },
                 {
-                    "$ref": "#/definitions/BarObject"
-                }
-            ],
-            "title": "Foo"
-        },
-        "UnionValue": {
-            "anyOf": [
-                {
-                    "type": "boolean"
+                    "type": "object",
+                    "additionalProperties": {
+                        "type": "boolean"
+                    }
                 },
                 {
-                    "$ref": "#/definitions/BarObject"
+                    "type": "object",
+                    "additionalProperties": {
+                        "$ref": "#/definitions/UnionValue"
+                    }
                 }
             ],
-            "title": "UnionValue"
+            "title": "TopLevelUnion"
         }
     }
 }
diff --git a/base/schema-schema/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.schema
index 624e1db..270354d 100644
--- a/base/schema-schema/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.schema
@@ -18,24 +18,61 @@
             ],
             "title": "TopLevel"
         },
-        "Item": {
+        "Message": {
             "type": "object",
             "additionalProperties": {},
             "properties": {
                 "content": {
                     "type": "string"
-                },
+                }
+            },
+            "required": [
+                "content"
+            ],
+            "title": "Message"
+        },
+        "FunctionOutput": {
+            "type": "object",
+            "additionalProperties": {},
+            "properties": {
                 "id": {
                     "type": "string"
                 },
                 "output": {
                     "type": "string"
-                },
+                }
+            },
+            "required": [
+                "id",
+                "output"
+            ],
+            "title": "FunctionOutput"
+        },
+        "ReasoningItem": {
+            "type": "object",
+            "additionalProperties": {},
+            "properties": {
                 "summary": {
                     "type": "string"
                 }
             },
-            "required": [],
+            "required": [
+                "summary"
+            ],
+            "title": "ReasoningItem"
+        },
+        "Item": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/Message"
+                },
+                {
+                    "$ref": "#/definitions/FunctionOutput"
+                },
+                {
+                    "$ref": "#/definitions/ReasoningItem"
+                }
+            ],
             "title": "Item"
         }
     }
diff --git a/base/schema-schema/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.schema
index 8258c0d..6903fd1 100644
--- a/base/schema-schema/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.schema
@@ -2,7 +2,31 @@
     "$schema": "http://json-schema.org/draft-06/schema#",
     "$ref": "#/definitions/TopLevel",
     "definitions": {
-        "TopLevel": {
+        "One": {
+            "type": "object",
+            "additionalProperties": {},
+            "properties": {
+                "b": {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        },
+                        {
+                            "type": "string"
+                        }
+                    ]
+                },
+                "kind": {
+                    "$ref": "#/definitions/PurpleKind"
+                }
+            },
+            "required": [
+                "b",
+                "kind"
+            ],
+            "title": "One"
+        },
+        "Two": {
             "type": "object",
             "additionalProperties": {},
             "properties": {
@@ -17,21 +41,38 @@
                     ]
                 },
                 "kind": {
-                    "$ref": "#/definitions/Kind"
+                    "$ref": "#/definitions/FluffyKind"
                 }
             },
             "required": [
                 "kind"
             ],
+            "title": "Two"
+        },
+        "TopLevel": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/One"
+                },
+                {
+                    "$ref": "#/definitions/Two"
+                }
+            ],
             "title": "TopLevel"
         },
-        "Kind": {
+        "PurpleKind": {
+            "type": "string",
+            "enum": [
+                "one"
+            ],
+            "title": "PurpleKind"
+        },
+        "FluffyKind": {
             "type": "string",
             "enum": [
-                "one",
                 "two"
             ],
-            "title": "Kind"
+            "title": "FluffyKind"
         }
     }
 }
diff --git a/head/schema-schema/test/inputs/schema/one-of-objects.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/one-of-objects.schema/default/TopLevel.schema
new file mode 100644
index 0000000..b0cae6f
--- /dev/null
+++ b/head/schema-schema/test/inputs/schema/one-of-objects.schema/default/TopLevel.schema
@@ -0,0 +1,61 @@
+{
+    "$schema": "http://json-schema.org/draft-06/schema#",
+    "$ref": "#/definitions/TopLevel",
+    "definitions": {
+        "TopLevel": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "items": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/ItemElement"
+                    }
+                }
+            },
+            "required": [
+                "items"
+            ],
+            "title": "TopLevel"
+        },
+        "PurpleItem": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aa": {
+                    "type": "string"
+                },
+                "bb": {
+                    "type": "string"
+                }
+            },
+            "required": [],
+            "title": "PurpleItem"
+        },
+        "FluffyItem": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "cc": {
+                    "type": "string"
+                },
+                "dd": {
+                    "type": "string"
+                }
+            },
+            "required": [],
+            "title": "FluffyItem"
+        },
+        "ItemElement": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/PurpleItem"
+                },
+                {
+                    "$ref": "#/definitions/FluffyItem"
+                }
+            ],
+            "title": "ItemElement"
+        }
+    }
+}
diff --git a/base/schema-schema/test/inputs/schema/postman-collection.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/postman-collection.schema/default/TopLevel.schema
index ee371f3..5c72e3a 100644
--- a/base/schema-schema/test/inputs/schema/postman-collection.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/postman-collection.schema/default/TopLevel.schema
@@ -2,7 +2,7 @@
     "$schema": "http://json-schema.org/draft-06/schema#",
     "$ref": "#/definitions/TopLevel",
     "definitions": {
-        "TopLevel": {
+        "Group": {
             "type": "object",
             "additionalProperties": {},
             "properties": {
@@ -11,7 +11,15 @@
                     "items": {
                         "$ref": "#/definitions/TopLevel"
                     }
-                },
+                }
+            },
+            "required": [],
+            "title": "Group"
+        },
+        "Item": {
+            "type": "object",
+            "additionalProperties": {},
+            "properties": {
                 "name": {
                     "type": "string"
                 },
@@ -23,8 +31,7 @@
                 }
             },
             "required": [],
-            "title": "TopLevel",
-            "description": "Postman collection"
+            "title": "Item"
         },
         "Response": {
             "type": "object",
@@ -36,6 +43,18 @@
             },
             "required": [],
             "title": "Response"
+        },
+        "TopLevel": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/Group"
+                },
+                {
+                    "$ref": "#/definitions/Item"
+                }
+            ],
+            "title": "TopLevel",
+            "description": "Postman collection"
         }
     }
 }
diff --git a/base/schema-schema/test/inputs/schema/union.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/union.schema/default/TopLevel.schema
index a15e999..e95942f 100644
--- a/base/schema-schema/test/inputs/schema/union.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/union.schema/default/TopLevel.schema
@@ -5,7 +5,7 @@
         "$ref": "#/definitions/TopLevelElement"
     },
     "definitions": {
-        "TopLevelElement": {
+        "PurpleTopLevel": {
             "type": "object",
             "additionalProperties": {},
             "properties": {
@@ -14,14 +14,40 @@
                 },
                 "two": {
                     "type": "boolean"
-                },
+                }
+            },
+            "required": [
+                "one",
+                "two"
+            ],
+            "title": "PurpleTopLevel"
+        },
+        "FluffyTopLevel": {
+            "type": "object",
+            "additionalProperties": {},
+            "properties": {
                 "three": {
                     "type": "number"
+                },
+                "two": {
+                    "type": "boolean"
                 }
             },
             "required": [
+                "three",
                 "two"
             ],
+            "title": "FluffyTopLevel"
+        },
+        "TopLevelElement": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/PurpleTopLevel"
+                },
+                {
+                    "$ref": "#/definitions/FluffyTopLevel"
+                }
+            ],
             "title": "TopLevelElement"
         }
     }
diff --git a/base/schema-schema/test/inputs/schema/vega-lite.schema/default/TopLevel.schema b/head/schema-schema/test/inputs/schema/vega-lite.schema/default/TopLevel.schema
index acaeea5..d4a58c5 100644
--- a/base/schema-schema/test/inputs/schema/vega-lite.schema/default/TopLevel.schema
+++ b/head/schema-schema/test/inputs/schema/vega-lite.schema/default/TopLevel.schema
@@ -2,7 +2,7 @@
     "$schema": "http://json-schema.org/draft-06/schema#",
     "$ref": "#/definitions/TopLevel",
     "definitions": {
-        "TopLevel": {
+        "TopLevelFacetedUnitSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
@@ -75,725 +75,526 @@
                 "width": {
                     "type": "number",
                     "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
+                }
+            },
+            "required": [
+                "encoding",
+                "mark"
+            ],
+            "title": "TopLevelFacetedUnitSpec"
+        },
+        "TopLevelLayerSpec": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "$schema": {
+                    "type": "string",
+                    "description": "URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you\nhave a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.\nSetting the `$schema` property allows automatic validation and autocomplete in editors\nthat support JSON schema."
+                },
+                "autosize": {
+                    "$ref": "#/definitions/Autosize",
+                    "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
+                },
+                "background": {
+                    "type": "string",
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
+                },
+                "config": {
+                    "$ref": "#/definitions/Config",
+                    "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a\nspecification."
+                },
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
+                },
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
+                },
+                "height": {
+                    "type": "number",
+                    "description": "The height of a visualization.\n\n__Default value:__\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its y-channel has a\n[continuous scale](scale.html#continuous), the height will be the value of\n[`config.view.height`](spec.html#config).\n- For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the height is [determined by the range step, paddings, and the\ncardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the\n`rangeStep` is `null`, the height will be the value of\n[`config.view.height`](spec.html#config).\n- If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.\n\n__Note__: For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the height of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 },
                 "layer": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/LayerSpec"
+                        "$ref": "#/definitions/SpecElement"
                     },
                     "description": "Layer or single view specifications to be layered.\n\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as\nlayering facet specifications is not allowed."
                 },
-                "resolve": {
-                    "$ref": "#/definitions/Resolve",
-                    "description": "Scale, axis, and legend resolutions for layers.\n\nScale, axis, and legend resolutions for facets.\n\nScale and legend resolutions for repeated charts.\n\nScale, axis, and legend resolutions for vertically concatenated charts.\n\nScale, axis, and legend resolutions for horizontally concatenated charts."
-                },
-                "facet": {
-                    "$ref": "#/definitions/FacetMapping",
-                    "description": "An object that describes mappings between `row` and `column` channels and their field\ndefinitions."
+                "name": {
+                    "type": "string",
+                    "description": "Name of the visualization for later reference."
                 },
-                "spec": {
-                    "$ref": "#/definitions/Spec",
-                    "description": "A specification of the view that gets faceted."
+                "padding": {
+                    "$ref": "#/definitions/Padding",
+                    "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "repeat": {
-                    "$ref": "#/definitions/Repeat",
-                    "description": "An object that describes what fields should be repeated into views that are laid out as a\n`row` or `column`."
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for layers."
                 },
-                "vconcat": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/Spec"
-                    },
-                    "description": "A list of views that should be concatenated and put into a column."
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "hconcat": {
+                "transform": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/Spec"
+                        "$ref": "#/definitions/Transform"
                     },
-                    "description": "A list of views that should be concatenated and put into a row."
-                }
-            },
-            "required": [],
-            "title": "TopLevel"
-        },
-        "AutoSizeParams": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "contains": {
-                    "$ref": "#/definitions/Contains",
-                    "description": "Determines how size calculation should be performed, one of `\"content\"` or `\"padding\"`.\nThe default setting (`\"content\"`) interprets the width and height settings as the data\nrectangle (plotting) dimensions, to which padding is then added. In contrast, the\n`\"padding\"` setting includes the padding within the view size calculations, such that the\nwidth and height settings indicate the **total** intended size of the view.\n\n__Default value__: `\"content\"`"
-                },
-                "resize": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if autosize layout should be re-calculated on every view\nupdate.\n\n__Default value__: `false`"
+                    "description": "An array of data transformations such as filter and new field calculation."
                 },
-                "type": {
-                    "$ref": "#/definitions/AutosizeType",
-                    "description": "The sizing format type. One of `\"pad\"`, `\"fit\"` or `\"none\"`. See the [autosize\ntype](https://vega.github.io/vega-lite/docs/size.html#autosize) documentation for\ndescriptions of each.\n\n__Default value__: `\"pad\"`"
+                "width": {
+                    "type": "number",
+                    "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 }
             },
-            "required": [],
-            "title": "AutoSizeParams"
+            "required": [
+                "layer"
+            ],
+            "title": "TopLevelLayerSpec"
         },
-        "Config": {
+        "TopLevelFacetSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "area": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Area-Specific Config"
+                "$schema": {
+                    "type": "string",
+                    "description": "URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you\nhave a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.\nSetting the `$schema` property allows automatic validation and autocomplete in editors\nthat support JSON schema."
                 },
                 "autosize": {
                     "$ref": "#/definitions/Autosize",
                     "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
                 },
-                "axis": {
-                    "$ref": "#/definitions/AxisConfig",
-                    "description": "Axis configuration, which determines default properties for all `x` and `y`\n[axes](axis.html). For a full list of axis configuration options, please see the\n[corresponding section of the axis documentation](axis.html#config)."
-                },
-                "axisBand": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Specific axis config for axes with \"band\" scales."
+                "background": {
+                    "type": "string",
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
                 },
-                "axisBottom": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Specific axis config for x-axis along the bottom edge of the chart."
+                "config": {
+                    "$ref": "#/definitions/Config",
+                    "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a\nspecification."
                 },
-                "axisLeft": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Specific axis config for y-axis along the left edge of the chart."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "axisRight": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Specific axis config for y-axis along the right edge of the chart."
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "axisTop": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Specific axis config for x-axis along the top edge of the chart."
+                "facet": {
+                    "$ref": "#/definitions/FacetMapping",
+                    "description": "An object that describes mappings between `row` and `column` channels and their field\ndefinitions."
                 },
-                "axisX": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "X-axis specific config."
+                "name": {
+                    "type": "string",
+                    "description": "Name of the visualization for later reference."
                 },
-                "axisY": {
-                    "$ref": "#/definitions/VGAxisConfig",
-                    "description": "Y-axis specific config."
+                "padding": {
+                    "$ref": "#/definitions/Padding",
+                    "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "background": {
-                    "type": "string",
-                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for facets."
                 },
-                "bar": {
-                    "$ref": "#/definitions/BarConfig",
-                    "description": "Bar-Specific Config"
+                "spec": {
+                    "$ref": "#/definitions/SpecElement",
+                    "description": "A specification of the view that gets faceted."
                 },
-                "circle": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Circle-Specific Config"
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "countTitle": {
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
+                }
+            },
+            "required": [
+                "facet",
+                "spec"
+            ],
+            "title": "TopLevelFacetSpec"
+        },
+        "TopLevelRepeatSpec": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "$schema": {
                     "type": "string",
-                    "description": "Default axis and legend title for count fields.\n\n__Default value:__ `'Number of Records'`."
-                },
-                "fieldTitle": {
-                    "$ref": "#/definitions/FieldTitle",
-                    "description": "Defines how Vega-Lite generates title for fields.  There are three possible styles:\n\n- `\"verbal\"` (Default) - displays function in a verbal style (e.g., \"Sum of field\",\n\"Year-month of date\", \"field (binned)\").\n- `\"function\"` - displays function using parentheses and capitalized texts (e.g.,\n\"SUM(field)\", \"YEARMONTH(date)\", \"BIN(field)\").\n- `\"plain\"` - displays only the field name without functions (e.g., \"field\", \"date\",\n\"field\")."
+                    "description": "URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you\nhave a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.\nSetting the `$schema` property allows automatic validation and autocomplete in editors\nthat support JSON schema."
                 },
-                "geoshape": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Geoshape-Specific Config"
+                "autosize": {
+                    "$ref": "#/definitions/Autosize",
+                    "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
                 },
-                "invalidValues": {
-                    "$ref": "#/definitions/InvalidValues",
-                    "description": "Defines how Vega-Lite should handle invalid values (`null` and `NaN`).\n- If set to `\"filter\"` (default), all data items with null values are filtered.\n- If `null`, all data items are included. In this case, invalid values will be\ninterpreted as zeroes."
+                "background": {
+                    "type": "string",
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
                 },
-                "legend": {
-                    "$ref": "#/definitions/LegendConfig",
-                    "description": "Legend configuration, which determines default properties for all [legends](legend.html).\nFor a full list of legend configuration options, please see the [corresponding section of\nin the legend documentation](legend.html#config)."
+                "config": {
+                    "$ref": "#/definitions/Config",
+                    "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a\nspecification."
                 },
-                "line": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Line-Specific Config"
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "mark": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Mark Config"
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "numberFormat": {
+                "name": {
                     "type": "string",
-                    "description": "D3 Number format for axis labels and text tables. For example \"s\" for SI units. Use [D3's\nnumber format pattern](https://github.com/d3/d3-format#locale_format)."
+                    "description": "Name of the visualization for later reference."
                 },
                 "padding": {
                     "$ref": "#/definitions/Padding",
                     "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "point": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Point-Specific Config"
-                },
-                "projection": {
-                    "$ref": "#/definitions/ProjectionConfig",
-                    "description": "Projection configuration, which determines default properties for all\n[projections](projection.html). For a full list of projection configuration options,\nplease see the [corresponding section of the projection\ndocumentation](projection.html#config)."
-                },
-                "range": {
-                    "$ref": "#/definitions/RangeConfig",
-                    "description": "An object hash that defines default range arrays or schemes for using with scales.\nFor a full list of scale range configuration options, please see the [corresponding\nsection of the scale documentation](scale.html#config)."
-                },
-                "rect": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Rect-Specific Config"
+                "repeat": {
+                    "$ref": "#/definitions/Repeat",
+                    "description": "An object that describes what fields should be repeated into views that are laid out as a\n`row` or `column`."
                 },
-                "rule": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Rule-Specific Config"
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale and legend resolutions for repeated charts."
                 },
-                "scale": {
-                    "$ref": "#/definitions/ScaleConfig",
-                    "description": "Scale configuration determines default properties for all [scales](scale.html). For a\nfull list of scale configuration options, please see the [corresponding section of the\nscale documentation](scale.html#config)."
+                "spec": {
+                    "$ref": "#/definitions/Spec"
                 },
-                "selection": {
-                    "$ref": "#/definitions/SelectionConfig",
-                    "description": "An object hash for defining default properties for each type of selections."
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "square": {
-                    "$ref": "#/definitions/MarkConfig",
-                    "description": "Square-Specific Config"
-                },
-                "stack": {
-                    "$ref": "#/definitions/StackOffset",
-                    "description": "Default stack offset for stackable mark."
-                },
-                "style": {
-                    "type": "object",
-                    "additionalProperties": {
-                        "$ref": "#/definitions/VGMarkConfig"
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
                     },
-                    "description": "An object hash that defines key-value mappings to determine default properties for marks with a given [style](mark.html#mark-def).  The keys represent styles names; the value are valid [mark configuration objects](mark.html#config).  "
-                },
-                "text": {
-                    "$ref": "#/definitions/TextConfig",
-                    "description": "Text-Specific Config"
-                },
-                "tick": {
-                    "$ref": "#/definitions/TickConfig",
-                    "description": "Tick-Specific Config"
-                },
-                "timeFormat": {
-                    "type": "string",
-                    "description": "Default datetime format for axis and legend labels. The format can be set directly on\neach axis and legend. Use [D3's time format\npattern](https://github.com/d3/d3-time-format#locale_format).\n\n__Default value:__ `'%b %d, %Y'`."
-                },
-                "title": {
-                    "$ref": "#/definitions/VGTitleConfig",
-                    "description": "Title configuration, which determines default properties for all [titles](title.html).\nFor a full list of title configuration options, please see the [corresponding section of\nthe title documentation](title.html#config)."
-                },
-                "view": {
-                    "$ref": "#/definitions/ViewConfig",
-                    "description": "Default properties for [single view plots](spec.html#single)."
+                    "description": "An array of data transformations such as filter and new field calculation."
                 }
             },
-            "required": [],
-            "title": "Config",
-            "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a specification."
+            "required": [
+                "repeat",
+                "spec"
+            ],
+            "title": "TopLevelRepeatSpec"
         },
-        "MarkConfig": {
+        "TopLevelVConcatSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "align": {
-                    "$ref": "#/definitions/HorizontalAlign",
-                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
-                },
-                "angle": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 360,
-                    "description": "The rotation angle of the text, in degrees."
-                },
-                "baseline": {
-                    "$ref": "#/definitions/VerticalAlign",
-                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
-                },
-                "color": {
+                "$schema": {
                     "type": "string",
-                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
-                "cursor": {
-                    "$ref": "#/definitions/Cursor",
-                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
-                },
-                "dx": {
-                    "type": "number",
-                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                    "description": "URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you\nhave a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.\nSetting the `$schema` property allows automatic validation and autocomplete in editors\nthat support JSON schema."
                 },
-                "dy": {
-                    "type": "number",
-                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                "autosize": {
+                    "$ref": "#/definitions/Autosize",
+                    "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
                 },
-                "fill": {
+                "background": {
                     "type": "string",
-                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
                 },
-                "filled": {
-                    "type": "boolean",
-                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                "config": {
+                    "$ref": "#/definitions/Config",
+                    "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a\nspecification."
                 },
-                "fillOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "font": {
+                "description": {
                     "type": "string",
-                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
-                },
-                "fontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The font size, in pixels."
-                },
-                "fontStyle": {
-                    "$ref": "#/definitions/FontStyle",
-                    "description": "The font style (e.g., `\"italic\"`)."
-                },
-                "fontWeight": {
-                    "$ref": "#/definitions/FontWeightUnion",
-                    "description": "The font weight (e.g., `\"bold\"`)."
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "href": {
+                "name": {
                     "type": "string",
-                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
-                },
-                "interpolate": {
-                    "$ref": "#/definitions/Interpolate",
-                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
-                },
-                "limit": {
-                    "type": "number",
-                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
-                },
-                "opacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
-                },
-                "orient": {
-                    "$ref": "#/definitions/Orient",
-                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
-                },
-                "radius": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                    "description": "Name of the visualization for later reference."
                 },
-                "shape": {
-                    "type": "string",
-                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
+                "padding": {
+                    "$ref": "#/definitions/Padding",
+                    "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "size": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for vertically concatenated charts."
                 },
-                "stroke": {
-                    "type": "string",
-                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "strokeDash": {
+                "transform": {
                     "type": "array",
                     "items": {
-                        "type": "number"
+                        "$ref": "#/definitions/Transform"
                     },
-                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
-                },
-                "strokeDashOffset": {
-                    "type": "number",
-                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
-                },
-                "strokeOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
-                },
-                "strokeWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The stroke width, in pixels."
-                },
-                "tension": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
-                },
-                "text": {
-                    "type": "string",
-                    "description": "Placeholder text if the `text` channel is not specified"
+                    "description": "An array of data transformations such as filter and new field calculation."
                 },
-                "theta": {
-                    "type": "number",
-                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
+                "vconcat": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Spec"
+                    },
+                    "description": "A list of views that should be concatenated and put into a column."
                 }
             },
-            "required": [],
-            "title": "MarkConfig",
-            "description": "Area-Specific Config \nCircle-Specific Config \nGeoshape-Specific Config \nLine-Specific Config \nMark Config \nPoint-Specific Config \nRect-Specific Config \nRule-Specific Config \nSquare-Specific Config "
+            "required": [
+                "vconcat"
+            ],
+            "title": "TopLevelVConcatSpec"
         },
-        "AxisConfig": {
+        "TopLevelHConcatSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "bandPosition": {
-                    "type": "number",
-                    "description": "An interpolation fraction indicating where, for `band` scales, axis ticks should be\npositioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5`\nplaces ticks in the middle of their bands."
+                "$schema": {
+                    "type": "string",
+                    "description": "URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you\nhave a reason to change this, use `https://vega.github.io/schema/vega-lite/v2.json`.\nSetting the `$schema` property allows automatic validation and autocomplete in editors\nthat support JSON schema."
                 },
-                "domain": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
+                "autosize": {
+                    "$ref": "#/definitions/Autosize",
+                    "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
                 },
-                "domainColor": {
+                "background": {
                     "type": "string",
-                    "description": "Color of axis domain line.\n\n__Default value:__  (none, using Vega default)."
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
                 },
-                "domainWidth": {
-                    "type": "number",
-                    "description": "Stroke width of axis domain line\n\n__Default value:__  (none, using Vega default)."
+                "config": {
+                    "$ref": "#/definitions/Config",
+                    "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a\nspecification."
                 },
-                "grid": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "gridColor": {
+                "description": {
                     "type": "string",
-                    "description": "Color of gridlines."
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "gridDash": {
+                "hconcat": {
                     "type": "array",
                     "items": {
-                        "type": "number"
+                        "$ref": "#/definitions/Spec"
                     },
-                    "description": "The offset (in pixels) into which to begin drawing with the grid dash array."
+                    "description": "A list of views that should be concatenated and put into a row."
                 },
-                "gridOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity of grid (value between [0,1])\n\n__Default value:__ (`1` by default)"
+                "name": {
+                    "type": "string",
+                    "description": "Name of the visualization for later reference."
                 },
-                "gridWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The grid width, in pixels."
+                "padding": {
+                    "$ref": "#/definitions/Padding",
+                    "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "labelAngle": {
-                    "type": "number",
-                    "minimum": -360,
-                    "maximum": 360,
-                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for horizontally concatenated charts."
                 },
-                "labelBound": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "labelColor": {
-                    "type": "string",
-                    "description": "The color of the tick label, can be in hex color code or regular color name."
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
+                }
+            },
+            "required": [
+                "hconcat"
+            ],
+            "title": "TopLevelHConcatSpec"
+        },
+        "AutoSizeParams": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "contains": {
+                    "$ref": "#/definitions/Contains",
+                    "description": "Determines how size calculation should be performed, one of `\"content\"` or `\"padding\"`.\nThe default setting (`\"content\"`) interprets the width and height settings as the data\nrectangle (plotting) dimensions, to which padding is then added. In contrast, the\n`\"padding\"` setting includes the padding within the view size calculations, such that the\nwidth and height settings indicate the **total** intended size of the view.\n\n__Default value__: `\"content\"`"
                 },
-                "labelFlush": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
+                "resize": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if autosize layout should be re-calculated on every view\nupdate.\n\n__Default value__: `false`"
                 },
-                "labelFont": {
-                    "type": "string",
-                    "description": "The font of the tick label."
+                "type": {
+                    "$ref": "#/definitions/AutosizeType",
+                    "description": "The sizing format type. One of `\"pad\"`, `\"fit\"` or `\"none\"`. See the [autosize\ntype](https://vega.github.io/vega-lite/docs/size.html#autosize) documentation for\ndescriptions of each.\n\n__Default value__: `\"pad\"`"
+                }
+            },
+            "required": [],
+            "title": "AutoSizeParams"
+        },
+        "Config": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "area": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Area-Specific Config"
                 },
-                "labelFontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The font size of the label, in pixels."
+                "autosize": {
+                    "$ref": "#/definitions/Autosize",
+                    "description": "Sets how the visualization size should be determined. If a string, should be one of\n`\"pad\"`, `\"fit\"` or `\"none\"`.\nObject values can additionally specify parameters for content sizing and automatic\nresizing.\n`\"fit\"` is only supported for single and layered views that don't use `rangeStep`.\n\n__Default value__: `pad`"
                 },
-                "labelLimit": {
-                    "type": "number",
-                    "description": "Maximum allowed pixel width of axis tick labels."
+                "axis": {
+                    "$ref": "#/definitions/AxisConfig",
+                    "description": "Axis configuration, which determines default properties for all `x` and `y`\n[axes](axis.html). For a full list of axis configuration options, please see the\n[corresponding section of the axis documentation](axis.html#config)."
                 },
-                "labelOverlap": {
-                    "$ref": "#/definitions/LabelOverlapUnion",
-                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
+                "axisBand": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Specific axis config for axes with \"band\" scales."
                 },
-                "labelPadding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between axis and text labels."
+                "axisBottom": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Specific axis config for x-axis along the bottom edge of the chart."
                 },
-                "labels": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
+                "axisLeft": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Specific axis config for y-axis along the left edge of the chart."
                 },
-                "maxExtent": {
-                    "type": "number",
-                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
+                "axisRight": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Specific axis config for y-axis along the right edge of the chart."
                 },
-                "minExtent": {
-                    "type": "number",
-                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
+                "axisTop": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Specific axis config for x-axis along the top edge of the chart."
                 },
-                "shortTimeLabels": {
-                    "type": "boolean",
-                    "description": "Whether month names and weekday names should be abbreviated.\n\n__Default value:__  `false`"
+                "axisX": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "X-axis specific config."
                 },
-                "tickColor": {
+                "axisY": {
+                    "$ref": "#/definitions/VGAxisConfig",
+                    "description": "Y-axis specific config."
+                },
+                "background": {
                     "type": "string",
-                    "description": "The color of the axis's tick."
+                    "description": "CSS color property to use as the background of visualization.\n\n__Default value:__ none (transparent)"
                 },
-                "tickRound": {
-                    "type": "boolean",
-                    "description": "Boolean flag indicating if pixel position values should be rounded to the nearest integer."
+                "bar": {
+                    "$ref": "#/definitions/BarConfig",
+                    "description": "Bar-Specific Config"
                 },
-                "ticks": {
-                    "type": "boolean",
-                    "description": "Boolean value that determines whether the axis should include ticks."
+                "circle": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Circle-Specific Config"
                 },
-                "tickSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The size in pixels of axis ticks."
+                "countTitle": {
+                    "type": "string",
+                    "description": "Default axis and legend title for count fields.\n\n__Default value:__ `'Number of Records'`."
                 },
-                "tickWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The width, in pixels, of ticks."
+                "fieldTitle": {
+                    "$ref": "#/definitions/FieldTitle",
+                    "description": "Defines how Vega-Lite generates title for fields.  There are three possible styles:\n\n- `\"verbal\"` (Default) - displays function in a verbal style (e.g., \"Sum of field\",\n\"Year-month of date\", \"field (binned)\").\n- `\"function\"` - displays function using parentheses and capitalized texts (e.g.,\n\"SUM(field)\", \"YEARMONTH(date)\", \"BIN(field)\").\n- `\"plain\"` - displays only the field name without functions (e.g., \"field\", \"date\",\n\"field\")."
                 },
-                "titleAlign": {
-                    "type": "string",
-                    "description": "Horizontal text alignment of axis titles."
+                "geoshape": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Geoshape-Specific Config"
                 },
-                "titleAngle": {
-                    "type": "number",
-                    "description": "Angle in degrees of axis titles."
+                "invalidValues": {
+                    "$ref": "#/definitions/InvalidValues",
+                    "description": "Defines how Vega-Lite should handle invalid values (`null` and `NaN`).\n- If set to `\"filter\"` (default), all data items with null values are filtered.\n- If `null`, all data items are included. In this case, invalid values will be\ninterpreted as zeroes."
                 },
-                "titleBaseline": {
-                    "type": "string",
-                    "description": "Vertical text baseline for axis titles."
+                "legend": {
+                    "$ref": "#/definitions/LegendConfig",
+                    "description": "Legend configuration, which determines default properties for all [legends](legend.html).\nFor a full list of legend configuration options, please see the [corresponding section of\nin the legend documentation](legend.html#config)."
                 },
-                "titleColor": {
-                    "type": "string",
-                    "description": "Color of the title, can be in hex color code or regular color name."
+                "line": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Line-Specific Config"
                 },
-                "titleFont": {
+                "mark": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Mark Config"
+                },
+                "numberFormat": {
                     "type": "string",
-                    "description": "Font of the title. (e.g., `\"Helvetica Neue\"`)."
+                    "description": "D3 Number format for axis labels and text tables. For example \"s\" for SI units. Use [D3's\nnumber format pattern](https://github.com/d3/d3-format#locale_format)."
                 },
-                "titleFontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Font size of the title."
+                "padding": {
+                    "$ref": "#/definitions/Padding",
+                    "description": "The default visualization padding, in pixels, from the edge of the visualization canvas\nto the data rectangle.  If a number, specifies padding for all sides.\nIf an object, the value should have the format `{\"left\": 5, \"top\": 5, \"right\": 5,\n\"bottom\": 5}` to specify padding for each side of the visualization.\n\n__Default value__: `5`"
                 },
-                "titleFontWeight": {
-                    "$ref": "#/definitions/TitleFontWeight",
-                    "description": "Font weight of the title. (e.g., `\"bold\"`)."
+                "point": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Point-Specific Config"
                 },
-                "titleLimit": {
-                    "type": "number",
-                    "description": "Maximum allowed pixel width of axis titles."
+                "projection": {
+                    "$ref": "#/definitions/ProjectionConfig",
+                    "description": "Projection configuration, which determines default properties for all\n[projections](projection.html). For a full list of projection configuration options,\nplease see the [corresponding section of the projection\ndocumentation](projection.html#config)."
                 },
-                "titleMaxLength": {
-                    "type": "number",
-                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
+                "range": {
+                    "$ref": "#/definitions/RangeConfig",
+                    "description": "An object hash that defines default range arrays or schemes for using with scales.\nFor a full list of scale range configuration options, please see the [corresponding\nsection of the scale documentation](scale.html#config)."
                 },
-                "titlePadding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between title and axis."
+                "rect": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Rect-Specific Config"
                 },
-                "titleX": {
-                    "type": "number",
-                    "description": "X-coordinate of the axis title relative to the axis group."
+                "rule": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Rule-Specific Config"
                 },
-                "titleY": {
-                    "type": "number",
-                    "description": "Y-coordinate of the axis title relative to the axis group."
-                }
-            },
-            "required": [],
-            "title": "AxisConfig",
-            "description": "Axis configuration, which determines default properties for all `x` and `y` [axes](axis.html). For a full list of axis configuration options, please see the [corresponding section of the axis documentation](axis.html#config)."
-        },
-        "VGAxisConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "bandPosition": {
-                    "type": "number",
-                    "description": "An interpolation fraction indicating where, for `band` scales, axis ticks should be\npositioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5`\nplaces ticks in the middle of their bands."
+                "scale": {
+                    "$ref": "#/definitions/ScaleConfig",
+                    "description": "Scale configuration determines default properties for all [scales](scale.html). For a\nfull list of scale configuration options, please see the [corresponding section of the\nscale documentation](scale.html#config)."
                 },
-                "domain": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
+                "selection": {
+                    "$ref": "#/definitions/SelectionConfig",
+                    "description": "An object hash for defining default properties for each type of selections."
                 },
-                "domainColor": {
-                    "type": "string",
-                    "description": "Color of axis domain line.\n\n__Default value:__  (none, using Vega default)."
+                "square": {
+                    "$ref": "#/definitions/MarkConfig",
+                    "description": "Square-Specific Config"
                 },
-                "domainWidth": {
-                    "type": "number",
-                    "description": "Stroke width of axis domain line\n\n__Default value:__  (none, using Vega default)."
+                "stack": {
+                    "$ref": "#/definitions/StackOffset",
+                    "description": "Default stack offset for stackable mark."
                 },
-                "grid": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
+                "style": {
+                    "type": "object",
+                    "additionalProperties": {
+                        "$ref": "#/definitions/VGMarkConfig"
+                    },
+                    "description": "An object hash that defines key-value mappings to determine default properties for marks with a given [style](mark.html#mark-def).  The keys represent styles names; the value are valid [mark configuration objects](mark.html#config).  "
                 },
-                "gridColor": {
-                    "type": "string",
-                    "description": "Color of gridlines."
-                },
-                "gridDash": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "description": "The offset (in pixels) into which to begin drawing with the grid dash array."
-                },
-                "gridOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity of grid (value between [0,1])\n\n__Default value:__ (`1` by default)"
-                },
-                "gridWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The grid width, in pixels."
-                },
-                "labelAngle": {
-                    "type": "number",
-                    "minimum": -360,
-                    "maximum": 360,
-                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
-                },
-                "labelBound": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
-                },
-                "labelColor": {
-                    "type": "string",
-                    "description": "The color of the tick label, can be in hex color code or regular color name."
-                },
-                "labelFlush": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
-                },
-                "labelFont": {
-                    "type": "string",
-                    "description": "The font of the tick label."
-                },
-                "labelFontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The font size of the label, in pixels."
-                },
-                "labelLimit": {
-                    "type": "number",
-                    "description": "Maximum allowed pixel width of axis tick labels."
-                },
-                "labelOverlap": {
-                    "$ref": "#/definitions/LabelOverlapUnion",
-                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
-                },
-                "labelPadding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between axis and text labels."
-                },
-                "labels": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
-                },
-                "maxExtent": {
-                    "type": "number",
-                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
-                },
-                "minExtent": {
-                    "type": "number",
-                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
-                },
-                "tickColor": {
-                    "type": "string",
-                    "description": "The color of the axis's tick."
-                },
-                "tickRound": {
-                    "type": "boolean",
-                    "description": "Boolean flag indicating if pixel position values should be rounded to the nearest integer."
-                },
-                "ticks": {
-                    "type": "boolean",
-                    "description": "Boolean value that determines whether the axis should include ticks."
-                },
-                "tickSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The size in pixels of axis ticks."
-                },
-                "tickWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The width, in pixels, of ticks."
-                },
-                "titleAlign": {
-                    "type": "string",
-                    "description": "Horizontal text alignment of axis titles."
-                },
-                "titleAngle": {
-                    "type": "number",
-                    "description": "Angle in degrees of axis titles."
-                },
-                "titleBaseline": {
-                    "type": "string",
-                    "description": "Vertical text baseline for axis titles."
+                "text": {
+                    "$ref": "#/definitions/TextConfig",
+                    "description": "Text-Specific Config"
                 },
-                "titleColor": {
-                    "type": "string",
-                    "description": "Color of the title, can be in hex color code or regular color name."
+                "tick": {
+                    "$ref": "#/definitions/TickConfig",
+                    "description": "Tick-Specific Config"
                 },
-                "titleFont": {
+                "timeFormat": {
                     "type": "string",
-                    "description": "Font of the title. (e.g., `\"Helvetica Neue\"`)."
-                },
-                "titleFontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Font size of the title."
-                },
-                "titleFontWeight": {
-                    "$ref": "#/definitions/TitleFontWeight",
-                    "description": "Font weight of the title. (e.g., `\"bold\"`)."
-                },
-                "titleLimit": {
-                    "type": "number",
-                    "description": "Maximum allowed pixel width of axis titles."
-                },
-                "titleMaxLength": {
-                    "type": "number",
-                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
-                },
-                "titlePadding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between title and axis."
+                    "description": "Default datetime format for axis and legend labels. The format can be set directly on\neach axis and legend. Use [D3's time format\npattern](https://github.com/d3/d3-time-format#locale_format).\n\n__Default value:__ `'%b %d, %Y'`."
                 },
-                "titleX": {
-                    "type": "number",
-                    "description": "X-coordinate of the axis title relative to the axis group."
+                "title": {
+                    "$ref": "#/definitions/VGTitleConfig",
+                    "description": "Title configuration, which determines default properties for all [titles](title.html).\nFor a full list of title configuration options, please see the [corresponding section of\nthe title documentation](title.html#config)."
                 },
-                "titleY": {
-                    "type": "number",
-                    "description": "Y-coordinate of the axis title relative to the axis group."
+                "view": {
+                    "$ref": "#/definitions/ViewConfig",
+                    "description": "Default properties for [single view plots](spec.html#single)."
                 }
             },
             "required": [],
-            "title": "VGAxisConfig",
-            "description": "Specific axis config for axes with \"band\" scales.\nSpecific axis config for x-axis along the bottom edge of the chart.\nSpecific axis config for y-axis along the left edge of the chart.\nSpecific axis config for y-axis along the right edge of the chart.\nSpecific axis config for x-axis along the top edge of the chart.\nX-axis specific config.\nY-axis specific config."
+            "title": "Config",
+            "description": "Vega-Lite configuration object.  This property can only be defined at the top-level of a specification."
         },
-        "BarConfig": {
+        "MarkConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
@@ -811,29 +612,14 @@
                     "$ref": "#/definitions/VerticalAlign",
                     "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
                 },
-                "binSpacing": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Offset between bar for binned field.  Ideal value for this is either 0 (Preferred by\nstatisticians) or 1 (Vega-Lite Default, D3 example style).\n\n__Default value:__ `1`"
-                },
                 "color": {
                     "type": "string",
                     "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
                 },
-                "continuousBandSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The default size of the bars on continuous scales.\n\n__Default value:__ `5`"
-                },
                 "cursor": {
                     "$ref": "#/definitions/Cursor",
                     "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
                 },
-                "discreteBandSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The size of the bars.  If unspecified, the default size is  `bandSize-1`,\nwhich provides 1 pixel offset between bars."
-                },
                 "dx": {
                     "type": "number",
                     "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
@@ -951,963 +737,1280 @@
                 }
             },
             "required": [],
-            "title": "BarConfig",
-            "description": "Bar-Specific Config "
+            "title": "MarkConfig",
+            "description": "Area-Specific Config \nCircle-Specific Config \nGeoshape-Specific Config \nLine-Specific Config \nMark Config \nPoint-Specific Config \nRect-Specific Config \nRule-Specific Config \nSquare-Specific Config "
         },
-        "LegendConfig": {
+        "AxisConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "cornerRadius": {
-                    "type": "number",
-                    "description": "Corner radius for the full legend."
-                },
-                "entryPadding": {
+                "bandPosition": {
                     "type": "number",
-                    "description": "Padding (in pixels) between legend entries in a symbol legend."
-                },
-                "fillColor": {
-                    "type": "string",
-                    "description": "Background fill color for the full legend."
+                    "description": "An interpolation fraction indicating where, for `band` scales, axis ticks should be\npositioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5`\nplaces ticks in the middle of their bands."
                 },
-                "gradientHeight": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The height of the gradient, in pixels."
+                "domain": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
                 },
-                "gradientLabelBaseline": {
+                "domainColor": {
                     "type": "string",
-                    "description": "Text baseline for color ramp gradient labels."
+                    "description": "Color of axis domain line.\n\n__Default value:__  (none, using Vega default)."
                 },
-                "gradientLabelLimit": {
+                "domainWidth": {
                     "type": "number",
-                    "description": "The maximum allowed length in pixels of color ramp gradient labels."
+                    "description": "Stroke width of axis domain line\n\n__Default value:__  (none, using Vega default)."
                 },
-                "gradientLabelOffset": {
-                    "type": "number",
-                    "description": "Vertical offset in pixels for color ramp gradient labels."
+                "grid": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
                 },
-                "gradientStrokeColor": {
+                "gridColor": {
                     "type": "string",
-                    "description": "The color of the gradient stroke, can be in hex color code or regular color name."
+                    "description": "Color of gridlines."
                 },
-                "gradientStrokeWidth": {
+                "gridDash": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "The offset (in pixels) into which to begin drawing with the grid dash array."
+                },
+                "gridOpacity": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The width of the gradient stroke, in pixels."
+                    "maximum": 1,
+                    "description": "The stroke opacity of grid (value between [0,1])\n\n__Default value:__ (`1` by default)"
                 },
-                "gradientWidth": {
+                "gridWidth": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The width of the gradient, in pixels."
+                    "description": "The grid width, in pixels."
                 },
-                "labelAlign": {
-                    "type": "string",
-                    "description": "The alignment of the legend label, can be left, middle or right."
+                "labelAngle": {
+                    "type": "number",
+                    "minimum": -360,
+                    "maximum": 360,
+                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
                 },
-                "labelBaseline": {
-                    "type": "string",
-                    "description": "The position of the baseline of legend label, can be top, middle or bottom."
+                "labelBound": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
                 },
                 "labelColor": {
                     "type": "string",
-                    "description": "The color of the legend label, can be in hex color code or regular color name."
+                    "description": "The color of the tick label, can be in hex color code or regular color name."
+                },
+                "labelFlush": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
                 },
                 "labelFont": {
                     "type": "string",
-                    "description": "The font of the legend label."
+                    "description": "The font of the tick label."
                 },
                 "labelFontSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The font size of legend label.\n\n__Default value:__ `10`."
+                    "description": "The font size of the label, in pixels."
                 },
                 "labelLimit": {
                     "type": "number",
                     "description": "Maximum allowed pixel width of axis tick labels."
                 },
-                "labelOffset": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The offset of the legend label."
+                "labelOverlap": {
+                    "$ref": "#/definitions/LabelOverlapUnion",
+                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
                 },
-                "offset": {
+                "labelPadding": {
                     "type": "number",
-                    "description": "The offset, in pixels, by which to displace the legend from the edge of the enclosing\ngroup or data rectangle.\n\n__Default value:__  `0`"
+                    "description": "The padding, in pixels, between axis and text labels."
                 },
-                "orient": {
-                    "$ref": "#/definitions/LegendOrient",
-                    "description": "The orientation of the legend, which determines how the legend is positioned within the\nscene. One of \"left\", \"right\", \"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\",\n\"none\".\n\n__Default value:__ `\"right\"`"
+                "labels": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
                 },
-                "padding": {
+                "maxExtent": {
                     "type": "number",
-                    "description": "The padding, in pixels, between the legend and axis."
+                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
+                },
+                "minExtent": {
+                    "type": "number",
+                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
                 },
                 "shortTimeLabels": {
                     "type": "boolean",
                     "description": "Whether month names and weekday names should be abbreviated.\n\n__Default value:__  `false`"
                 },
-                "strokeColor": {
+                "tickColor": {
                     "type": "string",
-                    "description": "Border stroke color for the full legend."
-                },
-                "strokeDash": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "description": "Border stroke dash pattern for the full legend."
+                    "description": "The color of the axis's tick."
                 },
-                "strokeWidth": {
-                    "type": "number",
-                    "description": "Border stroke width for the full legend."
+                "tickRound": {
+                    "type": "boolean",
+                    "description": "Boolean flag indicating if pixel position values should be rounded to the nearest integer."
                 },
-                "symbolColor": {
-                    "type": "string",
-                    "description": "The color of the legend symbol,"
+                "ticks": {
+                    "type": "boolean",
+                    "description": "Boolean value that determines whether the axis should include ticks."
                 },
-                "symbolSize": {
+                "tickSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The size of the legend symbol, in pixels."
+                    "description": "The size in pixels of axis ticks."
                 },
-                "symbolStrokeWidth": {
+                "tickWidth": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The width of the symbol's stroke."
-                },
-                "symbolType": {
-                    "type": "string",
-                    "description": "Default shape type (such as \"circle\") for legend symbols."
+                    "description": "The width, in pixels, of ticks."
                 },
                 "titleAlign": {
                     "type": "string",
-                    "description": "Horizontal text alignment for legend titles."
+                    "description": "Horizontal text alignment of axis titles."
+                },
+                "titleAngle": {
+                    "type": "number",
+                    "description": "Angle in degrees of axis titles."
                 },
                 "titleBaseline": {
                     "type": "string",
-                    "description": "Vertical text baseline for legend titles."
+                    "description": "Vertical text baseline for axis titles."
                 },
                 "titleColor": {
                     "type": "string",
-                    "description": "The color of the legend title, can be in hex color code or regular color name."
+                    "description": "Color of the title, can be in hex color code or regular color name."
                 },
                 "titleFont": {
                     "type": "string",
-                    "description": "The font of the legend title."
+                    "description": "Font of the title. (e.g., `\"Helvetica Neue\"`)."
                 },
                 "titleFontSize": {
                     "type": "number",
-                    "description": "The font size of the legend title."
+                    "minimum": 0,
+                    "description": "Font size of the title."
                 },
                 "titleFontWeight": {
                     "$ref": "#/definitions/TitleFontWeight",
-                    "description": "The font weight of the legend title."
+                    "description": "Font weight of the title. (e.g., `\"bold\"`)."
                 },
                 "titleLimit": {
                     "type": "number",
                     "description": "Maximum allowed pixel width of axis titles."
                 },
+                "titleMaxLength": {
+                    "type": "number",
+                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
+                },
                 "titlePadding": {
                     "type": "number",
-                    "description": "The padding, in pixels, between title and legend."
+                    "description": "The padding, in pixels, between title and axis."
+                },
+                "titleX": {
+                    "type": "number",
+                    "description": "X-coordinate of the axis title relative to the axis group."
+                },
+                "titleY": {
+                    "type": "number",
+                    "description": "Y-coordinate of the axis title relative to the axis group."
                 }
             },
             "required": [],
-            "title": "LegendConfig",
-            "description": "Legend configuration, which determines default properties for all [legends](legend.html). For a full list of legend configuration options, please see the [corresponding section of in the legend documentation](legend.html#config)."
+            "title": "AxisConfig",
+            "description": "Axis configuration, which determines default properties for all `x` and `y` [axes](axis.html). For a full list of axis configuration options, please see the [corresponding section of the axis documentation](axis.html#config)."
         },
-        "PaddingClass": {
+        "VGAxisConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "bottom": {
-                    "type": "number"
+                "bandPosition": {
+                    "type": "number",
+                    "description": "An interpolation fraction indicating where, for `band` scales, axis ticks should be\npositioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5`\nplaces ticks in the middle of their bands."
                 },
-                "left": {
-                    "type": "number"
+                "domain": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
                 },
-                "right": {
-                    "type": "number"
+                "domainColor": {
+                    "type": "string",
+                    "description": "Color of axis domain line.\n\n__Default value:__  (none, using Vega default)."
                 },
-                "top": {
-                    "type": "number"
-                }
-            },
-            "required": [],
-            "title": "PaddingClass"
-        },
-        "ProjectionConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "center": {
+                "domainWidth": {
+                    "type": "number",
+                    "description": "Stroke width of axis domain line\n\n__Default value:__  (none, using Vega default)."
+                },
+                "grid": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
+                },
+                "gridColor": {
+                    "type": "string",
+                    "description": "Color of gridlines."
+                },
+                "gridDash": {
                     "type": "array",
                     "items": {
                         "type": "number"
                     },
-                    "description": "Sets the projection’s center to the specified center, a two-element array of longitude\nand latitude in degrees.\n\n__Default value:__ `[0, 0]`"
+                    "description": "The offset (in pixels) into which to begin drawing with the grid dash array."
                 },
-                "clipAngle": {
+                "gridOpacity": {
                     "type": "number",
-                    "description": "Sets the projection’s clipping circle radius to the specified angle in degrees. If\n`null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather\nthan small-circle clipping."
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The stroke opacity of grid (value between [0,1])\n\n__Default value:__ (`1` by default)"
                 },
-                "clipExtent": {
-                    "type": "array",
-                    "items": {
-                        "type": "array",
-                        "items": {
-                            "type": "number"
-                        }
-                    },
-                    "description": "Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent\nbounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of\nthe viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no\nviewport clipping is performed."
+                "gridWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The grid width, in pixels."
                 },
-                "coefficient": {
-                    "type": "number"
+                "labelAngle": {
+                    "type": "number",
+                    "minimum": -360,
+                    "maximum": 360,
+                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
                 },
-                "distance": {
-                    "type": "number"
+                "labelBound": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
                 },
-                "fraction": {
-                    "type": "number"
+                "labelColor": {
+                    "type": "string",
+                    "description": "The color of the tick label, can be in hex color code or regular color name."
                 },
-                "lobes": {
-                    "type": "number"
+                "labelFlush": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
                 },
-                "parallel": {
-                    "type": "number"
+                "labelFont": {
+                    "type": "string",
+                    "description": "The font of the tick label."
                 },
-                "precision": {
-                    "$ref": "#/definitions/PurplePrecision",
-                    "description": "Sets the threshold for the projection’s [adaptive\nresampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This\nvalue corresponds to the [Douglas–Peucker\ndistance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).\nIf precision is not specified, returns the projection’s current resampling precision\nwhich defaults to `√0.5 ≅ 0.70710…`."
+                "labelFontSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The font size of the label, in pixels."
                 },
-                "radius": {
-                    "type": "number"
+                "labelLimit": {
+                    "type": "number",
+                    "description": "Maximum allowed pixel width of axis tick labels."
                 },
-                "ratio": {
-                    "type": "number"
+                "labelOverlap": {
+                    "$ref": "#/definitions/LabelOverlapUnion",
+                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
                 },
-                "rotate": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "description": "Sets the projection’s three-axis rotation to the specified angles, which must be a two-\nor three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation\nangles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)\n\n__Default value:__ `[0, 0, 0]`"
+                "labelPadding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between axis and text labels."
                 },
-                "spacing": {
-                    "type": "number"
+                "labels": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
                 },
-                "tilt": {
-                    "type": "number"
+                "maxExtent": {
+                    "type": "number",
+                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
                 },
-                "type": {
-                    "$ref": "#/definitions/VGProjectionType",
-                    "description": "The cartographic projection to use. This value is case-insensitive, for example\n`\"albers\"` and `\"Albers\"` indicate the same projection type. You can find all valid\nprojection types [in the\ndocumentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\n\n__Default value:__ `mercator`"
-                }
-            },
-            "required": [],
-            "title": "ProjectionConfig",
-            "description": "Projection configuration, which determines default properties for all [projections](projection.html). For a full list of projection configuration options, please see the [corresponding section of the projection documentation](projection.html#config).\nAny property of Projection can be in config"
-        },
-        "PurplePrecision": {
-            "type": "object",
-            "additionalProperties": {
-                "type": "string"
-            },
-            "properties": {
-                "length": {
+                "minExtent": {
                     "type": "number",
-                    "description": "Returns the length of a String object."
-                }
-            },
-            "required": [
-                "length"
-            ],
-            "title": "PurplePrecision",
-            "description": "Sets the threshold for the projection’s [adaptive resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This value corresponds to the [Douglas–Peucker distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm). If precision is not specified, returns the projection’s current resampling precision which defaults to `√0.5 ≅ 0.70710…`."
-        },
-        "RangeConfig": {
-            "type": "object",
-            "additionalProperties": {
-                "$ref": "#/definitions/RangeConfigValue"
-            },
-            "properties": {
-                "category": {
-                    "$ref": "#/definitions/Category",
-                    "description": "Default range for _nominal_ (categorical) fields."
+                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
                 },
-                "diverging": {
-                    "$ref": "#/definitions/Category",
-                    "description": "Default range for diverging _quantitative_ fields."
+                "tickColor": {
+                    "type": "string",
+                    "description": "The color of the axis's tick."
                 },
-                "heatmap": {
-                    "$ref": "#/definitions/Category",
-                    "description": "Default range for _quantitative_ heatmaps."
+                "tickRound": {
+                    "type": "boolean",
+                    "description": "Boolean flag indicating if pixel position values should be rounded to the nearest integer."
                 },
-                "ordinal": {
-                    "$ref": "#/definitions/Category",
-                    "description": "Default range for _ordinal_ fields."
+                "ticks": {
+                    "type": "boolean",
+                    "description": "Boolean value that determines whether the axis should include ticks."
                 },
-                "ramp": {
-                    "$ref": "#/definitions/Category",
-                    "description": "Default range for _quantitative_ and _temporal_ fields."
+                "tickSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The size in pixels of axis ticks."
                 },
-                "symbol": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "Default range palette for the `shape` channel."
-                }
-            },
-            "required": [],
-            "title": "RangeConfig",
-            "description": "An object hash that defines default range arrays or schemes for using with scales.\nFor a full list of scale range configuration options, please see the [corresponding section of the scale documentation](scale.html#config)."
-        },
-        "CategoryVGScheme": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "count": {
-                    "type": "number"
+                "tickWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The width, in pixels, of ticks."
                 },
-                "extent": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    }
+                "titleAlign": {
+                    "type": "string",
+                    "description": "Horizontal text alignment of axis titles."
                 },
-                "scheme": {
-                    "type": "string"
-                }
-            },
-            "required": [
-                "scheme"
-            ],
-            "title": "CategoryVGScheme"
-        },
-        "RangeConfigValueVGScheme": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "count": {
-                    "type": "number"
+                "titleAngle": {
+                    "type": "number",
+                    "description": "Angle in degrees of axis titles."
                 },
-                "extent": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    }
+                "titleBaseline": {
+                    "type": "string",
+                    "description": "Vertical text baseline for axis titles."
                 },
-                "scheme": {
-                    "type": "string"
+                "titleColor": {
+                    "type": "string",
+                    "description": "Color of the title, can be in hex color code or regular color name."
                 },
-                "step": {
-                    "type": "number"
+                "titleFont": {
+                    "type": "string",
+                    "description": "Font of the title. (e.g., `\"Helvetica Neue\"`)."
+                },
+                "titleFontSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Font size of the title."
+                },
+                "titleFontWeight": {
+                    "$ref": "#/definitions/TitleFontWeight",
+                    "description": "Font weight of the title. (e.g., `\"bold\"`)."
+                },
+                "titleLimit": {
+                    "type": "number",
+                    "description": "Maximum allowed pixel width of axis titles."
+                },
+                "titleMaxLength": {
+                    "type": "number",
+                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
+                },
+                "titlePadding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between title and axis."
+                },
+                "titleX": {
+                    "type": "number",
+                    "description": "X-coordinate of the axis title relative to the axis group."
+                },
+                "titleY": {
+                    "type": "number",
+                    "description": "Y-coordinate of the axis title relative to the axis group."
                 }
             },
             "required": [],
-            "title": "RangeConfigValueVGScheme"
+            "title": "VGAxisConfig",
+            "description": "Specific axis config for axes with \"band\" scales.\nSpecific axis config for x-axis along the bottom edge of the chart.\nSpecific axis config for y-axis along the left edge of the chart.\nSpecific axis config for y-axis along the right edge of the chart.\nSpecific axis config for x-axis along the top edge of the chart.\nX-axis specific config.\nY-axis specific config."
         },
-        "ScaleConfig": {
+        "BarConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "bandPaddingInner": {
+                "align": {
+                    "$ref": "#/definitions/HorizontalAlign",
+                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
+                },
+                "angle": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "Default inner padding for `x` and `y` band-ordinal scales.\n\n__Default value:__ `0.1`"
+                    "maximum": 360,
+                    "description": "The rotation angle of the text, in degrees."
                 },
-                "bandPaddingOuter": {
+                "baseline": {
+                    "$ref": "#/definitions/VerticalAlign",
+                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
+                },
+                "binSpacing": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "Default outer padding for `x` and `y` band-ordinal scales.\nIf not specified, by default, band scale's paddingOuter is paddingInner/2."
+                    "description": "Offset between bar for binned field.  Ideal value for this is either 0 (Preferred by\nstatisticians) or 1 (Vega-Lite Default, D3 example style).\n\n__Default value:__ `1`"
                 },
-                "clamp": {
-                    "type": "boolean",
-                    "description": "If true, values that exceed the data domain are clamped to either the minimum or maximum\nrange value"
+                "color": {
+                    "type": "string",
+                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
                 },
-                "continuousPadding": {
+                "continuousBandSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Default padding for continuous scales.\n\n__Default:__ `5` for continuous x-scale of a vertical bar and continuous y-scale of a\nhorizontal bar.; `0` otherwise."
+                    "description": "The default size of the bars on continuous scales.\n\n__Default value:__ `5`"
                 },
-                "maxBandSize": {
+                "cursor": {
+                    "$ref": "#/definitions/Cursor",
+                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                },
+                "discreteBandSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The default max value for mapping quantitative fields to bar's size/bandSize.\n\nIf undefined (default), we will use the scale's `rangeStep` - 1."
+                    "description": "The size of the bars.  If unspecified, the default size is  `bandSize-1`,\nwhich provides 1 pixel offset between bars."
                 },
-                "maxFontSize": {
+                "dx": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "The default max value for mapping quantitative fields to text's size/fontSize.\n\n__Default value:__ `40`"
+                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
                 },
-                "maxOpacity": {
+                "dy": {
+                    "type": "number",
+                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "fill": {
+                    "type": "string",
+                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                },
+                "filled": {
+                    "type": "boolean",
+                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "fillOpacity": {
                     "type": "number",
                     "minimum": 0,
                     "maximum": 1,
-                    "description": "Default max opacity for mapping a field to opacity.\n\n__Default value:__ `0.8`"
+                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
                 },
-                "maxSize": {
+                "font": {
+                    "type": "string",
+                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
+                },
+                "fontSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Default max value for point size scale."
+                    "description": "The font size, in pixels."
                 },
-                "maxStrokeWidth": {
+                "fontStyle": {
+                    "$ref": "#/definitions/FontStyle",
+                    "description": "The font style (e.g., `\"italic\"`)."
+                },
+                "fontWeight": {
+                    "$ref": "#/definitions/FontWeightUnion",
+                    "description": "The font weight (e.g., `\"bold\"`)."
+                },
+                "href": {
+                    "type": "string",
+                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
+                },
+                "interpolate": {
+                    "$ref": "#/definitions/Interpolate",
+                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                },
+                "limit": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "Default max strokeWidth for strokeWidth  (or rule/line's size) scale.\n\n__Default value:__ `4`"
+                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
                 },
-                "minBandSize": {
+                "opacity": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The default min value for mapping quantitative fields to bar and tick's size/bandSize\nscale with zero=false.\n\n__Default value:__ `2`"
+                    "maximum": 1,
+                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
                 },
-                "minFontSize": {
+                "orient": {
+                    "$ref": "#/definitions/Orient",
+                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
+                },
+                "radius": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The default min value for mapping quantitative fields to tick's size/fontSize scale with\nzero=false\n\n__Default value:__ `8`"
+                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
                 },
-                "minOpacity": {
+                "shape": {
+                    "type": "string",
+                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
+                },
+                "size": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "Default minimum opacity for mapping a field to opacity.\n\n__Default value:__ `0.3`"
+                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
                 },
-                "minSize": {
+                "stroke": {
+                    "type": "string",
+                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                },
+                "strokeDash": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
+                },
+                "strokeDashOffset": {
+                    "type": "number",
+                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
+                },
+                "strokeOpacity": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Default minimum value for point size scale with zero=false.\n\n__Default value:__ `9`"
+                    "maximum": 1,
+                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
                 },
-                "minStrokeWidth": {
+                "strokeWidth": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Default minimum strokeWidth for strokeWidth (or rule/line's size) scale with zero=false.\n\n__Default value:__ `1`"
+                    "description": "The stroke width, in pixels."
                 },
-                "pointPadding": {
+                "tension": {
                     "type": "number",
                     "minimum": 0,
                     "maximum": 1,
-                    "description": "Default outer padding for `x` and `y` point-ordinal scales.\n\n__Default value:__ `0.5`"
-                },
-                "rangeStep": {
-                    "anyOf": [
-                        {
-                            "type": "number",
-                            "minimum": 0
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "Default range step for band and point scales of (1) the `y` channel\nand (2) the `x` channel when the mark is not `text`.\n\n__Default value:__ `21`"
+                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
                 },
-                "round": {
-                    "type": "boolean",
-                    "description": "If true, rounds numeric output values to integers.\nThis can be helpful for snapping to the pixel grid.\n(Only available for `x`, `y`, and `size` scales.)"
+                "text": {
+                    "type": "string",
+                    "description": "Placeholder text if the `text` channel is not specified"
                 },
-                "textXRangeStep": {
+                "theta": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "Default range step for `x` band and point scales of text marks.\n\n__Default value:__ `90`"
-                },
-                "useUnaggregatedDomain": {
-                    "type": "boolean",
-                    "description": "Use the source data range before aggregation as scale domain instead of aggregated data\nfor aggregate axis.\n\nThis is equivalent to setting `domain` to `\"unaggregate\"` for aggregated _quantitative_\nfields by default.\n\nThis property only works with aggregate functions that produce values within the raw data\ndomain (`\"mean\"`, `\"average\"`, `\"median\"`, `\"q1\"`, `\"q3\"`, `\"min\"`, `\"max\"`). For other\naggregations that produce values outside of the raw data domain (e.g. `\"count\"`,\n`\"sum\"`), this property is ignored.\n\n__Default value:__ `false`"
+                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
                 }
             },
             "required": [],
-            "title": "ScaleConfig",
-            "description": "Scale configuration determines default properties for all [scales](scale.html). For a full list of scale configuration options, please see the [corresponding section of the scale documentation](scale.html#config)."
+            "title": "BarConfig",
+            "description": "Bar-Specific Config "
         },
-        "SelectionConfig": {
+        "LegendConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "interval": {
-                    "$ref": "#/definitions/IntervalSelectionConfig",
-                    "description": "The default definition for an [`interval`](selection.html#type) selection. All properties\nand transformations\nfor an interval selection definition (except `type`) may be specified here.\n\nFor instance, setting `interval` to `{\"translate\": false}` disables the ability to move\ninterval selections by default."
+                "cornerRadius": {
+                    "type": "number",
+                    "description": "Corner radius for the full legend."
                 },
-                "multi": {
-                    "$ref": "#/definitions/MultiSelectionConfig",
-                    "description": "The default definition for a [`multi`](selection.html#type) selection. All properties and\ntransformations\nfor a multi selection definition (except `type`) may be specified here.\n\nFor instance, setting `multi` to `{\"toggle\": \"event.altKey\"}` adds additional values to\nmulti selections when clicking with the alt-key pressed by default."
+                "entryPadding": {
+                    "type": "number",
+                    "description": "Padding (in pixels) between legend entries in a symbol legend."
                 },
-                "single": {
-                    "$ref": "#/definitions/SingleSelectionConfig",
-                    "description": "The default definition for a [`single`](selection.html#type) selection. All properties\nand transformations\nfor a single selection definition (except `type`) may be specified here.\n\nFor instance, setting `single` to `{\"on\": \"dblclick\"}` populates single selections on\ndouble-click by default."
-                }
-            },
-            "required": [],
-            "title": "SelectionConfig",
-            "description": "An object hash for defining default properties for each type of selections. "
-        },
-        "IntervalSelectionConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "bind": {
-                    "$ref": "#/definitions/BindEnum",
-                    "description": "Establishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
+                "fillColor": {
+                    "type": "string",
+                    "description": "Background fill color for the full legend."
                 },
-                "empty": {
-                    "$ref": "#/definitions/Empty",
-                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                "gradientHeight": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The height of the gradient, in pixels."
                 },
-                "encodings": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/SingleDefChannel"
-                    },
-                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                "gradientLabelBaseline": {
+                    "type": "string",
+                    "description": "Text baseline for color ramp gradient labels."
                 },
-                "fields": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
+                "gradientLabelLimit": {
+                    "type": "number",
+                    "description": "The maximum allowed length in pixels of color ramp gradient labels."
                 },
-                "mark": {
-                    "$ref": "#/definitions/BrushConfig",
-                    "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
+                "gradientLabelOffset": {
+                    "type": "number",
+                    "description": "Vertical offset in pixels for color ramp gradient labels."
                 },
-                "on": {
-                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                "gradientStrokeColor": {
+                    "type": "string",
+                    "description": "The color of the gradient stroke, can be in hex color code or regular color name."
                 },
-                "resolve": {
-                    "$ref": "#/definitions/SelectionResolution",
-                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                "gradientStrokeWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The width of the gradient stroke, in pixels."
                 },
-                "translate": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "When truthy, allows a user to interactively move an interval selection\nback-and-forth. Can be `true`, `false` (to disable panning), or a\n[Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)\nwhich must include a start and end event to trigger continuous panning.\n\n__Default value:__ `true`, which corresponds to\n`[mousedown, window:mouseup] > window:mousemove!` which corresponds to\nclicks and dragging within an interval selection to reposition it."
+                "gradientWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The width of the gradient, in pixels."
                 },
-                "zoom": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "When truthy, allows a user to interactively resize an interval selection.\nCan be `true`, `false` (to disable zooming), or a [Vega event stream\ndefinition](https://vega.github.io/vega/docs/event-streams/). Currently,\nonly `wheel` events are supported.\n\n\n__Default value:__ `true`, which corresponds to `wheel!`."
-                }
-            },
-            "required": [],
-            "title": "IntervalSelectionConfig",
-            "description": "The default definition for an [`interval`](selection.html#type) selection. All properties and transformations\nfor an interval selection definition (except `type`) may be specified here.\n\nFor instance, setting `interval` to `{\"translate\": false}` disables the ability to move\ninterval selections by default."
-        },
-        "BrushConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "fill": {
+                "labelAlign": {
                     "type": "string",
-                    "description": "The fill color of the interval mark.\n\n__Default value:__ `#333333`"
+                    "description": "The alignment of the legend label, can be left, middle or right."
                 },
-                "fillOpacity": {
+                "labelBaseline": {
+                    "type": "string",
+                    "description": "The position of the baseline of legend label, can be top, middle or bottom."
+                },
+                "labelColor": {
+                    "type": "string",
+                    "description": "The color of the legend label, can be in hex color code or regular color name."
+                },
+                "labelFont": {
+                    "type": "string",
+                    "description": "The font of the legend label."
+                },
+                "labelFontSize": {
                     "type": "number",
-                    "description": "The fill opacity of the interval mark (a value between 0 and 1).\n\n__Default value:__ `0.125`"
+                    "minimum": 0,
+                    "description": "The font size of legend label.\n\n__Default value:__ `10`."
                 },
-                "stroke": {
+                "labelLimit": {
+                    "type": "number",
+                    "description": "Maximum allowed pixel width of axis tick labels."
+                },
+                "labelOffset": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The offset of the legend label."
+                },
+                "offset": {
+                    "type": "number",
+                    "description": "The offset, in pixels, by which to displace the legend from the edge of the enclosing\ngroup or data rectangle.\n\n__Default value:__  `0`"
+                },
+                "orient": {
+                    "$ref": "#/definitions/LegendOrient",
+                    "description": "The orientation of the legend, which determines how the legend is positioned within the\nscene. One of \"left\", \"right\", \"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\",\n\"none\".\n\n__Default value:__ `\"right\"`"
+                },
+                "padding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between the legend and axis."
+                },
+                "shortTimeLabels": {
+                    "type": "boolean",
+                    "description": "Whether month names and weekday names should be abbreviated.\n\n__Default value:__  `false`"
+                },
+                "strokeColor": {
                     "type": "string",
-                    "description": "The stroke color of the interval mark.\n\n__Default value:__ `#ffffff`"
+                    "description": "Border stroke color for the full legend."
                 },
                 "strokeDash": {
                     "type": "array",
                     "items": {
                         "type": "number"
                     },
-                    "description": "An array of alternating stroke and space lengths,\nfor creating dashed or dotted lines."
+                    "description": "Border stroke dash pattern for the full legend."
                 },
-                "strokeDashOffset": {
+                "strokeWidth": {
                     "type": "number",
-                    "description": "The offset (in pixels) with which to begin drawing the stroke dash array."
+                    "description": "Border stroke width for the full legend."
                 },
-                "strokeOpacity": {
+                "symbolColor": {
+                    "type": "string",
+                    "description": "The color of the legend symbol,"
+                },
+                "symbolSize": {
                     "type": "number",
-                    "description": "The stroke opacity of the interval mark (a value between 0 and 1)."
+                    "minimum": 0,
+                    "description": "The size of the legend symbol, in pixels."
                 },
-                "strokeWidth": {
+                "symbolStrokeWidth": {
                     "type": "number",
-                    "description": "The stroke width of the interval mark."
+                    "minimum": 0,
+                    "description": "The width of the symbol's stroke."
+                },
+                "symbolType": {
+                    "type": "string",
+                    "description": "Default shape type (such as \"circle\") for legend symbols."
+                },
+                "titleAlign": {
+                    "type": "string",
+                    "description": "Horizontal text alignment for legend titles."
+                },
+                "titleBaseline": {
+                    "type": "string",
+                    "description": "Vertical text baseline for legend titles."
+                },
+                "titleColor": {
+                    "type": "string",
+                    "description": "The color of the legend title, can be in hex color code or regular color name."
+                },
+                "titleFont": {
+                    "type": "string",
+                    "description": "The font of the legend title."
+                },
+                "titleFontSize": {
+                    "type": "number",
+                    "description": "The font size of the legend title."
+                },
+                "titleFontWeight": {
+                    "$ref": "#/definitions/TitleFontWeight",
+                    "description": "The font weight of the legend title."
+                },
+                "titleLimit": {
+                    "type": "number",
+                    "description": "Maximum allowed pixel width of axis titles."
+                },
+                "titlePadding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between title and legend."
                 }
             },
             "required": [],
-            "title": "BrushConfig",
-            "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
+            "title": "LegendConfig",
+            "description": "Legend configuration, which determines default properties for all [legends](legend.html). For a full list of legend configuration options, please see the [corresponding section of in the legend documentation](legend.html#config)."
         },
-        "MultiSelectionConfig": {
+        "PaddingClass": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "empty": {
-                    "$ref": "#/definitions/Empty",
-                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                "bottom": {
+                    "type": "number"
                 },
-                "encodings": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/SingleDefChannel"
-                    },
-                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                "left": {
+                    "type": "number"
                 },
-                "fields": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
-                },
-                "nearest": {
-                    "type": "boolean",
-                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
-                },
-                "on": {
-                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
-                },
-                "resolve": {
-                    "$ref": "#/definitions/SelectionResolution",
-                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                "right": {
+                    "type": "number"
                 },
-                "toggle": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "Controls whether data values should be toggled or only ever inserted into\nmulti selections. Can be `true`, `false` (for insertion only), or a\n[Vega expression](https://vega.github.io/vega/docs/expressions/).\n\n__Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,\ndata values are toggled when a user interacts with the shift-key pressed).\n\nSee the [toggle transform](toggle.html) documentation for more information."
+                "top": {
+                    "type": "number"
                 }
             },
             "required": [],
-            "title": "MultiSelectionConfig",
-            "description": "The default definition for a [`multi`](selection.html#type) selection. All properties and transformations\nfor a multi selection definition (except `type`) may be specified here.\n\nFor instance, setting `multi` to `{\"toggle\": \"event.altKey\"}` adds additional values to\nmulti selections when clicking with the alt-key pressed by default."
+            "title": "PaddingClass"
         },
-        "SingleSelectionConfig": {
+        "ProjectionConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "bind": {
-                    "type": "object",
-                    "additionalProperties": {
-                        "$ref": "#/definitions/VGBinding"
+                "center": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
                     },
-                    "description": "Establish a two-way binding between a single selection and input elements\n(also known as dynamic query widgets). A binding takes the form of\nVega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)\nor can be a mapping between projected field/encodings and binding definitions.\n\nSee the [bind transform](bind.html) documentation for more information."
+                    "description": "Sets the projection’s center to the specified center, a two-element array of longitude\nand latitude in degrees.\n\n__Default value:__ `[0, 0]`"
                 },
-                "empty": {
-                    "$ref": "#/definitions/Empty",
-                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                "clipAngle": {
+                    "type": "number",
+                    "description": "Sets the projection’s clipping circle radius to the specified angle in degrees. If\n`null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather\nthan small-circle clipping."
                 },
-                "encodings": {
+                "clipExtent": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/SingleDefChannel"
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
                     },
-                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                    "description": "Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent\nbounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of\nthe viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no\nviewport clipping is performed."
                 },
-                "fields": {
+                "coefficient": {
+                    "type": "number"
+                },
+                "distance": {
+                    "type": "number"
+                },
+                "fraction": {
+                    "type": "number"
+                },
+                "lobes": {
+                    "type": "number"
+                },
+                "parallel": {
+                    "type": "number"
+                },
+                "precision": {
+                    "$ref": "#/definitions/PurplePrecision",
+                    "description": "Sets the threshold for the projection’s [adaptive\nresampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This\nvalue corresponds to the [Douglas–Peucker\ndistance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).\nIf precision is not specified, returns the projection’s current resampling precision\nwhich defaults to `√0.5 ≅ 0.70710…`."
+                },
+                "radius": {
+                    "type": "number"
+                },
+                "ratio": {
+                    "type": "number"
+                },
+                "rotate": {
                     "type": "array",
                     "items": {
-                        "type": "string"
+                        "type": "number"
                     },
-                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
+                    "description": "Sets the projection’s three-axis rotation to the specified angles, which must be a two-\nor three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation\nangles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)\n\n__Default value:__ `[0, 0, 0]`"
                 },
-                "nearest": {
-                    "type": "boolean",
-                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
+                "spacing": {
+                    "type": "number"
                 },
-                "on": {
-                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                "tilt": {
+                    "type": "number"
                 },
-                "resolve": {
-                    "$ref": "#/definitions/SelectionResolution",
-                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                "type": {
+                    "$ref": "#/definitions/VGProjectionType",
+                    "description": "The cartographic projection to use. This value is case-insensitive, for example\n`\"albers\"` and `\"Albers\"` indicate the same projection type. You can find all valid\nprojection types [in the\ndocumentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\n\n__Default value:__ `mercator`"
                 }
             },
             "required": [],
-            "title": "SingleSelectionConfig",
-            "description": "The default definition for a [`single`](selection.html#type) selection. All properties and transformations\n  for a single selection definition (except `type`) may be specified here.\n\nFor instance, setting `single` to `{\"on\": \"dblclick\"}` populates single selections on double-click by default."
+            "title": "ProjectionConfig",
+            "description": "Projection configuration, which determines default properties for all [projections](projection.html). For a full list of projection configuration options, please see the [corresponding section of the projection documentation](projection.html#config).\nAny property of Projection can be in config"
         },
-        "VGMarkConfig": {
+        "PurplePrecision": {
             "type": "object",
-            "additionalProperties": false,
+            "additionalProperties": {
+                "type": "string"
+            },
             "properties": {
-                "align": {
-                    "$ref": "#/definitions/HorizontalAlign",
-                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
-                },
-                "angle": {
+                "length": {
                     "type": "number",
-                    "minimum": 0,
-                    "maximum": 360,
-                    "description": "The rotation angle of the text, in degrees."
+                    "description": "Returns the length of a String object."
+                }
+            },
+            "required": [
+                "length"
+            ],
+            "title": "PurplePrecision",
+            "description": "Sets the threshold for the projection’s [adaptive resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This value corresponds to the [Douglas–Peucker distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm). If precision is not specified, returns the projection’s current resampling precision which defaults to `√0.5 ≅ 0.70710…`."
+        },
+        "RangeConfig": {
+            "type": "object",
+            "additionalProperties": {
+                "$ref": "#/definitions/RangeConfigValue"
+            },
+            "properties": {
+                "category": {
+                    "$ref": "#/definitions/Category",
+                    "description": "Default range for _nominal_ (categorical) fields."
                 },
-                "baseline": {
-                    "$ref": "#/definitions/VerticalAlign",
-                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
+                "diverging": {
+                    "$ref": "#/definitions/Category",
+                    "description": "Default range for diverging _quantitative_ fields."
                 },
-                "cursor": {
-                    "$ref": "#/definitions/Cursor",
-                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                "heatmap": {
+                    "$ref": "#/definitions/Category",
+                    "description": "Default range for _quantitative_ heatmaps."
                 },
-                "dx": {
-                    "type": "number",
-                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                "ordinal": {
+                    "$ref": "#/definitions/Category",
+                    "description": "Default range for _ordinal_ fields."
                 },
-                "dy": {
-                    "type": "number",
-                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                "ramp": {
+                    "$ref": "#/definitions/Category",
+                    "description": "Default range for _quantitative_ and _temporal_ fields."
                 },
-                "fill": {
-                    "type": "string",
-                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                "symbol": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "Default range palette for the `shape` channel."
+                }
+            },
+            "required": [],
+            "title": "RangeConfig",
+            "description": "An object hash that defines default range arrays or schemes for using with scales.\nFor a full list of scale range configuration options, please see the [corresponding section of the scale documentation](scale.html#config)."
+        },
+        "VGScheme": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "count": {
+                    "type": "number"
                 },
-                "fillOpacity": {
+                "extent": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    }
+                },
+                "scheme": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "scheme"
+            ],
+            "title": "VGScheme"
+        },
+        "RangeConfigValueClass": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "step": {
+                    "type": "number"
+                }
+            },
+            "required": [
+                "step"
+            ],
+            "title": "RangeConfigValueClass"
+        },
+        "ScaleConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "bandPaddingInner": {
                     "type": "number",
                     "minimum": 0,
                     "maximum": 1,
-                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
-                },
-                "font": {
-                    "type": "string",
-                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
+                    "description": "Default inner padding for `x` and `y` band-ordinal scales.\n\n__Default value:__ `0.1`"
                 },
-                "fontSize": {
+                "bandPaddingOuter": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The font size, in pixels."
-                },
-                "fontStyle": {
-                    "$ref": "#/definitions/FontStyle",
-                    "description": "The font style (e.g., `\"italic\"`)."
-                },
-                "fontWeight": {
-                    "$ref": "#/definitions/FontWeightUnion",
-                    "description": "The font weight (e.g., `\"bold\"`)."
-                },
-                "href": {
-                    "type": "string",
-                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
+                    "maximum": 1,
+                    "description": "Default outer padding for `x` and `y` band-ordinal scales.\nIf not specified, by default, band scale's paddingOuter is paddingInner/2."
                 },
-                "interpolate": {
-                    "$ref": "#/definitions/Interpolate",
-                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                "clamp": {
+                    "type": "boolean",
+                    "description": "If true, values that exceed the data domain are clamped to either the minimum or maximum\nrange value"
                 },
-                "limit": {
+                "continuousPadding": {
                     "type": "number",
-                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
+                    "minimum": 0,
+                    "description": "Default padding for continuous scales.\n\n__Default:__ `5` for continuous x-scale of a vertical bar and continuous y-scale of a\nhorizontal bar.; `0` otherwise."
                 },
-                "opacity": {
+                "maxBandSize": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
-                },
-                "orient": {
-                    "$ref": "#/definitions/Orient",
-                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
+                    "description": "The default max value for mapping quantitative fields to bar's size/bandSize.\n\nIf undefined (default), we will use the scale's `rangeStep` - 1."
                 },
-                "radius": {
+                "maxFontSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                    "description": "The default max value for mapping quantitative fields to text's size/fontSize.\n\n__Default value:__ `40`"
                 },
-                "shape": {
-                    "type": "string",
-                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
-                },
-                "size": {
+                "maxOpacity": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
-                },
-                "stroke": {
-                    "type": "string",
-                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
-                },
-                "strokeDash": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
+                    "maximum": 1,
+                    "description": "Default max opacity for mapping a field to opacity.\n\n__Default value:__ `0.8`"
                 },
-                "strokeDashOffset": {
+                "maxSize": {
                     "type": "number",
-                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
+                    "minimum": 0,
+                    "description": "Default max value for point size scale."
                 },
-                "strokeOpacity": {
+                "maxStrokeWidth": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                    "description": "Default max strokeWidth for strokeWidth  (or rule/line's size) scale.\n\n__Default value:__ `4`"
                 },
-                "strokeWidth": {
+                "minBandSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The stroke width, in pixels."
+                    "description": "The default min value for mapping quantitative fields to bar and tick's size/bandSize\nscale with zero=false.\n\n__Default value:__ `2`"
                 },
-                "tension": {
+                "minFontSize": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
-                },
-                "text": {
-                    "type": "string",
-                    "description": "Placeholder text if the `text` channel is not specified"
+                    "description": "The default min value for mapping quantitative fields to tick's size/fontSize scale with\nzero=false\n\n__Default value:__ `8`"
                 },
-                "theta": {
+                "minOpacity": {
                     "type": "number",
-                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
-                }
-            },
-            "required": [],
-            "title": "VGMarkConfig"
-        },
-        "TextConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "align": {
-                    "$ref": "#/definitions/HorizontalAlign",
-                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "Default minimum opacity for mapping a field to opacity.\n\n__Default value:__ `0.3`"
                 },
-                "angle": {
+                "minSize": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 360,
-                    "description": "The rotation angle of the text, in degrees."
-                },
-                "baseline": {
-                    "$ref": "#/definitions/VerticalAlign",
-                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
-                },
-                "color": {
-                    "type": "string",
-                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
-                "cursor": {
-                    "$ref": "#/definitions/Cursor",
-                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                    "description": "Default minimum value for point size scale with zero=false.\n\n__Default value:__ `9`"
                 },
-                "dx": {
+                "minStrokeWidth": {
                     "type": "number",
-                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                    "minimum": 0,
+                    "description": "Default minimum strokeWidth for strokeWidth (or rule/line's size) scale with zero=false.\n\n__Default value:__ `1`"
                 },
-                "dy": {
+                "pointPadding": {
                     "type": "number",
-                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "Default outer padding for `x` and `y` point-ordinal scales.\n\n__Default value:__ `0.5`"
                 },
-                "fill": {
-                    "type": "string",
-                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                "rangeStep": {
+                    "anyOf": [
+                        {
+                            "type": "number",
+                            "minimum": 0
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "Default range step for band and point scales of (1) the `y` channel\nand (2) the `x` channel when the mark is not `text`.\n\n__Default value:__ `21`"
                 },
-                "filled": {
+                "round": {
                     "type": "boolean",
-                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                    "description": "If true, rounds numeric output values to integers.\nThis can be helpful for snapping to the pixel grid.\n(Only available for `x`, `y`, and `size` scales.)"
                 },
-                "fillOpacity": {
+                "textXRangeStep": {
                     "type": "number",
                     "minimum": 0,
-                    "maximum": 1,
-                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                    "description": "Default range step for `x` band and point scales of text marks.\n\n__Default value:__ `90`"
                 },
-                "font": {
-                    "type": "string",
-                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
+                "useUnaggregatedDomain": {
+                    "type": "boolean",
+                    "description": "Use the source data range before aggregation as scale domain instead of aggregated data\nfor aggregate axis.\n\nThis is equivalent to setting `domain` to `\"unaggregate\"` for aggregated _quantitative_\nfields by default.\n\nThis property only works with aggregate functions that produce values within the raw data\ndomain (`\"mean\"`, `\"average\"`, `\"median\"`, `\"q1\"`, `\"q3\"`, `\"min\"`, `\"max\"`). For other\naggregations that produce values outside of the raw data domain (e.g. `\"count\"`,\n`\"sum\"`), this property is ignored.\n\n__Default value:__ `false`"
+                }
+            },
+            "required": [],
+            "title": "ScaleConfig",
+            "description": "Scale configuration determines default properties for all [scales](scale.html). For a full list of scale configuration options, please see the [corresponding section of the scale documentation](scale.html#config)."
+        },
+        "SelectionConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "interval": {
+                    "$ref": "#/definitions/IntervalSelectionConfig",
+                    "description": "The default definition for an [`interval`](selection.html#type) selection. All properties\nand transformations\nfor an interval selection definition (except `type`) may be specified here.\n\nFor instance, setting `interval` to `{\"translate\": false}` disables the ability to move\ninterval selections by default."
                 },
-                "fontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The font size, in pixels."
+                "multi": {
+                    "$ref": "#/definitions/MultiSelectionConfig",
+                    "description": "The default definition for a [`multi`](selection.html#type) selection. All properties and\ntransformations\nfor a multi selection definition (except `type`) may be specified here.\n\nFor instance, setting `multi` to `{\"toggle\": \"event.altKey\"}` adds additional values to\nmulti selections when clicking with the alt-key pressed by default."
                 },
-                "fontStyle": {
-                    "$ref": "#/definitions/FontStyle",
-                    "description": "The font style (e.g., `\"italic\"`)."
+                "single": {
+                    "$ref": "#/definitions/SingleSelectionConfig",
+                    "description": "The default definition for a [`single`](selection.html#type) selection. All properties\nand transformations\nfor a single selection definition (except `type`) may be specified here.\n\nFor instance, setting `single` to `{\"on\": \"dblclick\"}` populates single selections on\ndouble-click by default."
+                }
+            },
+            "required": [],
+            "title": "SelectionConfig",
+            "description": "An object hash for defining default properties for each type of selections. "
+        },
+        "IntervalSelectionConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "bind": {
+                    "$ref": "#/definitions/Bind",
+                    "description": "Establishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
                 },
-                "fontWeight": {
-                    "$ref": "#/definitions/FontWeightUnion",
-                    "description": "The font weight (e.g., `\"bold\"`)."
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
                 },
-                "href": {
-                    "type": "string",
-                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
                 },
-                "interpolate": {
-                    "$ref": "#/definitions/Interpolate",
-                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                "fields": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
                 },
-                "limit": {
-                    "type": "number",
-                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
+                "mark": {
+                    "$ref": "#/definitions/BrushConfig",
+                    "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
                 },
-                "opacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
                 },
-                "orient": {
-                    "$ref": "#/definitions/Orient",
-                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
                 },
-                "radius": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                "translate": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "When truthy, allows a user to interactively move an interval selection\nback-and-forth. Can be `true`, `false` (to disable panning), or a\n[Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)\nwhich must include a start and end event to trigger continuous panning.\n\n__Default value:__ `true`, which corresponds to\n`[mousedown, window:mouseup] > window:mousemove!` which corresponds to\nclicks and dragging within an interval selection to reposition it."
                 },
-                "shape": {
+                "zoom": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "When truthy, allows a user to interactively resize an interval selection.\nCan be `true`, `false` (to disable zooming), or a [Vega event stream\ndefinition](https://vega.github.io/vega/docs/event-streams/). Currently,\nonly `wheel` events are supported.\n\n\n__Default value:__ `true`, which corresponds to `wheel!`."
+                }
+            },
+            "required": [],
+            "title": "IntervalSelectionConfig",
+            "description": "The default definition for an [`interval`](selection.html#type) selection. All properties and transformations\nfor an interval selection definition (except `type`) may be specified here.\n\nFor instance, setting `interval` to `{\"translate\": false}` disables the ability to move\ninterval selections by default."
+        },
+        "BrushConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "fill": {
                     "type": "string",
-                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
-                },
-                "shortTimeLabels": {
-                    "type": "boolean",
-                    "description": "Whether month names and weekday names should be abbreviated."
+                    "description": "The fill color of the interval mark.\n\n__Default value:__ `#333333`"
                 },
-                "size": {
+                "fillOpacity": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
+                    "description": "The fill opacity of the interval mark (a value between 0 and 1).\n\n__Default value:__ `0.125`"
                 },
                 "stroke": {
                     "type": "string",
-                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                    "description": "The stroke color of the interval mark.\n\n__Default value:__ `#ffffff`"
                 },
                 "strokeDash": {
                     "type": "array",
                     "items": {
                         "type": "number"
                     },
-                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
+                    "description": "An array of alternating stroke and space lengths,\nfor creating dashed or dotted lines."
                 },
                 "strokeDashOffset": {
                     "type": "number",
-                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
+                    "description": "The offset (in pixels) with which to begin drawing the stroke dash array."
                 },
                 "strokeOpacity": {
                     "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                    "description": "The stroke opacity of the interval mark (a value between 0 and 1)."
                 },
                 "strokeWidth": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "The stroke width, in pixels."
-                },
-                "tension": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
-                },
-                "text": {
-                    "type": "string",
-                    "description": "Placeholder text if the `text` channel is not specified"
-                },
-                "theta": {
-                    "type": "number",
-                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
+                    "description": "The stroke width of the interval mark."
                 }
             },
             "required": [],
-            "title": "TextConfig",
-            "description": "Text-Specific Config "
+            "title": "BrushConfig",
+            "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
         },
-        "TickConfig": {
+        "MultiSelectionConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                },
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                },
+                "fields": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
+                },
+                "nearest": {
+                    "type": "boolean",
+                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
+                },
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                },
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                },
+                "toggle": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "Controls whether data values should be toggled or only ever inserted into\nmulti selections. Can be `true`, `false` (for insertion only), or a\n[Vega expression](https://vega.github.io/vega/docs/expressions/).\n\n__Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,\ndata values are toggled when a user interacts with the shift-key pressed).\n\nSee the [toggle transform](toggle.html) documentation for more information."
+                }
+            },
+            "required": [],
+            "title": "MultiSelectionConfig",
+            "description": "The default definition for a [`multi`](selection.html#type) selection. All properties and transformations\nfor a multi selection definition (except `type`) may be specified here.\n\nFor instance, setting `multi` to `{\"toggle\": \"event.altKey\"}` adds additional values to\nmulti selections when clicking with the alt-key pressed by default."
+        },
+        "SingleSelectionConfig": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "bind": {
+                    "type": "object",
+                    "additionalProperties": {
+                        "$ref": "#/definitions/VGBinding"
+                    },
+                    "description": "Establish a two-way binding between a single selection and input elements\n(also known as dynamic query widgets). A binding takes the form of\nVega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)\nor can be a mapping between projected field/encodings and binding definitions.\n\nSee the [bind transform](bind.html) documentation for more information."
+                },
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                },
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                },
+                "fields": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
+                },
+                "nearest": {
+                    "type": "boolean",
+                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
+                },
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                },
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                }
+            },
+            "required": [],
+            "title": "SingleSelectionConfig",
+            "description": "The default definition for a [`single`](selection.html#type) selection. All properties and transformations\n  for a single selection definition (except `type`) may be specified here.\n\nFor instance, setting `single` to `{\"on\": \"dblclick\"}` populates single selections on double-click by default."
+        },
+        "VGCheckboxBinding": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "element": {
+                    "type": "string"
+                },
+                "input": {
+                    "$ref": "#/definitions/PurpleInput"
+                }
+            },
+            "required": [
+                "input"
+            ],
+            "title": "VGCheckboxBinding"
+        },
+        "VGRadioBinding": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "element": {
+                    "type": "string"
+                },
+                "input": {
+                    "$ref": "#/definitions/FluffyInput"
+                },
+                "options": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            },
+            "required": [
+                "input",
+                "options"
+            ],
+            "title": "VGRadioBinding"
+        },
+        "VGSelectBinding": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "element": {
+                    "type": "string"
+                },
+                "input": {
+                    "$ref": "#/definitions/TentacledInput"
+                },
+                "options": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            },
+            "required": [
+                "input",
+                "options"
+            ],
+            "title": "VGSelectBinding"
+        },
+        "VGRangeBinding": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "element": {
+                    "type": "string"
+                },
+                "input": {
+                    "$ref": "#/definitions/StickyInput"
+                },
+                "max": {
+                    "type": "number"
+                },
+                "min": {
+                    "type": "number"
+                },
+                "step": {
+                    "type": "number"
+                }
+            },
+            "required": [
+                "input"
+            ],
+            "title": "VGRangeBinding"
+        },
+        "VGGenericBinding": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "element": {
+                    "type": "string"
+                },
+                "input": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "input"
+            ],
+            "title": "VGGenericBinding"
+        },
+        "VGMarkConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
@@ -1921,19 +2024,10 @@
                     "maximum": 360,
                     "description": "The rotation angle of the text, in degrees."
                 },
-                "bandSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The width of the ticks.\n\n__Default value:__  2/3 of rangeStep."
-                },
                 "baseline": {
                     "$ref": "#/definitions/VerticalAlign",
                     "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
                 },
-                "color": {
-                    "type": "string",
-                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
                 "cursor": {
                     "$ref": "#/definitions/Cursor",
                     "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
@@ -1950,10 +2044,6 @@
                     "type": "string",
                     "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
                 },
-                "filled": {
-                    "type": "boolean",
-                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
                 "fillOpacity": {
                     "type": "number",
                     "minimum": 0,
@@ -2052,1838 +2142,2700 @@
                 "theta": {
                     "type": "number",
                     "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
-                },
-                "thickness": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Thickness of the tick mark.\n\n__Default value:__  `1`"
                 }
             },
             "required": [],
-            "title": "TickConfig",
-            "description": "Tick-Specific Config "
+            "title": "VGMarkConfig"
         },
-        "VGTitleConfig": {
+        "TextConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "anchor": {
-                    "$ref": "#/definitions/Anchor",
-                    "description": "The anchor position for placing the title. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For\nexample, with an orientation of top these anchor positions map to a left-, center-, or\nright-aligned title.\n\n__Default value:__ `\"middle\"` for [single](spec.html) and [layered](layer.html) views.\n`\"start\"` for other composite views.\n\n__Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only\ncustomizable only for [single](spec.html) and [layered](layer.html) views.  For other\ncomposite views, `anchor` is always `\"start\"`."
+                "align": {
+                    "$ref": "#/definitions/HorizontalAlign",
+                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
                 },
                 "angle": {
                     "type": "number",
-                    "description": "Angle in degrees of title text."
+                    "minimum": 0,
+                    "maximum": 360,
+                    "description": "The rotation angle of the text, in degrees."
                 },
                 "baseline": {
                     "$ref": "#/definitions/VerticalAlign",
-                    "description": "Vertical text baseline for title text."
+                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
                 },
                 "color": {
                     "type": "string",
-                    "description": "Text color for title text."
+                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "cursor": {
+                    "$ref": "#/definitions/Cursor",
+                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                },
+                "dx": {
+                    "type": "number",
+                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "dy": {
+                    "type": "number",
+                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "fill": {
+                    "type": "string",
+                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                },
+                "filled": {
+                    "type": "boolean",
+                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "fillOpacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
                 },
                 "font": {
                     "type": "string",
-                    "description": "Font name for title text."
+                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
                 },
                 "fontSize": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "Font size in pixels for title text.\n\n__Default value:__ `10`."
+                    "description": "The font size, in pixels."
+                },
+                "fontStyle": {
+                    "$ref": "#/definitions/FontStyle",
+                    "description": "The font style (e.g., `\"italic\"`)."
                 },
                 "fontWeight": {
                     "$ref": "#/definitions/FontWeightUnion",
-                    "description": "Font weight for title text."
+                    "description": "The font weight (e.g., `\"bold\"`)."
                 },
-                "limit": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The maximum allowed length in pixels of legend labels."
+                "href": {
+                    "type": "string",
+                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
                 },
-                "offset": {
+                "interpolate": {
+                    "$ref": "#/definitions/Interpolate",
+                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                },
+                "limit": {
                     "type": "number",
-                    "description": "Offset in pixels of the title from the chart body and axes."
+                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
+                },
+                "opacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
                 },
                 "orient": {
-                    "$ref": "#/definitions/TitleOrient",
-                    "description": "Default title orientation (\"top\", \"bottom\", \"left\", or \"right\")"
-                }
-            },
-            "required": [],
-            "title": "VGTitleConfig",
-            "description": "Title configuration, which determines default properties for all [titles](title.html). For a full list of title configuration options, please see the [corresponding section of the title documentation](title.html#config)."
-        },
-        "ViewConfig": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "clip": {
-                    "type": "boolean",
-                    "description": "Whether the view should be clipped."
+                    "$ref": "#/definitions/Orient",
+                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
                 },
-                "fill": {
+                "radius": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                },
+                "shape": {
                     "type": "string",
-                    "description": "The fill color.\n\n__Default value:__ (none)"
+                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
                 },
-                "fillOpacity": {
-                    "type": "number",
-                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ (none)"
+                "shortTimeLabels": {
+                    "type": "boolean",
+                    "description": "Whether month names and weekday names should be abbreviated."
                 },
-                "height": {
+                "size": {
                     "type": "number",
-                    "description": "The default height of the single plot or each plot in a trellis plot when the\nvisualization has a continuous (non-ordinal) y-scale with `rangeStep` = `null`.\n\n__Default value:__ `200`"
+                    "minimum": 0,
+                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
                 },
                 "stroke": {
                     "type": "string",
-                    "description": "The stroke color.\n\n__Default value:__ (none)"
+                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
                 },
                 "strokeDash": {
                     "type": "array",
                     "items": {
                         "type": "number"
                     },
-                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines.\n\n__Default value:__ (none)"
+                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
                 },
                 "strokeDashOffset": {
                     "type": "number",
-                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array.\n\n__Default value:__ (none)"
+                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
                 },
                 "strokeOpacity": {
                     "type": "number",
-                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ (none)"
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
                 },
                 "strokeWidth": {
                     "type": "number",
-                    "description": "The stroke width, in pixels.\n\n__Default value:__ (none)"
+                    "minimum": 0,
+                    "description": "The stroke width, in pixels."
                 },
-                "width": {
+                "tension": {
                     "type": "number",
-                    "description": "The default width of the single plot or each plot in a trellis plot when the\nvisualization has a continuous (non-ordinal) x-scale or ordinal x-scale with `rangeStep`\n= `null`.\n\n__Default value:__ `200`"
-                }
-            },
-            "required": [],
-            "title": "ViewConfig",
-            "description": "Default properties for [single view plots](spec.html#single). "
-        },
-        "Data": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "format": {
-                    "$ref": "#/definitions/DataFormat",
-                    "description": "An object that specifies the format for parsing the data file.\n\nAn object that specifies the format for parsing the data values.\n\nAn object that specifies the format for parsing the data."
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
                 },
-                "url": {
+                "text": {
                     "type": "string",
-                    "description": "An URL from which to load the data set. Use the `format.type` property\nto ensure the loaded data is correctly parsed."
-                },
-                "values": {
-                    "$ref": "#/definitions/Values",
-                    "description": "The full data set, included inline. This can be an array of objects or primitive values\nor a string.\nArrays of primitive values are ingested as objects with a `data` property. Strings are\nparsed according to the specified format type."
+                    "description": "Placeholder text if the `text` channel is not specified"
                 },
-                "name": {
-                    "type": "string",
-                    "description": "Provide a placeholder name and bind data at runtime."
+                "theta": {
+                    "type": "number",
+                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
                 }
             },
             "required": [],
-            "title": "Data",
-            "description": "An object describing the data source\nSecondary data source to lookup in."
+            "title": "TextConfig",
+            "description": "Text-Specific Config "
         },
-        "DataFormat": {
+        "TickConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "parse": {
-                    "$ref": "#/definitions/ParseUnion",
-                    "description": "If set to auto (the default), perform automatic type inference to determine the desired\ndata types.\nAlternatively, a parsing directive object can be provided for explicit data types. Each\nproperty of the object corresponds to a field name, and the value to the desired data\ntype (one of `\"number\"`, `\"boolean\"` or `\"date\"`).\nFor example, `\"parse\": {\"modified_on\": \"date\"}` parses the `modified_on` field in each\ninput record a Date value.\n\nFor `\"date\"`, we parse data based using Javascript's\n[`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).\nFor Specific date formats can be provided (e.g., `{foo: 'date:\"%m%d%Y\"'}`), using the\n[d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date\nformat parsing is supported similarly (e.g., `{foo: 'utc:\"%m%d%Y\"'}`). See more about\n[UTC time](timeunit.html#utc)"
+                "align": {
+                    "$ref": "#/definitions/HorizontalAlign",
+                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
                 },
-                "type": {
-                    "$ref": "#/definitions/DataFormatType",
-                    "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
+                "angle": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 360,
+                    "description": "The rotation angle of the text, in degrees."
                 },
-                "property": {
+                "bandSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The width of the ticks.\n\n__Default value:__  2/3 of rangeStep."
+                },
+                "baseline": {
+                    "$ref": "#/definitions/VerticalAlign",
+                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
+                },
+                "color": {
                     "type": "string",
-                    "description": "The JSON property containing the desired data.\nThis parameter can be used when the loaded JSON file may have surrounding structure or\nmeta-data.\nFor example `\"property\": \"values.features\"` is equivalent to retrieving\n`json.values.features`\nfrom the loaded JSON object."
+                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
                 },
-                "feature": {
+                "cursor": {
+                    "$ref": "#/definitions/Cursor",
+                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                },
+                "dx": {
+                    "type": "number",
+                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "dy": {
+                    "type": "number",
+                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "fill": {
                     "type": "string",
-                    "description": "The name of the TopoJSON object set to convert to a GeoJSON feature collection.\nFor example, in a map of the world, there may be an object set named `\"countries\"`.\nUsing the feature property, we can extract this set and generate a GeoJSON feature object\nfor each country."
+                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
                 },
-                "mesh": {
+                "filled": {
+                    "type": "boolean",
+                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "fillOpacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                },
+                "font": {
                     "type": "string",
-                    "description": "The name of the TopoJSON object set to convert to mesh.\nSimilar to the `feature` option, `mesh` extracts a named TopoJSON object set.\nUnlike the `feature` option, the corresponding geo data is returned as a single, unified\nmesh instance, not as individual GeoJSON features.\nExtracting a mesh is useful for more efficiently drawing borders or other geographic\nelements that you do not need to associate with specific regions such as individual\ncountries, states or counties."
-                }
-            },
-            "required": [],
-            "title": "DataFormat",
-            "description": "An object that specifies the format for parsing the data file.\nAn object that specifies the format for parsing the data values.\nAn object that specifies the format for parsing the data."
-        },
-        "EncodingWithFacet": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "color": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark\nconfig](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color\nscheme](scale.html#scheme)."
+                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
                 },
-                "column": {
-                    "$ref": "#/definitions/FacetFieldDef",
-                    "description": "Horizontal facets for trellis plots."
+                "fontSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The font size, in pixels."
                 },
-                "detail": {
-                    "$ref": "#/definitions/Detail",
-                    "description": "Additional levels of detail for grouping data in aggregate views and\nin line and area marks without mapping data to a specific visual channel."
+                "fontStyle": {
+                    "$ref": "#/definitions/FontStyle",
+                    "description": "The font style (e.g., `\"italic\"`)."
+                },
+                "fontWeight": {
+                    "$ref": "#/definitions/FontWeightUnion",
+                    "description": "The font weight (e.g., `\"bold\"`)."
                 },
                 "href": {
-                    "$ref": "#/definitions/DefWithCondition",
-                    "description": "A URL to load upon mouse click."
+                    "type": "string",
+                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
+                },
+                "interpolate": {
+                    "$ref": "#/definitions/Interpolate",
+                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                },
+                "limit": {
+                    "type": "number",
+                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
                 },
                 "opacity": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Opacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark\nconfig](config.html#mark)'s `opacity` property."
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
                 },
-                "order": {
-                    "$ref": "#/definitions/Order",
-                    "description": "Stack order for stacked marks or order of data points in line marks for connected scatter\nplots.\n\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating\nadditional aggregation grouping."
+                "orient": {
+                    "$ref": "#/definitions/Orient",
+                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
                 },
-                "row": {
-                    "$ref": "#/definitions/FacetFieldDef",
-                    "description": "Vertical facets for trellis plots."
+                "radius": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
                 },
                 "shape": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "For `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark\nconfig](config.html#point-config)'s `shape` property."
+                    "type": "string",
+                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
                 },
                 "size": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Size of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`."
-                },
-                "text": {
-                    "$ref": "#/definitions/TextDefWithCondition",
-                    "description": "Text of the `text` mark."
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
                 },
-                "tooltip": {
-                    "$ref": "#/definitions/TextDefWithCondition",
-                    "description": "The tooltip text to show upon mouse hover."
+                "stroke": {
+                    "type": "string",
+                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
                 },
-                "x": {
-                    "$ref": "#/definitions/XClass",
-                    "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`."
+                "strokeDash": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
                 },
-                "x2": {
-                    "$ref": "#/definitions/X2Class",
-                    "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+                "strokeDashOffset": {
+                    "type": "number",
+                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
                 },
-                "y": {
-                    "$ref": "#/definitions/XClass",
-                    "description": "Y coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`."
+                "strokeOpacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
                 },
-                "y2": {
-                    "$ref": "#/definitions/X2Class",
-                    "description": "Y2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+                "strokeWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The stroke width, in pixels."
+                },
+                "tension": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
+                },
+                "text": {
+                    "type": "string",
+                    "description": "Placeholder text if the `text` channel is not specified"
+                },
+                "theta": {
+                    "type": "number",
+                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
+                },
+                "thickness": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Thickness of the tick mark.\n\n__Default value:__  `1`"
                 }
             },
             "required": [],
-            "title": "EncodingWithFacet",
-            "description": "A key-value mapping between encoding channels and definition of fields."
+            "title": "TickConfig",
+            "description": "Tick-Specific Config "
         },
-        "MarkPropDefWithCondition": {
+        "VGTitleConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                "anchor": {
+                    "$ref": "#/definitions/Anchor",
+                    "description": "The anchor position for placing the title. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For\nexample, with an orientation of top these anchor positions map to a left-, center-, or\nright-aligned title.\n\n__Default value:__ `\"middle\"` for [single](spec.html) and [layered](layer.html) views.\n`\"start\"` for other composite views.\n\n__Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only\ncustomizable only for [single](spec.html) and [layered](layer.html) views.  For other\ncomposite views, `anchor` is always `\"start\"`."
                 },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                "angle": {
+                    "type": "number",
+                    "description": "Angle in degrees of title text."
                 },
-                "condition": {
-                    "$ref": "#/definitions/ColorCondition",
-                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel.\n\nA field definition or one or more value definition(s) with a selection predicate."
+                "baseline": {
+                    "$ref": "#/definitions/VerticalAlign",
+                    "description": "Vertical text baseline for title text."
                 },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                "color": {
+                    "type": "string",
+                    "description": "Text color for title text."
                 },
-                "legend": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/Legend"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
+                "font": {
+                    "type": "string",
+                    "description": "Font name for title text."
                 },
-                "scale": {
-                    "$ref": "#/definitions/Scale",
-                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+                "fontSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Font size in pixels for title text.\n\n__Default value:__ `10`."
                 },
-                "sort": {
-                    "$ref": "#/definitions/SortUnion",
-                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
+                "fontWeight": {
+                    "$ref": "#/definitions/FontWeightUnion",
+                    "description": "Font weight for title text."
                 },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                "limit": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The maximum allowed length in pixels of legend labels."
                 },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "offset": {
+                    "type": "number",
+                    "description": "Offset in pixels of the title from the chart body and axes."
                 },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain."
+                "orient": {
+                    "$ref": "#/definitions/TitleOrient",
+                    "description": "Default title orientation (\"top\", \"bottom\", \"left\", or \"right\")"
                 }
             },
             "required": [],
-            "title": "MarkPropDefWithCondition",
-            "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark config](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color scheme](scale.html#scheme).\nOpacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark config](config.html#mark)'s `opacity` property.\nFor `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark config](config.html#point-config)'s `shape` property.\nSize of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`.\nA FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}\nA ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+            "title": "VGTitleConfig",
+            "description": "Title configuration, which determines default properties for all [titles](title.html). For a full list of title configuration options, please see the [corresponding section of the title documentation](title.html#config)."
         },
-        "BinParams": {
+        "ViewConfig": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "base": {
+                "clip": {
+                    "type": "boolean",
+                    "description": "Whether the view should be clipped."
+                },
+                "fill": {
+                    "type": "string",
+                    "description": "The fill color.\n\n__Default value:__ (none)"
+                },
+                "fillOpacity": {
                     "type": "number",
-                    "description": "The number base to use for automatic bin determination (default is base 10).\n\n__Default value:__ `10`"
+                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ (none)"
                 },
-                "divide": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "minItems": 1,
-                    "description": "Scale factors indicating allowable subdivisions. The default value is [5, 2], which\nindicates that for base 10 numbers (the default base), the method may consider dividing\nbin sizes by 5 and/or 2. For example, for an initial step size of 10, the method can\ncheck if bin sizes of 2 (= 10/5), 5 (= 10/2), or 1 (= 10/(5*2)) might also satisfy the\ngiven constraints.\n\n__Default value:__ `[5, 2]`"
+                "height": {
+                    "type": "number",
+                    "description": "The default height of the single plot or each plot in a trellis plot when the\nvisualization has a continuous (non-ordinal) y-scale with `rangeStep` = `null`.\n\n__Default value:__ `200`"
                 },
-                "extent": {
+                "stroke": {
+                    "type": "string",
+                    "description": "The stroke color.\n\n__Default value:__ (none)"
+                },
+                "strokeDash": {
                     "type": "array",
                     "items": {
                         "type": "number"
                     },
-                    "minItems": 2,
-                    "maxItems": 2,
-                    "description": "A two-element (`[min, max]`) array indicating the range of desired bin values."
+                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines.\n\n__Default value:__ (none)"
                 },
-                "maxbins": {
+                "strokeDashOffset": {
                     "type": "number",
-                    "minimum": 2,
-                    "description": "Maximum number of bins.\n\n__Default value:__ `6` for `row`, `column` and `shape` channels; `10` for other channels"
+                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array.\n\n__Default value:__ (none)"
                 },
-                "minstep": {
+                "strokeOpacity": {
                     "type": "number",
-                    "description": "A minimum allowable step size (particularly useful for integer values)."
-                },
-                "nice": {
-                    "type": "boolean",
-                    "description": "If true (the default), attempts to make the bin boundaries use human-friendly boundaries,\nsuch as multiples of ten."
+                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ (none)"
                 },
-                "step": {
+                "strokeWidth": {
                     "type": "number",
-                    "description": "An exact step size to use between bins.\n\n__Note:__ If provided, options such as maxbins will be ignored."
+                    "description": "The stroke width, in pixels.\n\n__Default value:__ (none)"
                 },
-                "steps": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "minItems": 1,
-                    "description": "An array of allowable step sizes to choose from."
+                "width": {
+                    "type": "number",
+                    "description": "The default width of the single plot or each plot in a trellis plot when the\nvisualization has a continuous (non-ordinal) x-scale or ordinal x-scale with `rangeStep`\n= `null`.\n\n__Default value:__ `200`"
                 }
             },
             "required": [],
-            "title": "BinParams",
-            "description": "Binning properties or boolean flag for determining whether to bin data or not."
+            "title": "ViewConfig",
+            "description": "Default properties for [single view plots](spec.html#single). "
         },
-        "ConditionalValueDef": {
+        "URLData": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "test": {
-                    "$ref": "#/definitions/LogicalOperandPredicate"
-                },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
+                "format": {
+                    "$ref": "#/definitions/DataFormat",
+                    "description": "An object that specifies the format for parsing the data file."
                 },
-                "selection": {
-                    "$ref": "#/definitions/SelectionOperand",
-                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
+                "url": {
+                    "type": "string",
+                    "description": "An URL from which to load the data set. Use the `format.type` property\nto ensure the loaded data is correctly parsed."
                 }
             },
             "required": [
-                "value"
+                "url"
             ],
-            "title": "ConditionalValueDef"
+            "title": "URLData"
         },
-        "ConditionalPredicateMarkPropFieldDefClass": {
+        "InlineData": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "test": {
-                    "$ref": "#/definitions/LogicalOperandPredicate"
-                },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
-                },
-                "selection": {
-                    "$ref": "#/definitions/SelectionOperand",
-                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
-                },
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "legend": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/Legend"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
-                },
-                "scale": {
-                    "$ref": "#/definitions/Scale",
-                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
-                },
-                "sort": {
-                    "$ref": "#/definitions/SortUnion",
-                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                "format": {
+                    "$ref": "#/definitions/DataFormat",
+                    "description": "An object that specifies the format for parsing the data values."
                 },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "values": {
+                    "$ref": "#/definitions/Values",
+                    "description": "The full data set, included inline. This can be an array of objects or primitive values\nor a string.\nArrays of primitive values are ingested as objects with a `data` property. Strings are\nparsed according to the specified format type."
                 }
             },
-            "required": [],
-            "title": "ConditionalPredicateMarkPropFieldDefClass"
+            "required": [
+                "values"
+            ],
+            "title": "InlineData"
         },
-        "Selection": {
+        "NamedData": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "not": {
-                    "$ref": "#/definitions/SelectionOperand"
-                },
-                "and": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/SelectionOperand"
-                    }
+                "format": {
+                    "$ref": "#/definitions/DataFormat",
+                    "description": "An object that specifies the format for parsing the data."
                 },
-                "or": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/SelectionOperand"
-                    }
+                "name": {
+                    "type": "string",
+                    "description": "Provide a placeholder name and bind data at runtime."
                 }
             },
-            "required": [],
-            "title": "Selection"
+            "required": [
+                "name"
+            ],
+            "title": "NamedData"
         },
-        "Predicate": {
+        "CSVDataFormat": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "not": {
-                    "$ref": "#/definitions/LogicalOperandPredicate"
-                },
-                "and": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/LogicalOperandPredicate"
-                    }
-                },
-                "or": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/LogicalOperandPredicate"
-                    }
+                "parse": {
+                    "$ref": "#/definitions/ParseUnion",
+                    "description": "If set to auto (the default), perform automatic type inference to determine the desired\ndata types.\nAlternatively, a parsing directive object can be provided for explicit data types. Each\nproperty of the object corresponds to a field name, and the value to the desired data\ntype (one of `\"number\"`, `\"boolean\"` or `\"date\"`).\nFor example, `\"parse\": {\"modified_on\": \"date\"}` parses the `modified_on` field in each\ninput record a Date value.\n\nFor `\"date\"`, we parse data based using Javascript's\n[`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).\nFor Specific date formats can be provided (e.g., `{foo: 'date:\"%m%d%Y\"'}`), using the\n[d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date\nformat parsing is supported similarly (e.g., `{foo: 'utc:\"%m%d%Y\"'}`). See more about\n[UTC time](timeunit.html#utc)"
                 },
-                "equal": {
-                    "$ref": "#/definitions/Equal",
-                    "description": "The value that the field should be equal to."
+                "type": {
+                    "$ref": "#/definitions/PurpleType",
+                    "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
+                }
+            },
+            "required": [],
+            "title": "CSVDataFormat"
+        },
+        "JSONDataFormat": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "parse": {
+                    "$ref": "#/definitions/ParseUnion",
+                    "description": "If set to auto (the default), perform automatic type inference to determine the desired\ndata types.\nAlternatively, a parsing directive object can be provided for explicit data types. Each\nproperty of the object corresponds to a field name, and the value to the desired data\ntype (one of `\"number\"`, `\"boolean\"` or `\"date\"`).\nFor example, `\"parse\": {\"modified_on\": \"date\"}` parses the `modified_on` field in each\ninput record a Date value.\n\nFor `\"date\"`, we parse data based using Javascript's\n[`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).\nFor Specific date formats can be provided (e.g., `{foo: 'date:\"%m%d%Y\"'}`), using the\n[d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date\nformat parsing is supported similarly (e.g., `{foo: 'utc:\"%m%d%Y\"'}`). See more about\n[UTC time](timeunit.html#utc)"
                 },
-                "field": {
+                "property": {
                     "type": "string",
-                    "description": "Field to be filtered.\n\nField to be filtered"
+                    "description": "The JSON property containing the desired data.\nThis parameter can be used when the loaded JSON file may have surrounding structure or\nmeta-data.\nFor example `\"property\": \"values.features\"` is equivalent to retrieving\n`json.values.features`\nfrom the loaded JSON object."
                 },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit for the field to be filtered.\n\ntime unit for the field to be filtered."
+                "type": {
+                    "$ref": "#/definitions/FluffyType",
+                    "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
+                }
+            },
+            "required": [],
+            "title": "JSONDataFormat"
+        },
+        "TopoDataFormat": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "feature": {
+                    "type": "string",
+                    "description": "The name of the TopoJSON object set to convert to a GeoJSON feature collection.\nFor example, in a map of the world, there may be an object set named `\"countries\"`.\nUsing the feature property, we can extract this set and generate a GeoJSON feature object\nfor each country."
                 },
-                "range": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/RangeElement"
-                    },
-                    "minItems": 2,
-                    "maxItems": 2,
-                    "description": "An array of inclusive minimum and maximum values\nfor a field value of a data item to be included in the filtered data."
+                "mesh": {
+                    "type": "string",
+                    "description": "The name of the TopoJSON object set to convert to mesh.\nSimilar to the `feature` option, `mesh` extracts a named TopoJSON object set.\nUnlike the `feature` option, the corresponding geo data is returned as a single, unified\nmesh instance, not as individual GeoJSON features.\nExtracting a mesh is useful for more efficiently drawing borders or other geographic\nelements that you do not need to associate with specific regions such as individual\ncountries, states or counties."
                 },
-                "oneOf": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/Equal"
-                    },
-                    "description": "A set of values that the `field`'s value should be a member of,\nfor a data item included in the filtered data."
+                "parse": {
+                    "$ref": "#/definitions/ParseUnion",
+                    "description": "If set to auto (the default), perform automatic type inference to determine the desired\ndata types.\nAlternatively, a parsing directive object can be provided for explicit data types. Each\nproperty of the object corresponds to a field name, and the value to the desired data\ntype (one of `\"number\"`, `\"boolean\"` or `\"date\"`).\nFor example, `\"parse\": {\"modified_on\": \"date\"}` parses the `modified_on` field in each\ninput record a Date value.\n\nFor `\"date\"`, we parse data based using Javascript's\n[`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).\nFor Specific date formats can be provided (e.g., `{foo: 'date:\"%m%d%Y\"'}`), using the\n[d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date\nformat parsing is supported similarly (e.g., `{foo: 'utc:\"%m%d%Y\"'}`). See more about\n[UTC time](timeunit.html#utc)"
                 },
-                "selection": {
-                    "$ref": "#/definitions/SelectionOperand",
-                    "description": "Filter using a selection name."
+                "type": {
+                    "$ref": "#/definitions/TentacledType",
+                    "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
                 }
             },
             "required": [],
-            "title": "Predicate"
+            "title": "TopoDataFormat"
         },
-        "DateTime": {
+        "EncodingWithFacet": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "date": {
-                    "type": "number",
-                    "minimum": 1,
-                    "maximum": 31,
-                    "description": "Integer value representing the date from 1-31."
+                "color": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark\nconfig](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color\nscheme](scale.html#scheme)."
                 },
-                "day": {
-                    "$ref": "#/definitions/Day",
-                    "description": "Value representing the day of a week.  This can be one of: (1) integer value -- `1`\nrepresents Monday; (2) case-insensitive day name (e.g., `\"Monday\"`);  (3)\ncase-insensitive, 3-character short day name (e.g., `\"Mon\"`).   <br/> **Warning:** A\nDateTime definition object with `day`** should not be combined with `year`, `quarter`,\n`month`, or `date`."
+                "column": {
+                    "$ref": "#/definitions/FacetFieldDef",
+                    "description": "Horizontal facets for trellis plots."
                 },
-                "hours": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 23,
-                    "description": "Integer value representing the hour of a day from 0-23."
+                "detail": {
+                    "$ref": "#/definitions/Detail",
+                    "description": "Additional levels of detail for grouping data in aggregate views and\nin line and area marks without mapping data to a specific visual channel."
                 },
-                "milliseconds": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 999,
-                    "description": "Integer value representing the millisecond segment of time."
+                "href": {
+                    "$ref": "#/definitions/Href",
+                    "description": "A URL to load upon mouse click."
                 },
-                "minutes": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 59,
-                    "description": "Integer value representing the minute segment of time from 0-59."
+                "opacity": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Opacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark\nconfig](config.html#mark)'s `opacity` property."
                 },
-                "month": {
-                    "$ref": "#/definitions/Month",
-                    "description": "One of: (1) integer value representing the month from `1`-`12`. `1` represents January;\n(2) case-insensitive month name (e.g., `\"January\"`);  (3) case-insensitive, 3-character\nshort month name (e.g., `\"Jan\"`)."
+                "order": {
+                    "$ref": "#/definitions/Order",
+                    "description": "Stack order for stacked marks or order of data points in line marks for connected scatter\nplots.\n\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating\nadditional aggregation grouping."
                 },
-                "quarter": {
-                    "type": "number",
-                    "minimum": 1,
-                    "maximum": 4,
-                    "description": "Integer value representing the quarter of the year (from 1-4)."
+                "row": {
+                    "$ref": "#/definitions/FacetFieldDef",
+                    "description": "Vertical facets for trellis plots."
                 },
-                "seconds": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 59,
-                    "description": "Integer value representing the second segment (0-59) of a time value"
+                "shape": {
+                    "$ref": "#/definitions/Color",
+                    "description": "For `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark\nconfig](config.html#point-config)'s `shape` property."
                 },
-                "utc": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if date time is in utc time. If false, the date time is in\nlocal time"
+                "size": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Size of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`."
                 },
-                "year": {
-                    "type": "number",
-                    "description": "Integer value representing the year."
+                "text": {
+                    "$ref": "#/definitions/Text",
+                    "description": "Text of the `text` mark."
+                },
+                "tooltip": {
+                    "$ref": "#/definitions/Text",
+                    "description": "The tooltip text to show upon mouse hover."
+                },
+                "x": {
+                    "$ref": "#/definitions/X",
+                    "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`."
+                },
+                "x2": {
+                    "$ref": "#/definitions/X2",
+                    "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+                },
+                "y": {
+                    "$ref": "#/definitions/X",
+                    "description": "Y coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`."
+                },
+                "y2": {
+                    "$ref": "#/definitions/X2",
+                    "description": "Y2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
                 }
             },
             "required": [],
-            "title": "DateTime",
-            "description": "Object for defining datetime in Vega-Lite Filter.\nIf both month and quarter are provided, month has higher precedence.\n`day` cannot be combined with other date.\nWe accept string for month and day names."
-        },
-        "RepeatRef": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "repeat": {
-                    "$ref": "#/definitions/RepeatEnum"
-                }
-            },
-            "required": [
-                "repeat"
-            ],
-            "title": "RepeatRef",
-            "description": "Reference to a repeated value."
+            "title": "EncodingWithFacet",
+            "description": "A key-value mapping between encoding channels and definition of fields."
         },
-        "Legend": {
+        "MarkPropFieldDefWithCondition": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "entryPadding": {
-                    "type": "number",
-                    "description": "Padding (in pixels) between legend entries in a symbol legend."
-                },
-                "format": {
-                    "type": "string",
-                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
-                },
-                "offset": {
-                    "type": "number",
-                    "description": "The offset, in pixels, by which to displace the legend from the edge of the enclosing\ngroup or data rectangle.\n\n__Default value:__  `0`"
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
                 },
-                "orient": {
-                    "$ref": "#/definitions/LegendOrient",
-                    "description": "The orientation of the legend, which determines how the legend is positioned within the\nscene. One of \"left\", \"right\", \"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\",\n\"none\".\n\n__Default value:__ `\"right\"`"
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
                 },
-                "padding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between the legend and axis."
+                "condition": {
+                    "$ref": "#/definitions/ConditionUnion",
+                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel."
                 },
-                "tickCount": {
-                    "type": "number",
-                    "description": "The desired number of tick values for quantitative legends."
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
                 },
-                "title": {
+                "legend": {
                     "anyOf": [
                         {
-                            "type": "null"
+                            "$ref": "#/definitions/Legend"
                         },
                         {
-                            "type": "string"
+                            "type": "null"
                         }
                     ],
-                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
+                    "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
                 },
-                "type": {
-                    "$ref": "#/definitions/LegendType",
-                    "description": "The type of the legend. Use `\"symbol\"` to create a discrete legend and `\"gradient\"` for a\ncontinuous color gradient.\n\n__Default value:__ `\"gradient\"` for non-binned quantitative fields and temporal fields;\n`\"symbol\"` otherwise."
+                "scale": {
+                    "$ref": "#/definitions/Scale",
+                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
                 },
-                "values": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/LegendValue"
-                    },
-                    "description": "Explicitly set the visible legend values."
+                "sort": {
+                    "$ref": "#/definitions/SortUnion",
+                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
                 },
-                "zindex": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "A non-positive integer indicating z-index of the legend.\nIf zindex is 0, legend should be drawn behind all chart elements.\nTo put them in front, use zindex = 1."
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
                 }
             },
-            "required": [],
-            "title": "Legend",
-            "description": "Properties of a legend or boolean flag for determining whether to show it."
+            "required": [
+                "type"
+            ],
+            "title": "MarkPropFieldDefWithCondition",
+            "description": "A FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}"
         },
-        "Scale": {
+        "MarkPropValueDefWithCondition": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "base": {
-                    "type": "number",
-                    "description": "The logarithm base of the `log` scale (default `10`)."
-                },
-                "clamp": {
-                    "type": "boolean",
-                    "description": "If `true`, values that exceed the data domain are clamped to either the minimum or\nmaximum range value\n\n__Default value:__ derived from the [scale config](config.html#scale-config)'s `clamp`\n(`true` by default)."
+                "condition": {
+                    "$ref": "#/definitions/ColorCondition",
+                    "description": "A field definition or one or more value definition(s) with a selection predicate."
                 },
-                "domain": {
-                    "$ref": "#/definitions/DomainUnion",
-                    "description": "Customized domain values.\n\nFor _quantitative_ fields, `domain` can take the form of a two-element array with minimum\nand maximum values.  [Piecewise scales](scale.html#piecewise) can be created by providing\na `domain` with more than two entries.\nIf the input field is aggregated, `domain` can also be a string value `\"unaggregated\"`,\nindicating that the domain should include the raw data values prior to the aggregation.\n\nFor _temporal_ fields, `domain` can be a two-element array minimum and maximum values, in\nthe form of either timestamps or the [DateTime definition objects](types.html#datetime).\n\nFor _ordinal_ and _nominal_ fields, `domain` can be an array that lists valid input\nvalues.\n\nThe `selection` property can be used to [interactively\ndetermine](selection.html#scale-domains) the scale domain."
-                },
-                "exponent": {
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain."
+                }
+            },
+            "required": [],
+            "title": "MarkPropValueDefWithCondition",
+            "description": "A ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+        },
+        "BinParams": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "base": {
                     "type": "number",
-                    "description": "The exponent of the `pow` scale."
-                },
-                "interpolate": {
-                    "$ref": "#/definitions/InterpolateUnion",
-                    "description": "The interpolation method for range values. By default, a general interpolator for\nnumbers, dates, strings and colors (in RGB space) is used. For color ranges, this\nproperty allows interpolation in alternative color spaces. Legal values include `rgb`,\n`hsl`, `hsl-long`, `lab`, `hcl`, `hcl-long`, `cubehelix` and `cubehelix-long` ('-long'\nvariants use longer paths in polar coordinate spaces). If object-valued, this property\naccepts an object with a string-valued _type_ property and an optional numeric _gamma_\nproperty applicable to rgb and cubehelix interpolators. For more, see the [d3-interpolate\ndocumentation](https://github.com/d3/d3-interpolate).\n\n__Note:__ Sequential scales do not support `interpolate` as they have a fixed\ninterpolator.  Since Vega-Lite uses sequential scales for quantitative fields by default,\nyou have to set the scale `type` to other quantitative scale type such as `\"linear\"` to\ncustomize `interpolate`."
+                    "description": "The number base to use for automatic bin determination (default is base 10).\n\n__Default value:__ `10`"
                 },
-                "nice": {
-                    "$ref": "#/definitions/NiceUnion",
-                    "description": "Extending the domain so that it starts and ends on nice round values. This method\ntypically modifies the scale’s domain, and may only extend the bounds to the nearest\nround value. Nicing is useful if the domain is computed from data and may be irregular.\nFor example, for a domain of _[0.201479…, 0.996679…]_, a nice domain might be _[0.2,\n1.0]_.\n\nFor quantitative scales such as linear, `nice` can be either a boolean flag or a number.\nIf `nice` is a number, it will represent a desired tick count. This allows greater\ncontrol over the step size used to extend the bounds, guaranteeing that the returned\nticks will exactly cover the domain.\n\nFor temporal fields with time and utc scales, the `nice` value can be a string indicating\nthe desired time interval. Legal values are `\"millisecond\"`, `\"second\"`, `\"minute\"`,\n`\"hour\"`, `\"day\"`, `\"week\"`, `\"month\"`, and `\"year\"`. Alternatively, `time` and `utc`\nscales can accept an object-valued interval specifier of the form `{\"interval\": \"month\",\n\"step\": 3}`, which includes a desired number of interval steps. Here, the domain would\nsnap to quarter (Jan, Apr, Jul, Oct) boundaries.\n\n__Default value:__ `true` for unbinned _quantitative_ fields; `false` otherwise."
+                "divide": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "minItems": 1,
+                    "description": "Scale factors indicating allowable subdivisions. The default value is [5, 2], which\nindicates that for base 10 numbers (the default base), the method may consider dividing\nbin sizes by 5 and/or 2. For example, for an initial step size of 10, the method can\ncheck if bin sizes of 2 (= 10/5), 5 (= 10/2), or 1 (= 10/(5*2)) might also satisfy the\ngiven constraints.\n\n__Default value:__ `[5, 2]`"
                 },
-                "padding": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "For _[continuous](scale.html#continuous)_ scales, expands the scale domain to accommodate\nthe specified number of pixels on each of the scale range. The scale range must represent\npixels for this parameter to function as intended. Padding adjustment is performed prior\nto all other adjustments, including the effects of the zero, nice, domainMin, and\ndomainMax properties.\n\nFor _[band](scale.html#band)_ scales, shortcut for setting `paddingInner` and\n`paddingOuter` to the same value.\n\nFor _[point](scale.html#point)_ scales, alias for `paddingOuter`.\n\n__Default value:__ For _continuous_ scales, derived from the [scale\nconfig](scale.html#config)'s `continuousPadding`.\nFor _band and point_ scales, see `paddingInner` and `paddingOuter`."
+                "extent": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "minItems": 2,
+                    "maxItems": 2,
+                    "description": "A two-element (`[min, max]`) array indicating the range of desired bin values."
                 },
-                "paddingInner": {
+                "maxbins": {
                     "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The inner padding (spacing) within each band step of band scales, as a fraction of the\nstep size. This value must lie in the range [0,1].\n\nFor point scale, this property is invalid as point scales do not have internal band\nwidths (only step sizes between bands).\n\n__Default value:__ derived from the [scale config](scale.html#config)'s\n`bandPaddingInner`."
+                    "minimum": 2,
+                    "description": "Maximum number of bins.\n\n__Default value:__ `6` for `row`, `column` and `shape` channels; `10` for other channels"
                 },
-                "paddingOuter": {
+                "minstep": {
                     "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The outer padding (spacing) at the ends of the range of band and point scales,\nas a fraction of the step size. This value must lie in the range [0,1].\n\n__Default value:__ derived from the [scale config](scale.html#config)'s\n`bandPaddingOuter` for band scales and `pointPadding` for point scales."
-                },
-                "range": {
-                    "$ref": "#/definitions/ScaleRange",
-                    "description": "The range of the scale. One of:\n\n- A string indicating a [pre-defined named scale range](scale.html#range-config) (e.g.,\nexample, `\"symbol\"`, or `\"diverging\"`).\n\n- For [continuous scales](scale.html#continuous), two-element array indicating  minimum\nand maximum values, or an array with more than two entries for specifying a [piecewise\nscale](scale.html#piecewise).\n\n- For [discrete](scale.html#discrete) and [discretizing](scale.html#discretizing) scales,\nan array of desired output values.\n\n__Notes:__\n\n1) For [sequential](scale.html#sequential), [ordinal](scale.html#ordinal), and\ndiscretizing color scales, you can also specify a color [`scheme`](scale.html#scheme)\ninstead of `range`.\n\n2) Any directly specified `range` for `x` and `y` channels will be ignored. Range can be\ncustomized via the view's corresponding [size](size.html) (`width` and `height`) or via\n[range steps and paddings properties](#range-step) for [band](#band) and [point](#point)\nscales."
-                },
-                "rangeStep": {
-                    "anyOf": [
-                        {
-                            "type": "number",
-                            "minimum": 0
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "The distance between the starts of adjacent bands or points in [band](scale.html#band)\nand [point](scale.html#point) scales.\n\nIf `rangeStep` is `null` or if the view contains the scale's corresponding\n[size](size.html) (`width` for `x` scales and `height` for `y` scales), `rangeStep` will\nbe automatically determined to fit the size of the view.\n\n__Default value:__  derived the [scale config](config.html#scale-config)'s\n`textXRangeStep` (`90` by default) for x-scales of `text` marks and `rangeStep` (`21` by\ndefault) for x-scales of other marks and y-scales.\n\n__Warning__: If `rangeStep` is `null` and the cardinality of the scale's domain is higher\nthan `width` or `height`, the rangeStep might become less than one pixel and the mark\nmight not appear correctly."
+                    "description": "A minimum allowable step size (particularly useful for integer values)."
                 },
-                "round": {
+                "nice": {
                     "type": "boolean",
-                    "description": "If `true`, rounds numeric output values to integers. This can be helpful for snapping to\nthe pixel grid.\n\n__Default value:__ `false`."
-                },
-                "scheme": {
-                    "$ref": "#/definitions/Scheme",
-                    "description": "A string indicating a color [scheme](scale.html#scheme) name (e.g., `\"category10\"` or\n`\"viridis\"`) or a [scheme parameter object](scale.html#scheme-params).\n\nDiscrete color schemes may be used with [discrete](scale.html#discrete) or\n[discretizing](scale.html#discretizing) scales. Continuous color schemes are intended for\nuse with [sequential](scales.html#sequential) scales.\n\nFor the full list of supported scheme, please refer to the [Vega\nScheme](https://vega.github.io/vega/docs/schemes/#reference) reference."
+                    "description": "If true (the default), attempts to make the bin boundaries use human-friendly boundaries,\nsuch as multiples of ten."
                 },
-                "type": {
-                    "$ref": "#/definitions/ScaleType",
-                    "description": "The type of scale.  Vega-Lite supports the following categories of scale types:\n\n1) [**Continuous Scales**](scale.html#continuous) -- mapping continuous domains to\ncontinuous output ranges ([`\"linear\"`](scale.html#linear), [`\"pow\"`](scale.html#pow),\n[`\"sqrt\"`](scale.html#sqrt), [`\"log\"`](scale.html#log), [`\"time\"`](scale.html#time),\n[`\"utc\"`](scale.html#utc), [`\"sequential\"`](scale.html#sequential)).\n\n2) [**Discrete Scales**](scale.html#discrete) -- mapping discrete domains to discrete\n([`\"ordinal\"`](scale.html#ordinal)) or continuous ([`\"band\"`](scale.html#band) and\n[`\"point\"`](scale.html#point)) output ranges.\n\n3) [**Discretizing Scales**](scale.html#discretizing) -- mapping continuous domains to\ndiscrete output ranges ([`\"bin-linear\"`](scale.html#bin-linear) and\n[`\"bin-ordinal\"`](scale.html#bin-ordinal)).\n\n__Default value:__ please see the [scale type table](scale.html#type)."
+                "step": {
+                    "type": "number",
+                    "description": "An exact step size to use between bins.\n\n__Note:__ If provided, options such as maxbins will be ignored."
                 },
-                "zero": {
-                    "type": "boolean",
-                    "description": "If `true`, ensures that a zero baseline value is included in the scale domain.\n\n__Default value:__ `true` for x and y channels if the quantitative field is not binned\nand no custom `domain` is provided; `false` otherwise.\n\n__Note:__ Log, time, and utc scales do not support `zero`."
+                "steps": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "minItems": 1,
+                    "description": "An array of allowable step sizes to choose from."
                 }
             },
             "required": [],
-            "title": "Scale",
-            "description": "An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+            "title": "BinParams",
+            "description": "Binning properties or boolean flag for determining whether to bin data or not."
         },
-        "DomainClass": {
+        "ConditionalPredicateValueDef": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "field": {
-                    "type": "string",
-                    "description": "The field name to extract selected values for, when a selection is\n[projected](project.html)\nover multiple fields or encodings."
-                },
-                "selection": {
-                    "type": "string",
-                    "description": "The name of a selection."
+                "test": {
+                    "$ref": "#/definitions/LogicalOperandPredicate"
                 },
-                "encoding": {
-                    "type": "string",
-                    "description": "The encoding channel to extract selected values for, when a selection is\n[projected](project.html)\nover multiple fields or encodings."
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
                 }
             },
             "required": [
-                "selection"
+                "test",
+                "value"
             ],
-            "title": "DomainClass"
+            "title": "ConditionalPredicateValueDef"
         },
-        "InterpolateParams": {
+        "ConditionalSelectionValueDef": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "gamma": {
-                    "type": "number"
+                "selection": {
+                    "$ref": "#/definitions/SelectionOperand",
+                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
                 },
-                "type": {
-                    "$ref": "#/definitions/InterpolateParamsType"
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
                 }
             },
             "required": [
-                "type"
+                "selection",
+                "value"
             ],
-            "title": "InterpolateParams"
+            "title": "ConditionalSelectionValueDef"
         },
-        "NiceClass": {
+        "LogicalNotPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "interval": {
-                    "type": "string"
-                },
-                "step": {
-                    "type": "number"
+                "not": {
+                    "$ref": "#/definitions/LogicalOperandPredicate"
                 }
             },
             "required": [
-                "interval",
-                "step"
+                "not"
             ],
-            "title": "NiceClass"
+            "title": "LogicalNotPredicate"
         },
-        "SchemeParams": {
+        "LogicalAndPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "extent": {
+                "and": {
                     "type": "array",
                     "items": {
-                        "type": "number"
-                    },
-                    "description": "For sequential and diverging schemes only, determines the extent of the color range to\nuse. For example `[0.2, 1]` will rescale the color scheme such that color values in the\nrange _[0, 0.2)_ are excluded from the scheme."
-                },
-                "name": {
-                    "type": "string",
-                    "description": "A color scheme name for sequential/ordinal scales (e.g., `\"category10\"` or `\"viridis\"`).\n\nFor the full list of supported scheme, please refer to the [Vega\nScheme](https://vega.github.io/vega/docs/schemes/#reference) reference."
+                        "$ref": "#/definitions/LogicalOperandPredicate"
+                    }
                 }
             },
             "required": [
-                "name"
+                "and"
             ],
-            "title": "SchemeParams"
+            "title": "LogicalAndPredicate"
         },
-        "SortField": {
+        "LogicalOrPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "The data [field](field.html) to sort by.\n\n__Default value:__ If unspecified, defaults to the field specified in the outer data\nreference."
-                },
-                "op": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "An [aggregate operation](aggregate.html#ops) to perform on the field prior to sorting\n(e.g., `\"count\"`, `\"mean\"` and `\"median\"`).\nThis property is required in cases where the sort field and the data reference field do\nnot match.\nThe input data objects will be aggregated, grouped by the encoded data field.\n\nFor a full list of operations, please see the documentation for\n[aggregate](aggregate.html#ops)."
-                },
-                "order": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/SortEnum"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
+                "or": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/LogicalOperandPredicate"
+                    }
                 }
             },
             "required": [
-                "op"
+                "or"
             ],
-            "title": "SortField"
+            "title": "LogicalOrPredicate"
         },
-        "FacetFieldDef": {
+        "FieldEqualPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                "equal": {
+                    "$ref": "#/definitions/Equal",
+                    "description": "The value that the field should be equal to."
                 },
                 "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "header": {
-                    "$ref": "#/definitions/Header",
-                    "description": "An object defining properties of a facet's header."
-                },
-                "sort": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/SortEnum"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
+                    "type": "string",
+                    "description": "Field to be filtered."
                 },
                 "timeUnit": {
                     "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                    "description": "Time unit for the field to be filtered."
                 }
             },
             "required": [
-                "type"
+                "equal",
+                "field"
             ],
-            "title": "FacetFieldDef",
-            "description": "Horizontal facets for trellis plots.\nVertical facets for trellis plots."
+            "title": "FieldEqualPredicate"
         },
-        "Header": {
+        "FieldRangePredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "format": {
+                "field": {
                     "type": "string",
-                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
+                    "description": "Field to be filtered"
                 },
-                "labelAngle": {
-                    "type": "number",
-                    "minimum": -360,
-                    "maximum": 360,
-                    "description": "The rotation angle of the header labels.\n\n__Default value:__ `0`."
+                "range": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/RangeElement"
+                    },
+                    "minItems": 2,
+                    "maxItems": 2,
+                    "description": "An array of inclusive minimum and maximum values\nfor a field value of a data item to be included in the filtered data."
                 },
-                "title": {
-                    "anyOf": [
-                        {
-                            "type": "null"
-                        },
-                        {
-                            "type": "string"
-                        }
-                    ],
-                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "time unit for the field to be filtered."
                 }
             },
-            "required": [],
-            "title": "Header",
-            "description": "An object defining properties of a facet's header.\nHeaders of row / column channels for faceted plots."
+            "required": [
+                "field",
+                "range"
+            ],
+            "title": "FieldRangePredicate"
         },
-        "FieldDef": {
+        "FieldOneOfPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
                 "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                    "type": "string",
+                    "description": "Field to be filtered"
+                },
+                "oneOf": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Equal"
+                    },
+                    "description": "A set of values that the `field`'s value should be a member of,\nfor a data item included in the filtered data."
                 },
                 "timeUnit": {
                     "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                    "description": "time unit for the field to be filtered."
                 }
             },
             "required": [
-                "type"
+                "field",
+                "oneOf"
             ],
-            "title": "FieldDef",
-            "description": "Definition object for a data field, its type and transformation of an encoding channel."
+            "title": "FieldOneOfPredicate"
         },
-        "DefWithCondition": {
+        "SelectionPredicate": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "condition": {
-                    "$ref": "#/definitions/HrefCondition",
-                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel.\n\nA field definition or one or more value definition(s) with a selection predicate."
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
-                },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain."
+                "selection": {
+                    "$ref": "#/definitions/SelectionOperand",
+                    "description": "Filter using a selection name."
                 }
             },
-            "required": [],
-            "title": "DefWithCondition",
-            "description": "A URL to load upon mouse click.\nA FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}\nA ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+            "required": [
+                "selection"
+            ],
+            "title": "SelectionPredicate"
         },
-        "ConditionalPredicateFieldDefClass": {
+        "DateTime": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "test": {
-                    "$ref": "#/definitions/LogicalOperandPredicate"
+                "date": {
+                    "type": "number",
+                    "minimum": 1,
+                    "maximum": 31,
+                    "description": "Integer value representing the date from 1-31."
                 },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
+                "day": {
+                    "$ref": "#/definitions/Day",
+                    "description": "Value representing the day of a week.  This can be one of: (1) integer value -- `1`\nrepresents Monday; (2) case-insensitive day name (e.g., `\"Monday\"`);  (3)\ncase-insensitive, 3-character short day name (e.g., `\"Mon\"`).   <br/> **Warning:** A\nDateTime definition object with `day`** should not be combined with `year`, `quarter`,\n`month`, or `date`."
                 },
-                "selection": {
-                    "$ref": "#/definitions/SelectionOperand",
-                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
+                "hours": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 23,
+                    "description": "Integer value representing the hour of a day from 0-23."
                 },
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                "milliseconds": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 999,
+                    "description": "Integer value representing the millisecond segment of time."
                 },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                "minutes": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 59,
+                    "description": "Integer value representing the minute segment of time from 0-59."
                 },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                "month": {
+                    "$ref": "#/definitions/Month",
+                    "description": "One of: (1) integer value representing the month from `1`-`12`. `1` represents January;\n(2) case-insensitive month name (e.g., `\"January\"`);  (3) case-insensitive, 3-character\nshort month name (e.g., `\"Jan\"`)."
                 },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                "quarter": {
+                    "type": "number",
+                    "minimum": 1,
+                    "maximum": 4,
+                    "description": "Integer value representing the quarter of the year (from 1-4)."
                 },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "seconds": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 59,
+                    "description": "Integer value representing the second segment (0-59) of a time value"
+                },
+                "utc": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if date time is in utc time. If false, the date time is in\nlocal time"
+                },
+                "year": {
+                    "type": "number",
+                    "description": "Integer value representing the year."
                 }
             },
             "required": [],
-            "title": "ConditionalPredicateFieldDefClass"
+            "title": "DateTime",
+            "description": "Object for defining datetime in Vega-Lite Filter.\nIf both month and quarter are provided, month has higher precedence.\n`day` cannot be combined with other date.\nWe accept string for month and day names."
         },
-        "OrderFieldDef": {
+        "SelectionNot": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "sort": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/SortEnum"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "not": {
+                    "$ref": "#/definitions/SelectionOperand"
                 }
             },
             "required": [
-                "type"
+                "not"
             ],
-            "title": "OrderFieldDef"
+            "title": "SelectionNot"
         },
-        "TextDefWithCondition": {
+        "SelectionAnd": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "condition": {
-                    "$ref": "#/definitions/TextCondition",
-                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel.\n\nA field definition or one or more value definition(s) with a selection predicate."
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "format": {
-                    "type": "string",
-                    "description": "The [formatting pattern](format.html) for a text field. If not defined, this will be\ndetermined automatically."
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
-                },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain."
+                "and": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SelectionOperand"
+                    }
                 }
             },
-            "required": [],
-            "title": "TextDefWithCondition",
-            "description": "Text of the `text` mark.\nThe tooltip text to show upon mouse hover.\nA FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}\nA ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+            "required": [
+                "and"
+            ],
+            "title": "SelectionAnd"
         },
-        "ConditionalPredicateTextFieldDefClass": {
+        "SelectionOr": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "test": {
-                    "$ref": "#/definitions/LogicalOperandPredicate"
-                },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
-                },
-                "selection": {
-                    "$ref": "#/definitions/SelectionOperand",
-                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
-                },
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
-                },
-                "format": {
-                    "type": "string",
-                    "description": "The [formatting pattern](format.html) for a text field. If not defined, this will be\ndetermined automatically."
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
-                },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "or": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SelectionOperand"
+                    }
                 }
             },
-            "required": [],
-            "title": "ConditionalPredicateTextFieldDefClass"
+            "required": [
+                "or"
+            ],
+            "title": "SelectionOr"
         },
-        "XClass": {
+        "RepeatRef": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
-                },
-                "axis": {
-                    "anyOf": [
-                        {
-                            "$ref": "#/definitions/Axis"
-                        },
-                        {
-                            "type": "null"
-                        }
-                    ],
-                    "description": "An object defining properties of axis's gridlines, ticks and labels.\nIf `null`, the axis for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [axis properties](axis.html) are applied."
-                },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
-                },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                "repeat": {
+                    "$ref": "#/definitions/RepeatEnum"
+                }
+            },
+            "required": [
+                "repeat"
+            ],
+            "title": "RepeatRef",
+            "description": "Reference to a repeated value."
+        },
+        "Legend": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "entryPadding": {
+                    "type": "number",
+                    "description": "Padding (in pixels) between legend entries in a symbol legend."
                 },
-                "scale": {
-                    "$ref": "#/definitions/Scale",
-                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+                "format": {
+                    "type": "string",
+                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
                 },
-                "sort": {
-                    "$ref": "#/definitions/SortUnion",
-                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
+                "offset": {
+                    "type": "number",
+                    "description": "The offset, in pixels, by which to displace the legend from the edge of the enclosing\ngroup or data rectangle.\n\n__Default value:__  `0`"
                 },
-                "stack": {
+                "orient": {
+                    "$ref": "#/definitions/LegendOrient",
+                    "description": "The orientation of the legend, which determines how the legend is positioned within the\nscene. One of \"left\", \"right\", \"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\",\n\"none\".\n\n__Default value:__ `\"right\"`"
+                },
+                "padding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between the legend and axis."
+                },
+                "tickCount": {
+                    "type": "number",
+                    "description": "The desired number of tick values for quantitative legends."
+                },
+                "title": {
                     "anyOf": [
                         {
-                            "$ref": "#/definitions/StackOffset"
+                            "type": "null"
                         },
                         {
-                            "type": "null"
+                            "type": "string"
                         }
                     ],
-                    "description": "Type of stacking offset if the field should be stacked.\n`stack` is only applicable for `x` and `y` channels with continuous domains.\nFor example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\n\n`stack` can be one of the following values:\n\n- `\"zero\"`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](stack.html#bar) and [area](stack.html#area) chart).\n- `\"normalize\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](stack.html#normalized). <br/>\n- `\"center\"` - stacking with center baseline (for [streamgraph](stack.html#streamgraph)).\n- `null` - No-stacking. This will produce layered [bar](stack.html#layered-bar-chart) and area chart.\n\n__Default value:__ `zero` for plots with all of the following conditions are true:\n\n1. The mark is `bar` or `area`;\n2. The stacked measure channel (x or y) has a linear scale;\n3. At least one of non-position channels mapped to an unaggregated field that is different from x and y.  Otherwise, `null` by default."
-                },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
                 },
                 "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                    "$ref": "#/definitions/LegendType",
+                    "description": "The type of the legend. Use `\"symbol\"` to create a discrete legend and `\"gradient\"` for a\ncontinuous color gradient.\n\n__Default value:__ `\"gradient\"` for non-binned quantitative fields and temporal fields;\n`\"symbol\"` otherwise."
                 },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
+                "values": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/LegendValue"
+                    },
+                    "description": "Explicitly set the visible legend values."
+                },
+                "zindex": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "A non-positive integer indicating z-index of the legend.\nIf zindex is 0, legend should be drawn behind all chart elements.\nTo put them in front, use zindex = 1."
                 }
             },
             "required": [],
-            "title": "XClass",
-            "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`.\nY coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`.\nDefinition object for a constant value of an encoding channel."
+            "title": "Legend",
+            "description": "Properties of a legend or boolean flag for determining whether to show it."
         },
-        "Axis": {
+        "Scale": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "domain": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
-                },
-                "format": {
-                    "type": "string",
-                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
-                },
-                "grid": {
-                    "type": "boolean",
-                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
-                },
-                "labelAngle": {
-                    "type": "number",
-                    "minimum": -360,
-                    "maximum": 360,
-                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
-                },
-                "labelBound": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
-                },
-                "labelFlush": {
-                    "$ref": "#/definitions/Label",
-                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
-                },
-                "labelOverlap": {
-                    "$ref": "#/definitions/LabelOverlapUnion",
-                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
-                },
-                "labelPadding": {
+                "base": {
                     "type": "number",
-                    "description": "The padding, in pixels, between axis and text labels."
+                    "description": "The logarithm base of the `log` scale (default `10`)."
                 },
-                "labels": {
+                "clamp": {
                     "type": "boolean",
-                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
+                    "description": "If `true`, values that exceed the data domain are clamped to either the minimum or\nmaximum range value\n\n__Default value:__ derived from the [scale config](config.html#scale-config)'s `clamp`\n(`true` by default)."
                 },
-                "maxExtent": {
-                    "type": "number",
-                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
+                "domain": {
+                    "$ref": "#/definitions/DomainUnion",
+                    "description": "Customized domain values.\n\nFor _quantitative_ fields, `domain` can take the form of a two-element array with minimum\nand maximum values.  [Piecewise scales](scale.html#piecewise) can be created by providing\na `domain` with more than two entries.\nIf the input field is aggregated, `domain` can also be a string value `\"unaggregated\"`,\nindicating that the domain should include the raw data values prior to the aggregation.\n\nFor _temporal_ fields, `domain` can be a two-element array minimum and maximum values, in\nthe form of either timestamps or the [DateTime definition objects](types.html#datetime).\n\nFor _ordinal_ and _nominal_ fields, `domain` can be an array that lists valid input\nvalues.\n\nThe `selection` property can be used to [interactively\ndetermine](selection.html#scale-domains) the scale domain."
                 },
-                "minExtent": {
+                "exponent": {
                     "type": "number",
-                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
+                    "description": "The exponent of the `pow` scale."
                 },
-                "offset": {
-                    "type": "number",
-                    "description": "The offset, in pixels, by which to displace the axis from the edge of the enclosing group\nor data rectangle.\n\n__Default value:__ derived from the [axis config](config.html#facet-scale-config)'s\n`offset` (`0` by default)"
+                "interpolate": {
+                    "$ref": "#/definitions/InterpolateUnion",
+                    "description": "The interpolation method for range values. By default, a general interpolator for\nnumbers, dates, strings and colors (in RGB space) is used. For color ranges, this\nproperty allows interpolation in alternative color spaces. Legal values include `rgb`,\n`hsl`, `hsl-long`, `lab`, `hcl`, `hcl-long`, `cubehelix` and `cubehelix-long` ('-long'\nvariants use longer paths in polar coordinate spaces). If object-valued, this property\naccepts an object with a string-valued _type_ property and an optional numeric _gamma_\nproperty applicable to rgb and cubehelix interpolators. For more, see the [d3-interpolate\ndocumentation](https://github.com/d3/d3-interpolate).\n\n__Note:__ Sequential scales do not support `interpolate` as they have a fixed\ninterpolator.  Since Vega-Lite uses sequential scales for quantitative fields by default,\nyou have to set the scale `type` to other quantitative scale type such as `\"linear\"` to\ncustomize `interpolate`."
                 },
-                "orient": {
-                    "$ref": "#/definitions/TitleOrient",
-                    "description": "The orientation of the axis. One of `\"top\"`, `\"bottom\"`, `\"left\"` or `\"right\"`. The\norientation can be used to further specialize the axis type (e.g., a y axis oriented for\nthe right edge of the chart).\n\n__Default value:__ `\"bottom\"` for x-axes and `\"left\"` for y-axes."
+                "nice": {
+                    "$ref": "#/definitions/NiceUnion",
+                    "description": "Extending the domain so that it starts and ends on nice round values. This method\ntypically modifies the scale’s domain, and may only extend the bounds to the nearest\nround value. Nicing is useful if the domain is computed from data and may be irregular.\nFor example, for a domain of _[0.201479…, 0.996679…]_, a nice domain might be _[0.2,\n1.0]_.\n\nFor quantitative scales such as linear, `nice` can be either a boolean flag or a number.\nIf `nice` is a number, it will represent a desired tick count. This allows greater\ncontrol over the step size used to extend the bounds, guaranteeing that the returned\nticks will exactly cover the domain.\n\nFor temporal fields with time and utc scales, the `nice` value can be a string indicating\nthe desired time interval. Legal values are `\"millisecond\"`, `\"second\"`, `\"minute\"`,\n`\"hour\"`, `\"day\"`, `\"week\"`, `\"month\"`, and `\"year\"`. Alternatively, `time` and `utc`\nscales can accept an object-valued interval specifier of the form `{\"interval\": \"month\",\n\"step\": 3}`, which includes a desired number of interval steps. Here, the domain would\nsnap to quarter (Jan, Apr, Jul, Oct) boundaries.\n\n__Default value:__ `true` for unbinned _quantitative_ fields; `false` otherwise."
                 },
-                "position": {
+                "padding": {
                     "type": "number",
-                    "description": "The anchor position of the axis in pixels. For x-axis with top or bottom orientation,\nthis sets the axis group x coordinate. For y-axis with left or right orientation, this\nsets the axis group y coordinate.\n\n__Default value__: `0`"
+                    "minimum": 0,
+                    "description": "For _[continuous](scale.html#continuous)_ scales, expands the scale domain to accommodate\nthe specified number of pixels on each of the scale range. The scale range must represent\npixels for this parameter to function as intended. Padding adjustment is performed prior\nto all other adjustments, including the effects of the zero, nice, domainMin, and\ndomainMax properties.\n\nFor _[band](scale.html#band)_ scales, shortcut for setting `paddingInner` and\n`paddingOuter` to the same value.\n\nFor _[point](scale.html#point)_ scales, alias for `paddingOuter`.\n\n__Default value:__ For _continuous_ scales, derived from the [scale\nconfig](scale.html#config)'s `continuousPadding`.\nFor _band and point_ scales, see `paddingInner` and `paddingOuter`."
                 },
-                "tickCount": {
+                "paddingInner": {
                     "type": "number",
-                    "description": "A desired number of ticks, for axes visualizing quantitative scales. The resulting number\nmay be different so that values are \"nice\" (multiples of 2, 5, 10) and lie within the\nunderlying scale's range."
-                },
-                "ticks": {
-                    "type": "boolean",
-                    "description": "Boolean value that determines whether the axis should include ticks."
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The inner padding (spacing) within each band step of band scales, as a fraction of the\nstep size. This value must lie in the range [0,1].\n\nFor point scale, this property is invalid as point scales do not have internal band\nwidths (only step sizes between bands).\n\n__Default value:__ derived from the [scale config](scale.html#config)'s\n`bandPaddingInner`."
                 },
-                "tickSize": {
+                "paddingOuter": {
                     "type": "number",
                     "minimum": 0,
-                    "description": "The size in pixels of axis ticks."
+                    "maximum": 1,
+                    "description": "The outer padding (spacing) at the ends of the range of band and point scales,\nas a fraction of the step size. This value must lie in the range [0,1].\n\n__Default value:__ derived from the [scale config](scale.html#config)'s\n`bandPaddingOuter` for band scales and `pointPadding` for point scales."
                 },
-                "title": {
+                "range": {
+                    "$ref": "#/definitions/ScaleRange",
+                    "description": "The range of the scale. One of:\n\n- A string indicating a [pre-defined named scale range](scale.html#range-config) (e.g.,\nexample, `\"symbol\"`, or `\"diverging\"`).\n\n- For [continuous scales](scale.html#continuous), two-element array indicating  minimum\nand maximum values, or an array with more than two entries for specifying a [piecewise\nscale](scale.html#piecewise).\n\n- For [discrete](scale.html#discrete) and [discretizing](scale.html#discretizing) scales,\nan array of desired output values.\n\n__Notes:__\n\n1) For [sequential](scale.html#sequential), [ordinal](scale.html#ordinal), and\ndiscretizing color scales, you can also specify a color [`scheme`](scale.html#scheme)\ninstead of `range`.\n\n2) Any directly specified `range` for `x` and `y` channels will be ignored. Range can be\ncustomized via the view's corresponding [size](size.html) (`width` and `height`) or via\n[range steps and paddings properties](#range-step) for [band](#band) and [point](#point)\nscales."
+                },
+                "rangeStep": {
                     "anyOf": [
                         {
-                            "type": "null"
+                            "type": "number",
+                            "minimum": 0
                         },
                         {
-                            "type": "string"
+                            "type": "null"
                         }
                     ],
-                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
+                    "description": "The distance between the starts of adjacent bands or points in [band](scale.html#band)\nand [point](scale.html#point) scales.\n\nIf `rangeStep` is `null` or if the view contains the scale's corresponding\n[size](size.html) (`width` for `x` scales and `height` for `y` scales), `rangeStep` will\nbe automatically determined to fit the size of the view.\n\n__Default value:__  derived the [scale config](config.html#scale-config)'s\n`textXRangeStep` (`90` by default) for x-scales of `text` marks and `rangeStep` (`21` by\ndefault) for x-scales of other marks and y-scales.\n\n__Warning__: If `rangeStep` is `null` and the cardinality of the scale's domain is higher\nthan `width` or `height`, the rangeStep might become less than one pixel and the mark\nmight not appear correctly."
                 },
-                "titleMaxLength": {
-                    "type": "number",
-                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
+                "round": {
+                    "type": "boolean",
+                    "description": "If `true`, rounds numeric output values to integers. This can be helpful for snapping to\nthe pixel grid.\n\n__Default value:__ `false`."
+                },
+                "scheme": {
+                    "$ref": "#/definitions/Scheme",
+                    "description": "A string indicating a color [scheme](scale.html#scheme) name (e.g., `\"category10\"` or\n`\"viridis\"`) or a [scheme parameter object](scale.html#scheme-params).\n\nDiscrete color schemes may be used with [discrete](scale.html#discrete) or\n[discretizing](scale.html#discretizing) scales. Continuous color schemes are intended for\nuse with [sequential](scales.html#sequential) scales.\n\nFor the full list of supported scheme, please refer to the [Vega\nScheme](https://vega.github.io/vega/docs/schemes/#reference) reference."
+                },
+                "type": {
+                    "$ref": "#/definitions/ScaleType",
+                    "description": "The type of scale.  Vega-Lite supports the following categories of scale types:\n\n1) [**Continuous Scales**](scale.html#continuous) -- mapping continuous domains to\ncontinuous output ranges ([`\"linear\"`](scale.html#linear), [`\"pow\"`](scale.html#pow),\n[`\"sqrt\"`](scale.html#sqrt), [`\"log\"`](scale.html#log), [`\"time\"`](scale.html#time),\n[`\"utc\"`](scale.html#utc), [`\"sequential\"`](scale.html#sequential)).\n\n2) [**Discrete Scales**](scale.html#discrete) -- mapping discrete domains to discrete\n([`\"ordinal\"`](scale.html#ordinal)) or continuous ([`\"band\"`](scale.html#band) and\n[`\"point\"`](scale.html#point)) output ranges.\n\n3) [**Discretizing Scales**](scale.html#discretizing) -- mapping continuous domains to\ndiscrete output ranges ([`\"bin-linear\"`](scale.html#bin-linear) and\n[`\"bin-ordinal\"`](scale.html#bin-ordinal)).\n\n__Default value:__ please see the [scale type table](scale.html#type)."
+                },
+                "zero": {
+                    "type": "boolean",
+                    "description": "If `true`, ensures that a zero baseline value is included in the scale domain.\n\n__Default value:__ `true` for x and y channels if the quantitative field is not binned\nand no custom `domain` is provided; `false` otherwise.\n\n__Note:__ Log, time, and utc scales do not support `zero`."
+                }
+            },
+            "required": [],
+            "title": "Scale",
+            "description": "An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+        },
+        "PurpleSelectionDomain": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "field": {
+                    "type": "string",
+                    "description": "The field name to extract selected values for, when a selection is\n[projected](project.html)\nover multiple fields or encodings."
+                },
+                "selection": {
+                    "type": "string",
+                    "description": "The name of a selection."
+                }
+            },
+            "required": [
+                "selection"
+            ],
+            "title": "PurpleSelectionDomain"
+        },
+        "FluffySelectionDomain": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "encoding": {
+                    "type": "string",
+                    "description": "The encoding channel to extract selected values for, when a selection is\n[projected](project.html)\nover multiple fields or encodings."
+                },
+                "selection": {
+                    "type": "string",
+                    "description": "The name of a selection."
+                }
+            },
+            "required": [
+                "selection"
+            ],
+            "title": "FluffySelectionDomain"
+        },
+        "InterpolateParams": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "gamma": {
+                    "type": "number"
+                },
+                "type": {
+                    "$ref": "#/definitions/InterpolateParamsType"
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "InterpolateParams"
+        },
+        "NiceClass": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "interval": {
+                    "type": "string"
+                },
+                "step": {
+                    "type": "number"
+                }
+            },
+            "required": [
+                "interval",
+                "step"
+            ],
+            "title": "NiceClass"
+        },
+        "SchemeParams": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "extent": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "For sequential and diverging schemes only, determines the extent of the color range to\nuse. For example `[0.2, 1]` will rescale the color scheme such that color values in the\nrange _[0, 0.2)_ are excluded from the scheme."
+                },
+                "name": {
+                    "type": "string",
+                    "description": "A color scheme name for sequential/ordinal scales (e.g., `\"category10\"` or `\"viridis\"`).\n\nFor the full list of supported scheme, please refer to the [Vega\nScheme](https://vega.github.io/vega/docs/schemes/#reference) reference."
+                }
+            },
+            "required": [
+                "name"
+            ],
+            "title": "SchemeParams"
+        },
+        "SortField": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "The data [field](field.html) to sort by.\n\n__Default value:__ If unspecified, defaults to the field specified in the outer data\nreference."
+                },
+                "op": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "An [aggregate operation](aggregate.html#ops) to perform on the field prior to sorting\n(e.g., `\"count\"`, `\"mean\"` and `\"median\"`).\nThis property is required in cases where the sort field and the data reference field do\nnot match.\nThe input data objects will be aggregated, grouped by the encoded data field.\n\nFor a full list of operations, please see the documentation for\n[aggregate](aggregate.html#ops)."
+                },
+                "order": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/SortOrderEnum"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
+                }
+            },
+            "required": [
+                "op"
+            ],
+            "title": "SortField"
+        },
+        "ConditionalPredicateMarkPropFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "legend": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/Legend"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
+                },
+                "scale": {
+                    "$ref": "#/definitions/Scale",
+                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+                },
+                "sort": {
+                    "$ref": "#/definitions/SortUnion",
+                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
+                },
+                "test": {
+                    "$ref": "#/definitions/LogicalOperandPredicate"
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "test",
+                "type"
+            ],
+            "title": "ConditionalPredicateMarkPropFieldDef"
+        },
+        "ConditionalSelectionMarkPropFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "legend": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/Legend"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
+                },
+                "scale": {
+                    "$ref": "#/definitions/Scale",
+                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+                },
+                "selection": {
+                    "$ref": "#/definitions/SelectionOperand",
+                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
+                },
+                "sort": {
+                    "$ref": "#/definitions/SortUnion",
+                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "selection",
+                "type"
+            ],
+            "title": "ConditionalSelectionMarkPropFieldDef"
+        },
+        "FacetFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "header": {
+                    "$ref": "#/definitions/Header",
+                    "description": "An object defining properties of a facet's header."
+                },
+                "sort": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/SortOrderEnum"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "FacetFieldDef",
+            "description": "Horizontal facets for trellis plots.\nVertical facets for trellis plots."
+        },
+        "Header": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "format": {
+                    "type": "string",
+                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
+                },
+                "labelAngle": {
+                    "type": "number",
+                    "minimum": -360,
+                    "maximum": 360,
+                    "description": "The rotation angle of the header labels.\n\n__Default value:__ `0`."
+                },
+                "title": {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        },
+                        {
+                            "type": "string"
+                        }
+                    ],
+                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
+                }
+            },
+            "required": [],
+            "title": "Header",
+            "description": "An object defining properties of a facet's header.\nHeaders of row / column channels for faceted plots."
+        },
+        "FieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "FieldDef",
+            "description": "Definition object for a data field, its type and transformation of an encoding channel."
+        },
+        "FieldDefWithCondition": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "condition": {
+                    "$ref": "#/definitions/ConditionUnion",
+                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel."
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "FieldDefWithCondition",
+            "description": "A FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}"
+        },
+        "ValueDefWithCondition": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "condition": {
+                    "$ref": "#/definitions/HrefCondition",
+                    "description": "A field definition or one or more value definition(s) with a selection predicate."
+                },
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain."
+                }
+            },
+            "required": [],
+            "title": "ValueDefWithCondition",
+            "description": "A ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+        },
+        "ConditionalPredicateFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "test": {
+                    "$ref": "#/definitions/LogicalOperandPredicate"
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "test",
+                "type"
+            ],
+            "title": "ConditionalPredicateFieldDef"
+        },
+        "ConditionalSelectionFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "selection": {
+                    "$ref": "#/definitions/SelectionOperand",
+                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "selection",
+                "type"
+            ],
+            "title": "ConditionalSelectionFieldDef"
+        },
+        "OrderFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "sort": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/SortOrderEnum"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "The sort order. One of `\"ascending\"` (default) or `\"descending\"`.\nSort order for a facet field.\nThis can be `\"ascending\"`, `\"descending\"`."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "OrderFieldDef"
+        },
+        "TextFieldDefWithCondition": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "condition": {
+                    "$ref": "#/definitions/ConditionUnion",
+                    "description": "One or more value definition(s) with a selection predicate.\n\n__Note:__ A field definition's `condition` property can only contain [value\ndefinitions](encoding.html#value-def)\nsince Vega-Lite only allows at most one encoded field per encoding channel."
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "format": {
+                    "type": "string",
+                    "description": "The [formatting pattern](format.html) for a text field. If not defined, this will be\ndetermined automatically."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "TextFieldDefWithCondition",
+            "description": "A FieldDef with Condition<ValueDef>\n{\n   condition: {value: ...},\n   field: ...,\n   ...\n}"
+        },
+        "TextValueDefWithCondition": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "condition": {
+                    "$ref": "#/definitions/TextCondition",
+                    "description": "A field definition or one or more value definition(s) with a selection predicate."
+                },
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain."
+                }
+            },
+            "required": [],
+            "title": "TextValueDefWithCondition",
+            "description": "A ValueDef with Condition<ValueDef | FieldDef>\n{\n   condition: {field: ...} | {value: ...},\n   value: ...,\n}"
+        },
+        "ConditionalPredicateTextFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "format": {
+                    "type": "string",
+                    "description": "The [formatting pattern](format.html) for a text field. If not defined, this will be\ndetermined automatically."
+                },
+                "test": {
+                    "$ref": "#/definitions/LogicalOperandPredicate"
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "test",
+                "type"
+            ],
+            "title": "ConditionalPredicateTextFieldDef"
+        },
+        "ConditionalSelectionTextFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "format": {
+                    "type": "string",
+                    "description": "The [formatting pattern](format.html) for a text field. If not defined, this will be\ndetermined automatically."
+                },
+                "selection": {
+                    "$ref": "#/definitions/SelectionOperand",
+                    "description": "A [selection name](selection.html), or a series of [composed\nselections](selection.html#compose)."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "selection",
+                "type"
+            ],
+            "title": "ConditionalSelectionTextFieldDef"
+        },
+        "PositionFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                },
+                "axis": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/Axis"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "An object defining properties of axis's gridlines, ticks and labels.\nIf `null`, the axis for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [axis properties](axis.html) are applied."
+                },
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                },
+                "field": {
+                    "$ref": "#/definitions/Field",
+                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                },
+                "scale": {
+                    "$ref": "#/definitions/Scale",
+                    "description": "An object defining properties of the channel's scale, which is the function that\ntransforms values in the data domain (numbers, dates, strings, etc) to visual values\n(pixels, colors, sizes) of the encoding channels.\n\n__Default value:__ If undefined, default [scale properties](scale.html) are applied."
+                },
+                "sort": {
+                    "$ref": "#/definitions/SortUnion",
+                    "description": "Sort order for the encoded field.\nSupported `sort` values include `\"ascending\"`, `\"descending\"` and `null` (no sorting).\nFor fields with discrete domains, `sort` can also be a [sort field definition\nobject](sort.html#sort-field).\n\n__Default value:__ `\"ascending\"`"
+                },
+                "stack": {
+                    "anyOf": [
+                        {
+                            "$ref": "#/definitions/StackOffset"
+                        },
+                        {
+                            "type": "null"
+                        }
+                    ],
+                    "description": "Type of stacking offset if the field should be stacked.\n`stack` is only applicable for `x` and `y` channels with continuous domains.\nFor example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\n\n`stack` can be one of the following values:\n\n- `\"zero\"`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](stack.html#bar) and [area](stack.html#area) chart).\n- `\"normalize\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](stack.html#normalized). <br/>\n- `\"center\"` - stacking with center baseline (for [streamgraph](stack.html#streamgraph)).\n- `null` - No-stacking. This will produce layered [bar](stack.html#layered-bar-chart) and area chart.\n\n__Default value:__ `zero` for plots with all of the following conditions are true:\n\n1. The mark is `bar` or `area`;\n2. The stacked measure channel (x or y) has a linear scale;\n3. At least one of non-position channels mapped to an unaggregated field that is different from x and y.  Otherwise, `null` by default."
+                },
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                },
+                "type": {
+                    "$ref": "#/definitions/Type",
+                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "PositionFieldDef"
+        },
+        "ValueDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "value": {
+                    "$ref": "#/definitions/ConditionValue",
+                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
+                }
+            },
+            "required": [
+                "value"
+            ],
+            "title": "ValueDef",
+            "description": "Definition object for a constant value of an encoding channel."
+        },
+        "Axis": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "domain": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if the domain (the axis baseline) should be included as part of\nthe axis.\n\n__Default value:__ `true`"
+                },
+                "format": {
+                    "type": "string",
+                    "description": "The formatting pattern for labels. This is D3's [number format\npattern](https://github.com/d3/d3-format#locale_format) for quantitative fields and D3's\n[time format pattern](https://github.com/d3/d3-time-format#locale_format) for time\nfield.\n\nSee the [format documentation](format.html) for more information.\n\n__Default value:__  derived from [numberFormat](config.html#format) config for\nquantitative fields and from [timeFormat](config.html#format) config for temporal fields."
+                },
+                "grid": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if grid lines should be included as part of the axis\n\n__Default value:__ `true` for [continuous scales](scale.html#continuous) that are not\nbinned; otherwise, `false`."
+                },
+                "labelAngle": {
+                    "type": "number",
+                    "minimum": -360,
+                    "maximum": 360,
+                    "description": "The rotation angle of the axis labels.\n\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise."
+                },
+                "labelBound": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if labels should be hidden if they exceed the axis range. If `false `(the\ndefault) no bounds overlap analysis is performed. If `true`, labels will be hidden if\nthey exceed the axis range by more than 1 pixel. If this property is a number, it\nspecifies the pixel tolerance: the maximum amount by which a label bounding box may\nexceed the axis range.\n\n__Default value:__ `false`."
+                },
+                "labelFlush": {
+                    "$ref": "#/definitions/Label",
+                    "description": "Indicates if the first and last axis labels should be aligned flush with the scale range.\nFlush alignment for a horizontal axis will left-align the first label and right-align the\nlast label. For vertical axes, bottom and top text baselines are applied instead. If this\nproperty is a number, it also indicates the number of pixels by which to offset the first\nand last labels; for example, a value of 2 will flush-align the first and last labels and\nalso push them 2 pixels outward from the center of the axis. The additional adjustment\ncan sometimes help the labels better visually group with corresponding axis ticks.\n\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`."
+                },
+                "labelOverlap": {
+                    "$ref": "#/definitions/LabelOverlapUnion",
+                    "description": "The strategy to use for resolving overlap of axis labels. If `false` (the default), no\noverlap reduction is attempted. If set to `true` or `\"parity\"`, a strategy of removing\nevery other label is used (this works well for standard linear axes). If set to\n`\"greedy\"`, a linear scan of the labels is performed, removing any labels that overlaps\nwith the last visible label (this often works better for log-scaled axes).\n\n__Default value:__ `true` for non-nominal fields with non-log scales; `\"greedy\"` for log\nscales; otherwise `false`."
+                },
+                "labelPadding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between axis and text labels."
+                },
+                "labels": {
+                    "type": "boolean",
+                    "description": "A boolean flag indicating if labels should be included as part of the axis.\n\n__Default value:__  `true`."
+                },
+                "maxExtent": {
+                    "type": "number",
+                    "description": "The maximum extent in pixels that axis ticks and labels should use. This determines a\nmaximum offset value for axis titles.\n\n__Default value:__ `undefined`."
+                },
+                "minExtent": {
+                    "type": "number",
+                    "description": "The minimum extent in pixels that axis ticks and labels should use. This determines a\nminimum offset value for axis titles.\n\n__Default value:__ `30` for y-axis; `undefined` for x-axis."
+                },
+                "offset": {
+                    "type": "number",
+                    "description": "The offset, in pixels, by which to displace the axis from the edge of the enclosing group\nor data rectangle.\n\n__Default value:__ derived from the [axis config](config.html#facet-scale-config)'s\n`offset` (`0` by default)"
+                },
+                "orient": {
+                    "$ref": "#/definitions/TitleOrient",
+                    "description": "The orientation of the axis. One of `\"top\"`, `\"bottom\"`, `\"left\"` or `\"right\"`. The\norientation can be used to further specialize the axis type (e.g., a y axis oriented for\nthe right edge of the chart).\n\n__Default value:__ `\"bottom\"` for x-axes and `\"left\"` for y-axes."
+                },
+                "position": {
+                    "type": "number",
+                    "description": "The anchor position of the axis in pixels. For x-axis with top or bottom orientation,\nthis sets the axis group x coordinate. For y-axis with left or right orientation, this\nsets the axis group y coordinate.\n\n__Default value__: `0`"
+                },
+                "tickCount": {
+                    "type": "number",
+                    "description": "A desired number of ticks, for axes visualizing quantitative scales. The resulting number\nmay be different so that values are \"nice\" (multiples of 2, 5, 10) and lie within the\nunderlying scale's range."
+                },
+                "ticks": {
+                    "type": "boolean",
+                    "description": "Boolean value that determines whether the axis should include ticks."
+                },
+                "tickSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The size in pixels of axis ticks."
+                },
+                "title": {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        },
+                        {
+                            "type": "string"
+                        }
+                    ],
+                    "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function\n(`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the\nfunction is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is\nbinned or has a time unit applied, the applied function will be denoted in parentheses\n(e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is\nsimply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle`\nproperty in the [config](config.html) or [`fieldTitle` function via the `compile`\nfunction's options](compile.html#field-title)."
+                },
+                "titleMaxLength": {
+                    "type": "number",
+                    "description": "Max length for axis title if the title is automatically generated from the field's\ndescription."
+                },
+                "titlePadding": {
+                    "type": "number",
+                    "description": "The padding, in pixels, between title and axis."
+                },
+                "values": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/AxisValue"
+                    },
+                    "description": "Explicitly set the visible axis tick values."
+                },
+                "zindex": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "A non-positive integer indicating z-index of the axis.\nIf zindex is 0, axes should be drawn behind all chart elements.\nTo put them in front, use `\"zindex = 1\"`.\n\n__Default value:__ `1` (in front of the marks) for actual axis and `0` (behind the marks)\nfor grids."
+                }
+            },
+            "required": [],
+            "title": "Axis"
+        },
+        "MarkDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "align": {
+                    "$ref": "#/definitions/HorizontalAlign",
+                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
+                },
+                "angle": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 360,
+                    "description": "The rotation angle of the text, in degrees."
+                },
+                "baseline": {
+                    "$ref": "#/definitions/VerticalAlign",
+                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
+                },
+                "clip": {
+                    "type": "boolean",
+                    "description": "Whether a mark be clipped to the enclosing group’s width and height."
+                },
+                "color": {
+                    "type": "string",
+                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "cursor": {
+                    "$ref": "#/definitions/Cursor",
+                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
+                },
+                "dx": {
+                    "type": "number",
+                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "dy": {
+                    "type": "number",
+                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                },
+                "fill": {
+                    "type": "string",
+                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                },
+                "filled": {
+                    "type": "boolean",
+                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
+                },
+                "fillOpacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                },
+                "font": {
+                    "type": "string",
+                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
+                },
+                "fontSize": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The font size, in pixels."
+                },
+                "fontStyle": {
+                    "$ref": "#/definitions/FontStyle",
+                    "description": "The font style (e.g., `\"italic\"`)."
+                },
+                "fontWeight": {
+                    "$ref": "#/definitions/FontWeightUnion",
+                    "description": "The font weight (e.g., `\"bold\"`)."
+                },
+                "href": {
+                    "type": "string",
+                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
+                },
+                "interpolate": {
+                    "$ref": "#/definitions/Interpolate",
+                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
+                },
+                "limit": {
+                    "type": "number",
+                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
+                },
+                "opacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
+                },
+                "orient": {
+                    "$ref": "#/definitions/Orient",
+                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
+                },
+                "radius": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                },
+                "shape": {
+                    "type": "string",
+                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
+                },
+                "size": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
+                },
+                "stroke": {
+                    "type": "string",
+                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                },
+                "strokeDash": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
+                },
+                "strokeDashOffset": {
+                    "type": "number",
+                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
+                },
+                "strokeOpacity": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                },
+                "strokeWidth": {
+                    "type": "number",
+                    "minimum": 0,
+                    "description": "The stroke width, in pixels."
+                },
+                "style": {
+                    "$ref": "#/definitions/Style",
+                    "description": "A string or array of strings indicating the name of custom styles to apply to the mark. A\nstyle is a named collection of mark property defaults defined within the [style\nconfiguration](mark.html#style-config). If style is an array, later styles will override\nearlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within\nthe `encoding` will override a style default.\n\n__Default value:__ The mark's name.  For example, a bar mark will have style `\"bar\"` by\ndefault.\n__Note:__ Any specified style will augment the default style. For example, a bar mark\nwith `\"style\": \"foo\"` will receive from `config.style.bar` and `config.style.foo` (the\nspecified style `\"foo\"` has higher precedence)."
+                },
+                "tension": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
+                },
+                "text": {
+                    "type": "string",
+                    "description": "Placeholder text if the `text` channel is not specified"
+                },
+                "theta": {
+                    "type": "number",
+                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
+                },
+                "type": {
+                    "$ref": "#/definitions/Mark",
+                    "description": "The mark type.\nOne of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`, `\"line\"`,\n`\"area\"`, `\"point\"`, `\"geoshape\"`, `\"rule\"`, and `\"text\"`."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "MarkDef"
+        },
+        "Projection": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "center": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "Sets the projection’s center to the specified center, a two-element array of longitude\nand latitude in degrees.\n\n__Default value:__ `[0, 0]`"
+                },
+                "clipAngle": {
+                    "type": "number",
+                    "description": "Sets the projection’s clipping circle radius to the specified angle in degrees. If\n`null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather\nthan small-circle clipping."
+                },
+                "clipExtent": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
+                    },
+                    "description": "Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent\nbounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of\nthe viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no\nviewport clipping is performed."
+                },
+                "coefficient": {
+                    "type": "number"
+                },
+                "distance": {
+                    "type": "number"
+                },
+                "fraction": {
+                    "type": "number"
+                },
+                "lobes": {
+                    "type": "number"
+                },
+                "parallel": {
+                    "type": "number"
+                },
+                "precision": {
+                    "$ref": "#/definitions/FluffyPrecision",
+                    "description": "Sets the threshold for the projection’s [adaptive\nresampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This\nvalue corresponds to the [Douglas–Peucker\ndistance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).\nIf precision is not specified, returns the projection’s current resampling precision\nwhich defaults to `√0.5 ≅ 0.70710…`."
+                },
+                "radius": {
+                    "type": "number"
+                },
+                "ratio": {
+                    "type": "number"
+                },
+                "rotate": {
+                    "type": "array",
+                    "items": {
+                        "type": "number"
+                    },
+                    "description": "Sets the projection’s three-axis rotation to the specified angles, which must be a two-\nor three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation\nangles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)\n\n__Default value:__ `[0, 0, 0]`"
+                },
+                "spacing": {
+                    "type": "number"
+                },
+                "tilt": {
+                    "type": "number"
+                },
+                "type": {
+                    "$ref": "#/definitions/VGProjectionType",
+                    "description": "The cartographic projection to use. This value is case-insensitive, for example\n`\"albers\"` and `\"Albers\"` indicate the same projection type. You can find all valid\nprojection types [in the\ndocumentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\n\n__Default value:__ `mercator`"
+                }
+            },
+            "required": [],
+            "title": "Projection",
+            "description": "An object defining properties of geographic projection.\n\nWorks with `\"geoshape\"` marks and `\"point\"` or `\"line\"` marks that have a channel (one or more of `\"X\"`, `\"X2\"`, `\"Y\"`, `\"Y2\"`) with type `\"latitude\"`, or `\"longitude\"`."
+        },
+        "FluffyPrecision": {
+            "type": "object",
+            "additionalProperties": {
+                "type": "string"
+            },
+            "properties": {
+                "length": {
+                    "type": "number",
+                    "description": "Returns the length of a String object."
+                }
+            },
+            "required": [
+                "length"
+            ],
+            "title": "FluffyPrecision",
+            "description": "Sets the threshold for the projection’s [adaptive resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This value corresponds to the [Douglas–Peucker distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm). If precision is not specified, returns the projection’s current resampling precision which defaults to `√0.5 ≅ 0.70710…`."
+        },
+        "SingleSelection": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "bind": {
+                    "type": "object",
+                    "additionalProperties": {
+                        "$ref": "#/definitions/VGBinding"
+                    },
+                    "description": "Establish a two-way binding between a single selection and input elements\n(also known as dynamic query widgets). A binding takes the form of\nVega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)\nor can be a mapping between projected field/encodings and binding definitions.\n\nSee the [bind transform](bind.html) documentation for more information."
+                },
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
                 },
-                "titlePadding": {
-                    "type": "number",
-                    "description": "The padding, in pixels, between title and axis."
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
                 },
-                "values": {
+                "fields": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/AxisValue"
+                        "type": "string"
                     },
-                    "description": "Explicitly set the visible axis tick values."
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
                 },
-                "zindex": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "A non-positive integer indicating z-index of the axis.\nIf zindex is 0, axes should be drawn behind all chart elements.\nTo put them in front, use `\"zindex = 1\"`.\n\n__Default value:__ `1` (in front of the marks) for actual axis and `0` (behind the marks)\nfor grids."
+                "nearest": {
+                    "type": "boolean",
+                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
+                },
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                },
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                },
+                "type": {
+                    "$ref": "#/definitions/StickyType"
                 }
             },
-            "required": [],
-            "title": "Axis"
+            "required": [
+                "type"
+            ],
+            "title": "SingleSelection"
         },
-        "X2Class": {
+        "MultiSelection": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "aggregate": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "Aggregation function for the field\n(e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).\n\n__Default value:__ `undefined` (None)"
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
                 },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "A flag for binning a `quantitative` field, or [an object defining binning\nparameters](bin.html#params).\nIf `true`, default [binning parameters](bin.html) will be applied.\n\n__Default value:__ `false`"
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
                 },
-                "field": {
-                    "$ref": "#/definitions/Field",
-                    "description": "__Required.__ A string defining the name of the field from which to pull a data value\nor an object defining iterated values from the [`repeat`](repeat.html) operator.\n\n__Note:__ Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects\n(e.g., `\"field\": \"foo.bar\"` and `\"field\": \"foo['bar']\"`).\nIf field names contain dots or brackets but are not nested, you can use `\\\\` to escape\ndots and brackets (e.g., `\"a\\\\.b\"` and `\"a\\\\[0\\\\]\"`).\nSee more details about escaping in the [field documentation](field.html).\n\n__Note:__ `field` is not required if `aggregate` is `count`."
+                "fields": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
                 },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field.\nor [a temporal field that gets casted as ordinal](type.html#cast).\n\n__Default value:__ `undefined` (None)"
+                "nearest": {
+                    "type": "boolean",
+                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
                 },
-                "type": {
-                    "$ref": "#/definitions/Type",
-                    "description": "The encoded field's type of measurement (`\"quantitative\"`, `\"temporal\"`, `\"ordinal\"`, or\n`\"nominal\"`).\nIt can also be a geo type (`\"latitude\"`, `\"longitude\"`, and `\"geojson\"`) when a\n[geographic projection](projection.html) is applied."
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
                 },
-                "value": {
-                    "$ref": "#/definitions/ConditionalValueDefValue",
-                    "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between\n`0` to `1` for opacity)."
-                }
-            },
-            "required": [],
-            "title": "X2Class",
-            "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`.\nY2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`.\nDefinition object for a data field, its type and transformation of an encoding channel.\nDefinition object for a constant value of an encoding channel."
-        },
-        "FacetMapping": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "column": {
-                    "$ref": "#/definitions/FacetFieldDef",
-                    "description": "Horizontal facets for trellis plots."
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
                 },
-                "row": {
-                    "$ref": "#/definitions/FacetFieldDef",
-                    "description": "Vertical facets for trellis plots."
+                "toggle": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "Controls whether data values should be toggled or only ever inserted into\nmulti selections. Can be `true`, `false` (for insertion only), or a\n[Vega expression](https://vega.github.io/vega/docs/expressions/).\n\n__Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,\ndata values are toggled when a user interacts with the shift-key pressed).\n\nSee the [toggle transform](toggle.html) documentation for more information."
+                },
+                "type": {
+                    "$ref": "#/definitions/IndigoType"
                 }
             },
-            "required": [],
-            "title": "FacetMapping",
-            "description": "An object that describes mappings between `row` and `column` channels and their field definitions."
+            "required": [
+                "type"
+            ],
+            "title": "MultiSelection"
         },
-        "Spec": {
+        "IntervalSelection": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "data": {
-                    "$ref": "#/definitions/Data",
-                    "description": "An object describing the data source"
+                "bind": {
+                    "$ref": "#/definitions/Bind",
+                    "description": "Establishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
                 },
-                "description": {
-                    "type": "string",
-                    "description": "Description of this mark for commenting purpose."
+                "empty": {
+                    "$ref": "#/definitions/Empty",
+                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
                 },
-                "height": {
-                    "type": "number",
-                    "description": "The height of a visualization.\n\n__Default value:__\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its y-channel has a\n[continuous scale](scale.html#continuous), the height will be the value of\n[`config.view.height`](spec.html#config).\n- For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the height is [determined by the range step, paddings, and the\ncardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the\n`rangeStep` is `null`, the height will be the value of\n[`config.view.height`](spec.html#config).\n- If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.\n\n__Note__: For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the height of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
+                "encodings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/SingleDefChannel"
+                    },
+                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
                 },
-                "layer": {
+                "fields": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/LayerSpec"
+                        "type": "string"
                     },
-                    "description": "Layer or single view specifications to be layered.\n\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as\nlayering facet specifications is not allowed."
+                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
                 },
-                "name": {
-                    "type": "string",
-                    "description": "Name of the visualization for later reference."
+                "mark": {
+                    "$ref": "#/definitions/BrushConfig",
+                    "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
                 },
-                "resolve": {
-                    "$ref": "#/definitions/Resolve",
-                    "description": "Scale, axis, and legend resolutions for layers.\n\nScale, axis, and legend resolutions for facets.\n\nScale and legend resolutions for repeated charts.\n\nScale, axis, and legend resolutions for vertically concatenated charts.\n\nScale, axis, and legend resolutions for horizontally concatenated charts."
+                "on": {
+                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
                 },
-                "title": {
-                    "$ref": "#/definitions/Title",
-                    "description": "Title for the plot."
+                "resolve": {
+                    "$ref": "#/definitions/SelectionResolution",
+                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
                 },
-                "transform": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/Transform"
-                    },
-                    "description": "An array of data transformations such as filter and new field calculation."
+                "translate": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "When truthy, allows a user to interactively move an interval selection\nback-and-forth. Can be `true`, `false` (to disable panning), or a\n[Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)\nwhich must include a start and end event to trigger continuous panning.\n\n__Default value:__ `true`, which corresponds to\n`[mousedown, window:mouseup] > window:mousemove!` which corresponds to\nclicks and dragging within an interval selection to reposition it."
                 },
-                "width": {
-                    "type": "number",
-                    "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
+                "type": {
+                    "$ref": "#/definitions/IndecentType"
                 },
-                "encoding": {
-                    "$ref": "#/definitions/Encoding",
-                    "description": "A key-value mapping between encoding channels and definition of fields."
+                "zoom": {
+                    "$ref": "#/definitions/Translate",
+                    "description": "When truthy, allows a user to interactively resize an interval selection.\nCan be `true`, `false` (to disable zooming), or a [Vega event stream\ndefinition](https://vega.github.io/vega/docs/event-streams/). Currently,\nonly `wheel` events are supported.\n\n\n__Default value:__ `true`, which corresponds to `wheel!`."
+                }
+            },
+            "required": [
+                "type"
+            ],
+            "title": "IntervalSelection"
+        },
+        "TitleParams": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "anchor": {
+                    "$ref": "#/definitions/Anchor",
+                    "description": "The anchor position for placing the title. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For\nexample, with an orientation of top these anchor positions map to a left-, center-, or\nright-aligned title.\n\n__Default value:__ `\"middle\"` for [single](spec.html) and [layered](layer.html) views.\n`\"start\"` for other composite views.\n\n__Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only\ncustomizable only for [single](spec.html) and [layered](layer.html) views.  For other\ncomposite views, `anchor` is always `\"start\"`."
                 },
-                "mark": {
-                    "$ref": "#/definitions/AnyMark",
-                    "description": "A string describing the mark type (one of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`,\n`\"line\"`,\n* `\"area\"`, `\"point\"`, `\"rule\"`, `\"geoshape\"`, and `\"text\"`) or a [mark definition\nobject](mark.html#mark-def)."
+                "offset": {
+                    "type": "number",
+                    "description": "The orthogonal offset in pixels by which to displace the title from its position along\nthe edge of the chart."
                 },
-                "projection": {
-                    "$ref": "#/definitions/Projection",
-                    "description": "An object defining properties of geographic projection.\n\nWorks with `\"geoshape\"` marks and `\"point\"` or `\"line\"` marks that have a channel (one or\nmore of `\"X\"`, `\"X2\"`, `\"Y\"`, `\"Y2\"`) with type `\"latitude\"`, or `\"longitude\"`."
+                "orient": {
+                    "$ref": "#/definitions/TitleOrient",
+                    "description": "The orientation of the title relative to the chart. One of `\"top\"` (the default),\n`\"bottom\"`, `\"left\"`, or `\"right\"`."
                 },
-                "selection": {
-                    "type": "object",
-                    "additionalProperties": {
-                        "$ref": "#/definitions/SelectionDef"
-                    },
-                    "description": "A key-value mapping between selection names and definitions."
+                "style": {
+                    "$ref": "#/definitions/Style",
+                    "description": "A [mark style property](config.html#style) to apply to the title text mark.\n\n__Default value:__ `\"group-title\"`."
                 },
-                "facet": {
-                    "$ref": "#/definitions/FacetMapping",
-                    "description": "An object that describes mappings between `row` and `column` channels and their field\ndefinitions."
+                "text": {
+                    "type": "string",
+                    "description": "The title text."
+                }
+            },
+            "required": [
+                "text"
+            ],
+            "title": "TitleParams"
+        },
+        "FilterTransform": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "filter": {
+                    "$ref": "#/definitions/LogicalOperandPredicate",
+                    "description": "The `filter` property must be one of the predicate definitions:\n(1) an [expression](types.html#expression) string,\nwhere `datum` can be used to refer to the current data object;\n(2) one of the field predicates: [equal predicate](filter.html#equal-predicate);\n[range predicate](filter.html#range-predicate), [one-of\npredicate](filter.html#one-of-predicate);\n(3) a [selection predicate](filter.html#selection-predicate);\nor (4) a logical operand that combines (1), (2), or (3)."
+                }
+            },
+            "required": [
+                "filter"
+            ],
+            "title": "FilterTransform"
+        },
+        "CalculateTransform": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "as": {
+                    "type": "string",
+                    "description": "The field for storing the computed formula value."
                 },
-                "spec": {
-                    "$ref": "#/definitions/Spec",
-                    "description": "A specification of the view that gets faceted."
+                "calculate": {
+                    "type": "string",
+                    "description": "A [expression](types.html#expression) string. Use the variable `datum` to refer to the\ncurrent data object."
+                }
+            },
+            "required": [
+                "as",
+                "calculate"
+            ],
+            "title": "CalculateTransform"
+        },
+        "LookupTransform": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "as": {
+                    "$ref": "#/definitions/Style",
+                    "description": "The field or fields for storing the computed formula value.\nIf `from.fields` is specified, the transform will use the same names for `as`.\nIf `from.fields` is not specified, `as` has to be a string and we put the whole object\ninto the data under the specified name."
                 },
-                "repeat": {
-                    "$ref": "#/definitions/Repeat",
-                    "description": "An object that describes what fields should be repeated into views that are laid out as a\n`row` or `column`."
+                "default": {
+                    "type": "string",
+                    "description": "The default value to use if lookup fails.\n\n__Default value:__ `null`"
                 },
-                "vconcat": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/Spec"
-                    },
-                    "description": "A list of views that should be concatenated and put into a column."
+                "from": {
+                    "$ref": "#/definitions/LookupData",
+                    "description": "Secondary data reference."
                 },
-                "hconcat": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/Spec"
-                    },
-                    "description": "A list of views that should be concatenated and put into a row."
+                "lookup": {
+                    "type": "string",
+                    "description": "Key in primary data source."
                 }
             },
-            "required": [],
-            "title": "Spec",
-            "description": "Unit spec that can have a composite mark."
+            "required": [
+                "from",
+                "lookup"
+            ],
+            "title": "LookupTransform"
         },
-        "Encoding": {
+        "BinTransform": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "color": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark\nconfig](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color\nscheme](scale.html#scheme)."
-                },
-                "detail": {
-                    "$ref": "#/definitions/Detail",
-                    "description": "Additional levels of detail for grouping data in aggregate views and\nin line and area marks without mapping data to a specific visual channel."
-                },
-                "href": {
-                    "$ref": "#/definitions/DefWithCondition",
-                    "description": "A URL to load upon mouse click."
-                },
-                "opacity": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Opacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark\nconfig](config.html#mark)'s `opacity` property."
-                },
-                "order": {
-                    "$ref": "#/definitions/Order",
-                    "description": "Stack order for stacked marks or order of data points in line marks for connected scatter\nplots.\n\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating\nadditional aggregation grouping."
-                },
-                "shape": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "For `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark\nconfig](config.html#point-config)'s `shape` property."
-                },
-                "size": {
-                    "$ref": "#/definitions/MarkPropDefWithCondition",
-                    "description": "Size of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`."
-                },
-                "text": {
-                    "$ref": "#/definitions/TextDefWithCondition",
-                    "description": "Text of the `text` mark."
-                },
-                "tooltip": {
-                    "$ref": "#/definitions/TextDefWithCondition",
-                    "description": "The tooltip text to show upon mouse hover."
-                },
-                "x": {
-                    "$ref": "#/definitions/XClass",
-                    "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`."
-                },
-                "x2": {
-                    "$ref": "#/definitions/X2Class",
-                    "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+                "as": {
+                    "type": "string",
+                    "description": "The output fields at which to write the start and end bin values."
                 },
-                "y": {
-                    "$ref": "#/definitions/XClass",
-                    "description": "Y coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`."
+                "bin": {
+                    "$ref": "#/definitions/Bin",
+                    "description": "An object indicating bin properties, or simply `true` for using default bin parameters."
                 },
-                "y2": {
-                    "$ref": "#/definitions/X2Class",
-                    "description": "Y2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+                "field": {
+                    "type": "string",
+                    "description": "The data field to bin."
                 }
             },
-            "required": [],
-            "title": "Encoding",
-            "description": "A key-value mapping between encoding channels and definition of fields."
+            "required": [
+                "as",
+                "bin",
+                "field"
+            ],
+            "title": "BinTransform"
         },
-        "LayerSpec": {
+        "TimeUnitTransform": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "data": {
-                    "$ref": "#/definitions/Data",
-                    "description": "An object describing the data source"
-                },
-                "description": {
+                "as": {
                     "type": "string",
-                    "description": "Description of this mark for commenting purpose."
+                    "description": "The output field to write the timeUnit value."
                 },
-                "height": {
-                    "type": "number",
-                    "description": "The height of a visualization.\n\n__Default value:__\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its y-channel has a\n[continuous scale](scale.html#continuous), the height will be the value of\n[`config.view.height`](spec.html#config).\n- For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the height is [determined by the range step, paddings, and the\ncardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the\n`rangeStep` is `null`, the height will be the value of\n[`config.view.height`](spec.html#config).\n- If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.\n\n__Note__: For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the height of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
+                "field": {
+                    "type": "string",
+                    "description": "The data field to apply time unit."
                 },
-                "layer": {
+                "timeUnit": {
+                    "$ref": "#/definitions/TimeUnit",
+                    "description": "The timeUnit."
+                }
+            },
+            "required": [
+                "as",
+                "field",
+                "timeUnit"
+            ],
+            "title": "TimeUnitTransform"
+        },
+        "AggregateTransform": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "aggregate": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/LayerSpec"
+                        "$ref": "#/definitions/AggregatedFieldDef"
                     },
-                    "description": "Layer or single view specifications to be layered.\n\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as\nlayering facet specifications is not allowed."
-                },
-                "name": {
-                    "type": "string",
-                    "description": "Name of the visualization for later reference."
-                },
-                "resolve": {
-                    "$ref": "#/definitions/Resolve",
-                    "description": "Scale, axis, and legend resolutions for layers."
-                },
-                "title": {
-                    "$ref": "#/definitions/Title",
-                    "description": "Title for the plot."
+                    "description": "Array of objects that define fields to aggregate."
                 },
-                "transform": {
+                "groupby": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/Transform"
-                    },
-                    "description": "An array of data transformations such as filter and new field calculation."
-                },
-                "width": {
-                    "type": "number",
-                    "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
-                },
-                "encoding": {
-                    "$ref": "#/definitions/Encoding",
-                    "description": "A key-value mapping between encoding channels and definition of fields."
-                },
-                "mark": {
-                    "$ref": "#/definitions/AnyMark",
-                    "description": "A string describing the mark type (one of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`,\n`\"line\"`,\n* `\"area\"`, `\"point\"`, `\"rule\"`, `\"geoshape\"`, and `\"text\"`) or a [mark definition\nobject](mark.html#mark-def)."
-                },
-                "projection": {
-                    "$ref": "#/definitions/Projection",
-                    "description": "An object defining properties of geographic projection.\n\nWorks with `\"geoshape\"` marks and `\"point\"` or `\"line\"` marks that have a channel (one or\nmore of `\"X\"`, `\"X2\"`, `\"Y\"`, `\"Y2\"`) with type `\"latitude\"`, or `\"longitude\"`."
-                },
-                "selection": {
-                    "type": "object",
-                    "additionalProperties": {
-                        "$ref": "#/definitions/SelectionDef"
+                        "type": "string"
                     },
-                    "description": "A key-value mapping between selection names and definitions."
+                    "description": "The data fields to group by. If not specified, a single group containing all data objects\nwill be used."
                 }
             },
-            "required": [],
-            "title": "LayerSpec",
-            "description": "Unit spec that can have a composite mark."
+            "required": [
+                "aggregate"
+            ],
+            "title": "AggregateTransform"
         },
-        "MarkDef": {
+        "LookupData": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "align": {
-                    "$ref": "#/definitions/HorizontalAlign",
-                    "description": "The horizontal alignment of the text. One of `\"left\"`, `\"right\"`, `\"center\"`."
-                },
-                "angle": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 360,
-                    "description": "The rotation angle of the text, in degrees."
-                },
-                "baseline": {
-                    "$ref": "#/definitions/VerticalAlign",
-                    "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n__Default value:__ `\"middle\"`"
-                },
-                "clip": {
-                    "type": "boolean",
-                    "description": "Whether a mark be clipped to the enclosing group’s width and height."
-                },
-                "color": {
-                    "type": "string",
-                    "description": "Default color.  Note that `fill` and `stroke` have higher precedence than `color` and\nwill override `color`.\n\n__Default value:__ <span style=\"color: #4682b4;\">&#9632;</span> `\"#4682b4\"`\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
-                "cursor": {
-                    "$ref": "#/definitions/Cursor",
-                    "description": "The mouse cursor used over the mark. Any valid [CSS cursor\ntype](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used."
-                },
-                "dx": {
-                    "type": "number",
-                    "description": "The horizontal offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "Secondary data source to lookup in."
                 },
-                "dy": {
-                    "type": "number",
-                    "description": "The vertical offset, in pixels, between the text label and its anchor point. The offset\nis applied after rotation by the _angle_ property."
+                "fields": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "Fields in foreign data to lookup.\nIf not specified, the entire object is queried."
                 },
-                "fill": {
+                "key": {
                     "type": "string",
-                    "description": "Default Fill Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
-                },
-                "filled": {
-                    "type": "boolean",
-                    "description": "Whether the mark's color should be used as fill color instead of stroke color.\n\n__Default value:__ `true` for all marks except `point` and `false` for `point`.\n\n__Applicable for:__ `bar`, `point`, `circle`, `square`, and `area` marks.\n\n__Note:__ This property cannot be used in a [style config](mark.html#style-config)."
-                },
-                "fillOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The fill opacity (value between [0,1]).\n\n__Default value:__ `1`"
-                },
-                "font": {
+                    "description": "Key in data to lookup."
+                }
+            },
+            "required": [
+                "data",
+                "key"
+            ],
+            "title": "LookupData",
+            "description": "Secondary data reference."
+        },
+        "AggregatedFieldDef": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "as": {
                     "type": "string",
-                    "description": "The typeface to set the text in (e.g., `\"Helvetica Neue\"`)."
-                },
-                "fontSize": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The font size, in pixels."
-                },
-                "fontStyle": {
-                    "$ref": "#/definitions/FontStyle",
-                    "description": "The font style (e.g., `\"italic\"`)."
-                },
-                "fontWeight": {
-                    "$ref": "#/definitions/FontWeightUnion",
-                    "description": "The font weight (e.g., `\"bold\"`)."
+                    "description": "The output field names to use for each aggregated field."
                 },
-                "href": {
+                "field": {
                     "type": "string",
-                    "description": "A URL to load upon mouse click. If defined, the mark acts as a hyperlink."
-                },
-                "interpolate": {
-                    "$ref": "#/definitions/Interpolate",
-                    "description": "The line interpolation method to use for line and area marks. One of the following:\n- `\"linear\"`: piecewise linear segments, as in a polyline.\n- `\"linear-closed\"`: close the linear segments to form a polygon.\n- `\"step\"`: alternate between horizontal and vertical segments, as in a step function.\n- `\"step-before\"`: alternate between vertical and horizontal segments, as in a step\nfunction.\n- `\"step-after\"`: alternate between horizontal and vertical segments, as in a step\nfunction.\n- `\"basis\"`: a B-spline, with control point duplication on the ends.\n- `\"basis-open\"`: an open B-spline; may not intersect the start or end.\n- `\"basis-closed\"`: a closed B-spline, as in a loop.\n- `\"cardinal\"`: a Cardinal spline, with control point duplication on the ends.\n- `\"cardinal-open\"`: an open Cardinal spline; may not intersect the start or end, but\nwill intersect other control points.\n- `\"cardinal-closed\"`: a closed Cardinal spline, as in a loop.\n- `\"bundle\"`: equivalent to basis, except the tension parameter is used to straighten the\nspline.\n- `\"monotone\"`: cubic interpolation that preserves monotonicity in y."
-                },
-                "limit": {
-                    "type": "number",
-                    "description": "The maximum length of the text mark in pixels (default 0, indicating no limit). The text\nvalue will be automatically truncated if the rendered size exceeds the limit."
-                },
-                "opacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The overall opacity (value between [0,1]).\n\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or\n`square` marks or layered `bar` charts and `1` otherwise."
-                },
-                "orient": {
-                    "$ref": "#/definitions/Orient",
-                    "description": "The orientation of a non-stacked bar, tick, area, and line charts.\nThe value is either horizontal (default) or vertical.\n- For bar, rule and tick, this determines whether the size of the bar and tick\nshould be applied to x or y dimension.\n- For area, this property determines the orient property of the Vega output.\n- For line, this property determines the sort order of the points in the line\nif `config.sortLineBy` is not specified.\nFor stacked charts, this is always determined by the orientation of the stack;\ntherefore explicitly specified value will be ignored."
+                    "description": "The data field for which to compute aggregate function."
                 },
-                "radius": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "Polar coordinate radial offset, in pixels, of the text label from the origin determined\nby the `x` and `y` properties."
+                "op": {
+                    "$ref": "#/definitions/AggregateOp",
+                    "description": "The aggregation operations to apply to the fields, such as sum, average or count.\nSee the [full list of supported aggregation\noperations](https://vega.github.io/vega-lite/docs/aggregate.html#ops)\nfor more information."
+                }
+            },
+            "required": [
+                "as",
+                "field",
+                "op"
+            ],
+            "title": "AggregatedFieldDef"
+        },
+        "LayerSpec": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "shape": {
+                "description": {
                     "type": "string",
-                    "description": "The default symbol shape to use. One of: `\"circle\"` (default), `\"square\"`, `\"cross\"`,\n`\"diamond\"`, `\"triangle-up\"`, or `\"triangle-down\"`, or a custom SVG path.\n\n__Default value:__ `\"circle\"`"
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "size": {
+                "height": {
                     "type": "number",
-                    "minimum": 0,
-                    "description": "The pixel area each the point/circle/square.\nFor example: in the case of circles, the radius is determined in part by the square root\nof the size value.\n\n__Default value:__ `30`"
-                },
-                "stroke": {
-                    "type": "string",
-                    "description": "Default Stroke Color.  This has higher precedence than config.color\n\n__Default value:__ (None)"
+                    "description": "The height of a visualization.\n\n__Default value:__\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its y-channel has a\n[continuous scale](scale.html#continuous), the height will be the value of\n[`config.view.height`](spec.html#config).\n- For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the height is [determined by the range step, paddings, and the\ncardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the\n`rangeStep` is `null`, the height will be the value of\n[`config.view.height`](spec.html#config).\n- If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.\n\n__Note__: For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the height of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 },
-                "strokeDash": {
+                "layer": {
                     "type": "array",
                     "items": {
-                        "type": "number"
+                        "$ref": "#/definitions/SpecElement"
                     },
-                    "description": "An array of alternating stroke, space lengths for creating dashed or dotted lines."
-                },
-                "strokeDashOffset": {
-                    "type": "number",
-                    "description": "The offset (in pixels) into which to begin drawing with the stroke dash array."
-                },
-                "strokeOpacity": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "The stroke opacity (value between [0,1]).\n\n__Default value:__ `1`"
+                    "description": "Layer or single view specifications to be layered.\n\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as\nlayering facet specifications is not allowed."
                 },
-                "strokeWidth": {
-                    "type": "number",
-                    "minimum": 0,
-                    "description": "The stroke width, in pixels."
+                "name": {
+                    "type": "string",
+                    "description": "Name of the visualization for later reference."
                 },
-                "style": {
-                    "$ref": "#/definitions/Style",
-                    "description": "A string or array of strings indicating the name of custom styles to apply to the mark. A\nstyle is a named collection of mark property defaults defined within the [style\nconfiguration](mark.html#style-config). If style is an array, later styles will override\nearlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within\nthe `encoding` will override a style default.\n\n__Default value:__ The mark's name.  For example, a bar mark will have style `\"bar\"` by\ndefault.\n__Note:__ Any specified style will augment the default style. For example, a bar mark\nwith `\"style\": \"foo\"` will receive from `config.style.bar` and `config.style.foo` (the\nspecified style `\"foo\"` has higher precedence)."
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for layers."
                 },
-                "tension": {
-                    "type": "number",
-                    "minimum": 0,
-                    "maximum": 1,
-                    "description": "Depending on the interpolation type, sets the tension parameter (for line and area marks)."
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "text": {
-                    "type": "string",
-                    "description": "Placeholder text if the `text` channel is not specified"
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
                 },
-                "theta": {
+                "width": {
                     "type": "number",
-                    "description": "Polar coordinate angle, in radians, of the text label from the origin determined by the\n`x` and `y` properties. Values for `theta` follow the same convention of `arc` mark\n`startAngle` and `endAngle` properties: angles are measured in radians, with `0`\nindicating \"north\"."
-                },
-                "type": {
-                    "$ref": "#/definitions/Mark",
-                    "description": "The mark type.\nOne of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`, `\"line\"`,\n`\"area\"`, `\"point\"`, `\"geoshape\"`, `\"rule\"`, and `\"text\"`."
+                    "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 }
             },
             "required": [
-                "type"
+                "layer"
             ],
-            "title": "MarkDef"
+            "title": "LayerSpec"
         },
-        "Projection": {
+        "CompositeUnitSpecAlias": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "center": {
-                    "type": "array",
-                    "items": {
-                        "type": "number"
-                    },
-                    "description": "Sets the projection’s center to the specified center, a two-element array of longitude\nand latitude in degrees.\n\n__Default value:__ `[0, 0]`"
-                },
-                "clipAngle": {
-                    "type": "number",
-                    "description": "Sets the projection’s clipping circle radius to the specified angle in degrees. If\n`null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather\nthan small-circle clipping."
-                },
-                "clipExtent": {
-                    "type": "array",
-                    "items": {
-                        "type": "array",
-                        "items": {
-                            "type": "number"
-                        }
-                    },
-                    "description": "Sets the projection’s viewport clip extent to the specified bounds in pixels. The extent\nbounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of\nthe viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no\nviewport clipping is performed."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "coefficient": {
-                    "type": "number"
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "distance": {
-                    "type": "number"
+                "encoding": {
+                    "$ref": "#/definitions/Encoding",
+                    "description": "A key-value mapping between encoding channels and definition of fields."
                 },
-                "fraction": {
-                    "type": "number"
+                "height": {
+                    "type": "number",
+                    "description": "The height of a visualization.\n\n__Default value:__\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its y-channel has a\n[continuous scale](scale.html#continuous), the height will be the value of\n[`config.view.height`](spec.html#config).\n- For y-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the height is [determined by the range step, paddings, and the\ncardinality of the field mapped to y-channel](scale.html#band). Otherwise, if the\n`rangeStep` is `null`, the height will be the value of\n[`config.view.height`](spec.html#config).\n- If no field is mapped to `y` channel, the `height` will be the value of `rangeStep`.\n\n__Note__: For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the height of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 },
-                "lobes": {
-                    "type": "number"
+                "mark": {
+                    "$ref": "#/definitions/AnyMark",
+                    "description": "A string describing the mark type (one of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`,\n`\"line\"`,\n* `\"area\"`, `\"point\"`, `\"rule\"`, `\"geoshape\"`, and `\"text\"`) or a [mark definition\nobject](mark.html#mark-def)."
                 },
-                "parallel": {
-                    "type": "number"
+                "name": {
+                    "type": "string",
+                    "description": "Name of the visualization for later reference."
                 },
-                "precision": {
-                    "$ref": "#/definitions/FluffyPrecision",
-                    "description": "Sets the threshold for the projection’s [adaptive\nresampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This\nvalue corresponds to the [Douglas–Peucker\ndistance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).\nIf precision is not specified, returns the projection’s current resampling precision\nwhich defaults to `√0.5 ≅ 0.70710…`."
+                "projection": {
+                    "$ref": "#/definitions/Projection",
+                    "description": "An object defining properties of geographic projection.\n\nWorks with `\"geoshape\"` marks and `\"point\"` or `\"line\"` marks that have a channel (one or\nmore of `\"X\"`, `\"X2\"`, `\"Y\"`, `\"Y2\"`) with type `\"latitude\"`, or `\"longitude\"`."
                 },
-                "radius": {
-                    "type": "number"
+                "selection": {
+                    "type": "object",
+                    "additionalProperties": {
+                        "$ref": "#/definitions/SelectionDef"
+                    },
+                    "description": "A key-value mapping between selection names and definitions."
                 },
-                "ratio": {
-                    "type": "number"
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "rotate": {
+                "transform": {
                     "type": "array",
                     "items": {
-                        "type": "number"
+                        "$ref": "#/definitions/Transform"
                     },
-                    "description": "Sets the projection’s three-axis rotation to the specified angles, which must be a two-\nor three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation\nangles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)\n\n__Default value:__ `[0, 0, 0]`"
-                },
-                "spacing": {
-                    "type": "number"
-                },
-                "tilt": {
-                    "type": "number"
+                    "description": "An array of data transformations such as filter and new field calculation."
                 },
-                "type": {
-                    "$ref": "#/definitions/VGProjectionType",
-                    "description": "The cartographic projection to use. This value is case-insensitive, for example\n`\"albers\"` and `\"Albers\"` indicate the same projection type. You can find all valid\nprojection types [in the\ndocumentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\n\n__Default value:__ `mercator`"
-                }
-            },
-            "required": [],
-            "title": "Projection",
-            "description": "An object defining properties of geographic projection.\n\nWorks with `\"geoshape\"` marks and `\"point\"` or `\"line\"` marks that have a channel (one or more of `\"X\"`, `\"X2\"`, `\"Y\"`, `\"Y2\"`) with type `\"latitude\"`, or `\"longitude\"`."
-        },
-        "FluffyPrecision": {
-            "type": "object",
-            "additionalProperties": {
-                "type": "string"
-            },
-            "properties": {
-                "length": {
+                "width": {
                     "type": "number",
-                    "description": "Returns the length of a String object."
+                    "description": "The width of a visualization.\n\n__Default value:__ This will be determined by the following rules:\n\n- If a view's [`autosize`](size.html#autosize) type is `\"fit\"` or its x-channel has a\n[continuous scale](scale.html#continuous), the width will be the value of\n[`config.view.width`](spec.html#config).\n- For x-axis with a band or point scale: if [`rangeStep`](scale.html#band) is a numeric\nvalue or unspecified, the width is [determined by the range step, paddings, and the\ncardinality of the field mapped to x-channel](scale.html#band).   Otherwise, if the\n`rangeStep` is `null`, the width will be the value of\n[`config.view.width`](spec.html#config).\n- If no field is mapped to `x` channel, the `width` will be the value of\n[`config.scale.textXRangeStep`](size.html#default-width-and-height) for `text` mark and\nthe value of `rangeStep` for other marks.\n\n__Note:__ For plots with [`row` and `column` channels](encoding.html#facet), this\nrepresents the width of a single view.\n\n__See also:__ The documentation for [width and height](size.html) contains more examples."
                 }
             },
             "required": [
-                "length"
+                "encoding",
+                "mark"
             ],
-            "title": "FluffyPrecision",
-            "description": "Sets the threshold for the projection’s [adaptive resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This value corresponds to the [Douglas–Peucker distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm). If precision is not specified, returns the projection’s current resampling precision which defaults to `√0.5 ≅ 0.70710…`."
+            "title": "CompositeUnitSpecAlias",
+            "description": "Unit spec that can have a composite mark."
         },
         "Resolve": {
             "type": "object",
@@ -3963,260 +4915,308 @@
             "required": [],
             "title": "ScaleResolveMap"
         },
-        "SelectionDef": {
+        "Encoding": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "bind": {
-                    "$ref": "#/definitions/BindUnion",
-                    "description": "Establish a two-way binding between a single selection and input elements\n(also known as dynamic query widgets). A binding takes the form of\nVega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)\nor can be a mapping between projected field/encodings and binding definitions.\n\nSee the [bind transform](bind.html) documentation for more information.\n\nEstablishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
+                "color": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark\nconfig](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color\nscheme](scale.html#scheme)."
                 },
-                "empty": {
-                    "$ref": "#/definitions/Empty",
-                    "description": "By default, all data values are considered to lie within an empty selection.\nWhen set to `none`, empty selections contain no data values."
+                "detail": {
+                    "$ref": "#/definitions/Detail",
+                    "description": "Additional levels of detail for grouping data in aggregate views and\nin line and area marks without mapping data to a specific visual channel."
                 },
-                "encodings": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/SingleDefChannel"
-                    },
-                    "description": "An array of encoding channels. The corresponding data field values\nmust match for a data tuple to fall within the selection."
+                "href": {
+                    "$ref": "#/definitions/Href",
+                    "description": "A URL to load upon mouse click."
                 },
-                "fields": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "An array of field names whose values must match for a data tuple to\nfall within the selection."
+                "opacity": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Opacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark\nconfig](config.html#mark)'s `opacity` property."
                 },
-                "nearest": {
-                    "type": "boolean",
-                    "description": "When true, an invisible voronoi diagram is computed to accelerate discrete\nselection. The data value _nearest_ the mouse cursor is added to the selection.\n\nSee the [nearest transform](nearest.html) documentation for more information."
+                "order": {
+                    "$ref": "#/definitions/Order",
+                    "description": "Stack order for stacked marks or order of data points in line marks for connected scatter\nplots.\n\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating\nadditional aggregation grouping."
                 },
-                "on": {
-                    "description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or\nselector) that triggers the selection.\nFor interval selections, the event stream must specify a [start and\nend](https://vega.github.io/vega/docs/event-streams/#between-filters)."
+                "shape": {
+                    "$ref": "#/definitions/Color",
+                    "description": "For `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark\nconfig](config.html#point-config)'s `shape` property."
                 },
-                "resolve": {
-                    "$ref": "#/definitions/SelectionResolution",
-                    "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
+                "size": {
+                    "$ref": "#/definitions/Color",
+                    "description": "Size of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`."
                 },
-                "type": {
-                    "$ref": "#/definitions/SelectionDefType"
+                "text": {
+                    "$ref": "#/definitions/Text",
+                    "description": "Text of the `text` mark."
                 },
-                "toggle": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "Controls whether data values should be toggled or only ever inserted into\nmulti selections. Can be `true`, `false` (for insertion only), or a\n[Vega expression](https://vega.github.io/vega/docs/expressions/).\n\n__Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,\ndata values are toggled when a user interacts with the shift-key pressed).\n\nSee the [toggle transform](toggle.html) documentation for more information."
+                "tooltip": {
+                    "$ref": "#/definitions/Text",
+                    "description": "The tooltip text to show upon mouse hover."
                 },
-                "mark": {
-                    "$ref": "#/definitions/BrushConfig",
-                    "description": "An interval selection also adds a rectangle mark to depict the\nextents of the interval. The `mark` property can be used to customize the\nappearance of the mark."
+                "x": {
+                    "$ref": "#/definitions/X",
+                    "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`."
                 },
-                "translate": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "When truthy, allows a user to interactively move an interval selection\nback-and-forth. Can be `true`, `false` (to disable panning), or a\n[Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)\nwhich must include a start and end event to trigger continuous panning.\n\n__Default value:__ `true`, which corresponds to\n`[mousedown, window:mouseup] > window:mousemove!` which corresponds to\nclicks and dragging within an interval selection to reposition it."
+                "x2": {
+                    "$ref": "#/definitions/X2",
+                    "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
                 },
-                "zoom": {
-                    "$ref": "#/definitions/Translate",
-                    "description": "When truthy, allows a user to interactively resize an interval selection.\nCan be `true`, `false` (to disable zooming), or a [Vega event stream\ndefinition](https://vega.github.io/vega/docs/event-streams/). Currently,\nonly `wheel` events are supported.\n\n\n__Default value:__ `true`, which corresponds to `wheel!`."
+                "y": {
+                    "$ref": "#/definitions/X",
+                    "description": "Y coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`."
+                },
+                "y2": {
+                    "$ref": "#/definitions/X2",
+                    "description": "Y2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
                 }
             },
-            "required": [
-                "type"
-            ],
-            "title": "SelectionDef"
+            "required": [],
+            "title": "Encoding",
+            "description": "A key-value mapping between encoding channels and definition of fields."
         },
-        "VGBinding": {
+        "FacetMapping": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "element": {
-                    "type": "string"
-                },
-                "input": {
-                    "type": "string"
+                "column": {
+                    "$ref": "#/definitions/FacetFieldDef",
+                    "description": "Horizontal facets for trellis plots."
                 },
-                "options": {
+                "row": {
+                    "$ref": "#/definitions/FacetFieldDef",
+                    "description": "Vertical facets for trellis plots."
+                }
+            },
+            "required": [],
+            "title": "FacetMapping",
+            "description": "An object that describes mappings between `row` and `column` channels and their field definitions."
+        },
+        "Repeat": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+                "column": {
                     "type": "array",
                     "items": {
                         "type": "string"
-                    }
-                },
-                "max": {
-                    "type": "number"
-                },
-                "min": {
-                    "type": "number"
+                    },
+                    "description": "Horizontal repeated views."
                 },
-                "step": {
-                    "type": "number"
+                "row": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "Vertical repeated views."
                 }
             },
-            "required": [
-                "input"
-            ],
-            "title": "VGBinding"
+            "required": [],
+            "title": "Repeat",
+            "description": "An object that describes what fields should be repeated into views that are laid out as a `row` or `column`."
         },
-        "TitleParams": {
+        "FacetSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "anchor": {
-                    "$ref": "#/definitions/Anchor",
-                    "description": "The anchor position for placing the title. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For\nexample, with an orientation of top these anchor positions map to a left-, center-, or\nright-aligned title.\n\n__Default value:__ `\"middle\"` for [single](spec.html) and [layered](layer.html) views.\n`\"start\"` for other composite views.\n\n__Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only\ncustomizable only for [single](spec.html) and [layered](layer.html) views.  For other\ncomposite views, `anchor` is always `\"start\"`."
-                },
-                "offset": {
-                    "type": "number",
-                    "description": "The orthogonal offset in pixels by which to displace the title from its position along\nthe edge of the chart."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "orient": {
-                    "$ref": "#/definitions/TitleOrient",
-                    "description": "The orientation of the title relative to the chart. One of `\"top\"` (the default),\n`\"bottom\"`, `\"left\"`, or `\"right\"`."
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "style": {
-                    "$ref": "#/definitions/Style",
-                    "description": "A [mark style property](config.html#style) to apply to the title text mark.\n\n__Default value:__ `\"group-title\"`."
+                "facet": {
+                    "$ref": "#/definitions/FacetMapping",
+                    "description": "An object that describes mappings between `row` and `column` channels and their field\ndefinitions."
                 },
-                "text": {
+                "name": {
                     "type": "string",
-                    "description": "The title text."
+                    "description": "Name of the visualization for later reference."
+                },
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for facets."
+                },
+                "spec": {
+                    "$ref": "#/definitions/SpecElement",
+                    "description": "A specification of the view that gets faceted."
+                },
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
+                },
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
                 }
             },
             "required": [
-                "text"
+                "facet",
+                "spec"
             ],
-            "title": "TitleParams"
+            "title": "FacetSpec"
         },
-        "Transform": {
+        "RepeatSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "filter": {
-                    "$ref": "#/definitions/LogicalOperandPredicate",
-                    "description": "The `filter` property must be one of the predicate definitions:\n(1) an [expression](types.html#expression) string,\nwhere `datum` can be used to refer to the current data object;\n(2) one of the field predicates: [equal predicate](filter.html#equal-predicate);\n[range predicate](filter.html#range-predicate), [one-of\npredicate](filter.html#one-of-predicate);\n(3) a [selection predicate](filter.html#selection-predicate);\nor (4) a logical operand that combines (1), (2), or (3)."
-                },
-                "as": {
-                    "$ref": "#/definitions/Style",
-                    "description": "The field for storing the computed formula value.\n\nThe field or fields for storing the computed formula value.\nIf `from.fields` is specified, the transform will use the same names for `as`.\nIf `from.fields` is not specified, `as` has to be a string and we put the whole object\ninto the data under the specified name.\n\nThe output fields at which to write the start and end bin values.\n\nThe output field to write the timeUnit value."
-                },
-                "calculate": {
-                    "type": "string",
-                    "description": "A [expression](types.html#expression) string. Use the variable `datum` to refer to the\ncurrent data object."
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
                 },
-                "default": {
+                "description": {
                     "type": "string",
-                    "description": "The default value to use if lookup fails.\n\n__Default value:__ `null`"
-                },
-                "from": {
-                    "$ref": "#/definitions/LookupData",
-                    "description": "Secondary data reference."
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "lookup": {
+                "name": {
                     "type": "string",
-                    "description": "Key in primary data source."
+                    "description": "Name of the visualization for later reference."
                 },
-                "bin": {
-                    "$ref": "#/definitions/Bin",
-                    "description": "An object indicating bin properties, or simply `true` for using default bin parameters."
+                "repeat": {
+                    "$ref": "#/definitions/Repeat",
+                    "description": "An object that describes what fields should be repeated into views that are laid out as a\n`row` or `column`."
                 },
-                "field": {
-                    "type": "string",
-                    "description": "The data field to bin.\n\nThe data field to apply time unit."
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale and legend resolutions for repeated charts."
                 },
-                "timeUnit": {
-                    "$ref": "#/definitions/TimeUnit",
-                    "description": "The timeUnit."
+                "spec": {
+                    "$ref": "#/definitions/Spec"
                 },
-                "aggregate": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/definitions/AggregatedFieldDef"
-                    },
-                    "description": "Array of objects that define fields to aggregate."
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
                 },
-                "groupby": {
+                "transform": {
                     "type": "array",
                     "items": {
-                        "type": "string"
+                        "$ref": "#/definitions/Transform"
                     },
-                    "description": "The data fields to group by. If not specified, a single group containing all data objects\nwill be used."
+                    "description": "An array of data transformations such as filter and new field calculation."
                 }
             },
-            "required": [],
-            "title": "Transform"
+            "required": [
+                "repeat",
+                "spec"
+            ],
+            "title": "RepeatSpec"
         },
-        "AggregatedFieldDef": {
+        "VConcatSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
-                "as": {
+                "data": {
+                    "$ref": "#/definitions/Data",
+                    "description": "An object describing the data source"
+                },
+                "description": {
                     "type": "string",
-                    "description": "The output field names to use for each aggregated field."
+                    "description": "Description of this mark for commenting purpose."
                 },
-                "field": {
+                "name": {
                     "type": "string",
-                    "description": "The data field for which to compute aggregate function."
+                    "description": "Name of the visualization for later reference."
                 },
-                "op": {
-                    "$ref": "#/definitions/AggregateOp",
-                    "description": "The aggregation operations to apply to the fields, such as sum, average or count.\nSee the [full list of supported aggregation\noperations](https://vega.github.io/vega-lite/docs/aggregate.html#ops)\nfor more information."
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for vertically concatenated charts."
+                },
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
+                },
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
+                },
+                "vconcat": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Spec"
+                    },
+                    "description": "A list of views that should be concatenated and put into a column."
                 }
             },
             "required": [
-                "as",
-                "field",
-                "op"
+                "vconcat"
             ],
-            "title": "AggregatedFieldDef"
+            "title": "VConcatSpec"
         },
-        "LookupData": {
+        "HConcatSpec": {
             "type": "object",
             "additionalProperties": false,
             "properties": {
                 "data": {
                     "$ref": "#/definitions/Data",
-                    "description": "Secondary data source to lookup in."
+                    "description": "An object describing the data source"
                 },
-                "fields": {
+                "description": {
+                    "type": "string",
+                    "description": "Description of this mark for commenting purpose."
+                },
+                "hconcat": {
                     "type": "array",
                     "items": {
-                        "type": "string"
+                        "$ref": "#/definitions/Spec"
                     },
-                    "description": "Fields in foreign data to lookup.\nIf not specified, the entire object is queried."
+                    "description": "A list of views that should be concatenated and put into a row."
                 },
-                "key": {
+                "name": {
                     "type": "string",
-                    "description": "Key in data to lookup."
+                    "description": "Name of the visualization for later reference."
+                },
+                "resolve": {
+                    "$ref": "#/definitions/Resolve",
+                    "description": "Scale, axis, and legend resolutions for horizontally concatenated charts."
+                },
+                "title": {
+                    "$ref": "#/definitions/Title",
+                    "description": "Title for the plot."
+                },
+                "transform": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Transform"
+                    },
+                    "description": "An array of data transformations such as filter and new field calculation."
                 }
             },
             "required": [
-                "data",
-                "key"
+                "hconcat"
             ],
-            "title": "LookupData",
-            "description": "Secondary data reference."
+            "title": "HConcatSpec"
         },
-        "Repeat": {
-            "type": "object",
-            "additionalProperties": false,
-            "properties": {
-                "column": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "Horizontal repeated views."
+        "TopLevel": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/TopLevelFacetedUnitSpec"
+                },
+                {
+                    "$ref": "#/definitions/TopLevelLayerSpec"
+                },
+                {
+                    "$ref": "#/definitions/TopLevelFacetSpec"
+                },
+                {
+                    "$ref": "#/definitions/TopLevelRepeatSpec"
                 },
-                "row": {
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    },
-                    "description": "Vertical repeated views."
+                {
+                    "$ref": "#/definitions/TopLevelVConcatSpec"
+                },
+                {
+                    "$ref": "#/definitions/TopLevelHConcatSpec"
                 }
-            },
-            "required": [],
-            "title": "Repeat",
-            "description": "An object that describes what fields should be repeated into views that are laid out as a `row` or `column`."
+            ],
+            "title": "TopLevel"
         },
         "Autosize": {
             "anyOf": [
@@ -4288,7 +5288,7 @@
                     }
                 },
                 {
-                    "$ref": "#/definitions/CategoryVGScheme"
+                    "$ref": "#/definitions/VGScheme"
                 }
             ],
             "title": "Category",
@@ -4303,7 +5303,10 @@
                     }
                 },
                 {
-                    "$ref": "#/definitions/RangeConfigValueVGScheme"
+                    "$ref": "#/definitions/VGScheme"
+                },
+                {
+                    "$ref": "#/definitions/RangeConfigValueClass"
                 }
             ],
             "title": "RangeConfigValue"
@@ -4332,6 +5335,56 @@
             "title": "Translate",
             "description": "When truthy, allows a user to interactively move an interval selection\nback-and-forth. Can be `true`, `false` (to disable panning), or a\n[Vega event stream definition](https://vega.github.io/vega/docs/event-streams/)\nwhich must include a start and end event to trigger continuous panning.\n\n__Default value:__ `true`, which corresponds to\n`[mousedown, window:mouseup] > window:mousemove!` which corresponds to\nclicks and dragging within an interval selection to reposition it.\nWhen truthy, allows a user to interactively resize an interval selection.\nCan be `true`, `false` (to disable zooming), or a [Vega event stream\ndefinition](https://vega.github.io/vega/docs/event-streams/). Currently,\nonly `wheel` events are supported.\n\n\n__Default value:__ `true`, which corresponds to `wheel!`.\nControls whether data values should be toggled or only ever inserted into\nmulti selections. Can be `true`, `false` (for insertion only), or a\n[Vega expression](https://vega.github.io/vega/docs/expressions/).\n\n__Default value:__ `true`, which corresponds to `event.shiftKey` (i.e.,\ndata values are toggled when a user interacts with the shift-key pressed).\n\nSee the [toggle transform](toggle.html) documentation for more information."
         },
+        "VGBinding": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/VGCheckboxBinding"
+                },
+                {
+                    "$ref": "#/definitions/VGRadioBinding"
+                },
+                {
+                    "$ref": "#/definitions/VGSelectBinding"
+                },
+                {
+                    "$ref": "#/definitions/VGRangeBinding"
+                },
+                {
+                    "$ref": "#/definitions/VGGenericBinding"
+                }
+            ],
+            "title": "VGBinding"
+        },
+        "Data": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/URLData"
+                },
+                {
+                    "$ref": "#/definitions/InlineData"
+                },
+                {
+                    "$ref": "#/definitions/NamedData"
+                }
+            ],
+            "title": "Data",
+            "description": "An object describing the data source\nSecondary data source to lookup in."
+        },
+        "DataFormat": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/CSVDataFormat"
+                },
+                {
+                    "$ref": "#/definitions/JSONDataFormat"
+                },
+                {
+                    "$ref": "#/definitions/TopoDataFormat"
+                }
+            ],
+            "title": "DataFormat",
+            "description": "An object that specifies the format for parsing the data file.\nAn object that specifies the format for parsing the data values.\nAn object that specifies the format for parsing the data."
+        },
         "ParseUnion": {
             "anyOf": [
                 {
@@ -4381,6 +5434,18 @@
             ],
             "title": "ValuesValue"
         },
+        "Color": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/MarkPropFieldDefWithCondition"
+                },
+                {
+                    "$ref": "#/definitions/MarkPropValueDefWithCondition"
+                }
+            ],
+            "title": "Color",
+            "description": "Color of the marks – either fill or stroke color based on mark type.\nBy default, `color` represents fill color for `\"area\"`, `\"bar\"`, `\"tick\"`,\n`\"text\"`, `\"circle\"`, and `\"square\"` / stroke color for `\"line\"` and `\"point\"`.\n\n__Default value:__ If undefined, the default color depends on [mark config](config.html#mark)'s `color` property.\n\n_Note:_ See the scale documentation for more information about customizing [color scheme](scale.html#scheme).\nOpacity of the marks – either can be a value or a range.\n\n__Default value:__ If undefined, the default opacity depends on [mark config](config.html#mark)'s `opacity` property.\nFor `point` marks the supported values are\n`\"circle\"` (default), `\"square\"`, `\"cross\"`, `\"diamond\"`, `\"triangle-up\"`,\nor `\"triangle-down\"`, or else a custom SVG path string.\nFor `geoshape` marks it should be a field definition of the geojson data\n\n__Default value:__ If undefined, the default shape depends on [mark config](config.html#point-config)'s `shape` property.\nSize of the mark.\n- For `\"point\"`, `\"square\"` and `\"circle\"`, – the symbol size, or pixel area of the mark.\n- For `\"bar\"` and `\"tick\"` – the bar and tick's size.\n- For `\"text\"` – the text's font size.\n- Size is currently unsupported for `\"line\"`, `\"area\"`, and `\"rect\"`."
+        },
         "Bin": {
             "anyOf": [
                 {
@@ -4392,7 +5457,7 @@
             ],
             "title": "Bin"
         },
-        "ColorCondition": {
+        "ConditionUnion": {
             "anyOf": [
                 {
                     "type": "array",
@@ -4401,27 +5466,47 @@
                     }
                 },
                 {
-                    "$ref": "#/definitions/ConditionalPredicateMarkPropFieldDefClass"
+                    "$ref": "#/definitions/ConditionalPredicateValueDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionValueDef"
                 }
             ],
-            "title": "ColorCondition"
+            "title": "ConditionUnion"
         },
-        "SelectionOperand": {
+        "ConditionalValueDef": {
             "anyOf": [
                 {
-                    "$ref": "#/definitions/Selection"
+                    "$ref": "#/definitions/ConditionalPredicateValueDef"
                 },
                 {
-                    "type": "string"
+                    "$ref": "#/definitions/ConditionalSelectionValueDef"
                 }
             ],
-            "title": "SelectionOperand",
-            "description": "Filter using a selection name.\nA [selection name](selection.html), or a series of [composed selections](selection.html#compose)."
+            "title": "ConditionalValueDef"
         },
         "LogicalOperandPredicate": {
             "anyOf": [
                 {
-                    "$ref": "#/definitions/Predicate"
+                    "$ref": "#/definitions/LogicalNotPredicate"
+                },
+                {
+                    "$ref": "#/definitions/LogicalAndPredicate"
+                },
+                {
+                    "$ref": "#/definitions/LogicalOrPredicate"
+                },
+                {
+                    "$ref": "#/definitions/FieldEqualPredicate"
+                },
+                {
+                    "$ref": "#/definitions/FieldRangePredicate"
+                },
+                {
+                    "$ref": "#/definitions/FieldOneOfPredicate"
+                },
+                {
+                    "$ref": "#/definitions/SelectionPredicate"
                 },
                 {
                     "type": "string"
@@ -4472,7 +5557,25 @@
             ],
             "title": "RangeElement"
         },
-        "ConditionalValueDefValue": {
+        "SelectionOperand": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/SelectionNot"
+                },
+                {
+                    "$ref": "#/definitions/SelectionAnd"
+                },
+                {
+                    "$ref": "#/definitions/SelectionOr"
+                },
+                {
+                    "type": "string"
+                }
+            ],
+            "title": "SelectionOperand",
+            "description": "Filter using a selection name.\nA [selection name](selection.html), or a series of [composed selections](selection.html#compose)."
+        },
+        "ConditionValue": {
             "anyOf": [
                 {
                     "type": "boolean"
@@ -4484,7 +5587,7 @@
                     "type": "string"
                 }
             ],
-            "title": "ConditionalValueDefValue",
+            "title": "ConditionValue",
             "description": "A constant value in visual domain (e.g., `\"red\"` / \"#0099ff\" for color, values between `0` to `1` for opacity).\nA constant value in visual domain."
         },
         "Field": {
@@ -4522,7 +5625,10 @@
                     "description": "A set of values that the `field`'s value should be a member of,\nfor a data item included in the filtered data."
                 },
                 {
-                    "$ref": "#/definitions/DomainClass"
+                    "$ref": "#/definitions/PurpleSelectionDomain"
+                },
+                {
+                    "$ref": "#/definitions/FluffySelectionDomain"
                 },
                 {
                     "$ref": "#/definitions/Domain"
@@ -4612,7 +5718,7 @@
                     "$ref": "#/definitions/SortField"
                 },
                 {
-                    "$ref": "#/definitions/SortEnum"
+                    "$ref": "#/definitions/SortOrderEnum"
                 },
                 {
                     "type": "null"
@@ -4620,6 +5726,30 @@
             ],
             "title": "SortUnion"
         },
+        "ColorCondition": {
+            "anyOf": [
+                {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/ConditionalValueDef"
+                    }
+                },
+                {
+                    "$ref": "#/definitions/ConditionalPredicateMarkPropFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionMarkPropFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalPredicateValueDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionValueDef"
+                }
+            ],
+            "title": "ColorCondition",
+            "description": "A field definition or one or more value definition(s) with a selection predicate."
+        },
         "Detail": {
             "anyOf": [
                 {
@@ -4634,6 +5764,18 @@
             ],
             "title": "Detail"
         },
+        "Href": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/FieldDefWithCondition"
+                },
+                {
+                    "$ref": "#/definitions/ValueDefWithCondition"
+                }
+            ],
+            "title": "Href",
+            "description": "A URL to load upon mouse click."
+        },
         "HrefCondition": {
             "anyOf": [
                 {
@@ -4643,10 +5785,20 @@
                     }
                 },
                 {
-                    "$ref": "#/definitions/ConditionalPredicateFieldDefClass"
+                    "$ref": "#/definitions/ConditionalPredicateFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalPredicateValueDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionValueDef"
                 }
             ],
-            "title": "HrefCondition"
+            "title": "HrefCondition",
+            "description": "A field definition or one or more value definition(s) with a selection predicate."
         },
         "Order": {
             "anyOf": [
@@ -4662,6 +5814,18 @@
             ],
             "title": "Order"
         },
+        "Text": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/TextFieldDefWithCondition"
+                },
+                {
+                    "$ref": "#/definitions/TextValueDefWithCondition"
+                }
+            ],
+            "title": "Text",
+            "description": "Text of the `text` mark.\nThe tooltip text to show upon mouse hover."
+        },
         "TextCondition": {
             "anyOf": [
                 {
@@ -4671,10 +5835,32 @@
                     }
                 },
                 {
-                    "$ref": "#/definitions/ConditionalPredicateTextFieldDefClass"
+                    "$ref": "#/definitions/ConditionalPredicateTextFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionTextFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalPredicateValueDef"
+                },
+                {
+                    "$ref": "#/definitions/ConditionalSelectionValueDef"
+                }
+            ],
+            "title": "TextCondition",
+            "description": "A field definition or one or more value definition(s) with a selection predicate."
+        },
+        "X": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/PositionFieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ValueDef"
                 }
             ],
-            "title": "TextCondition"
+            "title": "X",
+            "description": "X coordinates of the marks, or width of horizontal `\"bar\"` and `\"area\"`.\nY coordinates of the marks, or height of vertical `\"bar\"` and `\"area\"`."
         },
         "AxisValue": {
             "anyOf": [
@@ -4687,6 +5873,18 @@
             ],
             "title": "AxisValue"
         },
+        "X2": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/FieldDef"
+                },
+                {
+                    "$ref": "#/definitions/ValueDef"
+                }
+            ],
+            "title": "X2",
+            "description": "X2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`.\nY2 coordinates for ranged  `\"area\"`, `\"bar\"`, `\"rect\"`, and  `\"rule\"`."
+        },
         "AnyMark": {
             "anyOf": [
                 {
@@ -4712,22 +5910,21 @@
                 }
             ],
             "title": "Style",
-            "description": "A string or array of strings indicating the name of custom styles to apply to the mark. A style is a named collection of mark property defaults defined within the [style configuration](mark.html#style-config). If style is an array, later styles will override earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within the `encoding` will override a style default.\n\n__Default value:__ The mark's name.  For example, a bar mark will have style `\"bar\"` by default.\n__Note:__ Any specified style will augment the default style. For example, a bar mark with `\"style\": \"foo\"` will receive from `config.style.bar` and `config.style.foo` (the specified style `\"foo\"` has higher precedence).\nA [mark style property](config.html#style) to apply to the title text mark.\n\n__Default value:__ `\"group-title\"`."
+            "description": "A string or array of strings indicating the name of custom styles to apply to the mark. A style is a named collection of mark property defaults defined within the [style configuration](mark.html#style-config). If style is an array, later styles will override earlier styles. Any [mark properties](encoding.html#mark-prop) explicitly defined within the `encoding` will override a style default.\n\n__Default value:__ The mark's name.  For example, a bar mark will have style `\"bar\"` by default.\n__Note:__ Any specified style will augment the default style. For example, a bar mark with `\"style\": \"foo\"` will receive from `config.style.bar` and `config.style.foo` (the specified style `\"foo\"` has higher precedence).\nA [mark style property](config.html#style) to apply to the title text mark.\n\n__Default value:__ `\"group-title\"`.\nThe field or fields for storing the computed formula value.\nIf `from.fields` is specified, the transform will use the same names for `as`.\nIf `from.fields` is not specified, `as` has to be a string and we put the whole object into the data under the specified name."
         },
-        "BindUnion": {
+        "SelectionDef": {
             "anyOf": [
                 {
-                    "$ref": "#/definitions/BindEnum"
+                    "$ref": "#/definitions/SingleSelection"
                 },
                 {
-                    "type": "object",
-                    "additionalProperties": {
-                        "$ref": "#/definitions/VGBinding"
-                    },
-                    "description": "Establish a two-way binding between a single selection and input elements\n(also known as dynamic query widgets). A binding takes the form of\nVega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind)\nor can be a mapping between projected field/encodings and binding definitions.\n\nSee the [bind transform](bind.html) documentation for more information."
+                    "$ref": "#/definitions/MultiSelection"
+                },
+                {
+                    "$ref": "#/definitions/IntervalSelection"
                 }
             ],
-            "title": "BindUnion"
+            "title": "SelectionDef"
         },
         "Title": {
             "anyOf": [
@@ -4740,6 +5937,63 @@
             ],
             "title": "Title"
         },
+        "Transform": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/FilterTransform"
+                },
+                {
+                    "$ref": "#/definitions/CalculateTransform"
+                },
+                {
+                    "$ref": "#/definitions/LookupTransform"
+                },
+                {
+                    "$ref": "#/definitions/BinTransform"
+                },
+                {
+                    "$ref": "#/definitions/TimeUnitTransform"
+                },
+                {
+                    "$ref": "#/definitions/AggregateTransform"
+                }
+            ],
+            "title": "Transform"
+        },
+        "SpecElement": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/LayerSpec"
+                },
+                {
+                    "$ref": "#/definitions/CompositeUnitSpecAlias"
+                }
+            ],
+            "title": "SpecElement"
+        },
+        "Spec": {
+            "anyOf": [
+                {
+                    "$ref": "#/definitions/CompositeUnitSpecAlias"
+                },
+                {
+                    "$ref": "#/definitions/LayerSpec"
+                },
+                {
+                    "$ref": "#/definitions/FacetSpec"
+                },
+                {
+                    "$ref": "#/definitions/RepeatSpec"
+                },
+                {
+                    "$ref": "#/definitions/VConcatSpec"
+                },
+                {
+                    "$ref": "#/definitions/HConcatSpec"
+                }
+            ],
+            "title": "Spec"
+        },
         "AutosizeType": {
             "type": "string",
             "enum": [
@@ -4908,6 +6162,14 @@
             "title": "VGProjectionType",
             "description": "The cartographic projection to use. This value is case-insensitive, for example `\"albers\"` and `\"Albers\"` indicate the same projection type. You can find all valid projection types [in the documentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\n\n__Default value:__ `mercator`"
         },
+        "Bind": {
+            "type": "string",
+            "enum": [
+                "scales"
+            ],
+            "title": "Bind",
+            "description": "Establishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
+        },
         "Empty": {
             "type": "string",
             "enum": [
@@ -4946,6 +6208,34 @@
             "title": "SelectionResolution",
             "description": "With layered and multi-view displays, a strategy that determines how\nselections' data queries are resolved when applied in a filter transform,\nconditional encoding rule, or scale domain."
         },
+        "PurpleInput": {
+            "type": "string",
+            "enum": [
+                "checkbox"
+            ],
+            "title": "PurpleInput"
+        },
+        "FluffyInput": {
+            "type": "string",
+            "enum": [
+                "radio"
+            ],
+            "title": "FluffyInput"
+        },
+        "TentacledInput": {
+            "type": "string",
+            "enum": [
+                "select"
+            ],
+            "title": "TentacledInput"
+        },
+        "StickyInput": {
+            "type": "string",
+            "enum": [
+                "range"
+            ],
+            "title": "StickyInput"
+        },
         "Anchor": {
             "type": "string",
             "enum": [
@@ -4974,15 +6264,29 @@
             ],
             "title": "ParseEnum"
         },
-        "DataFormatType": {
+        "PurpleType": {
             "type": "string",
             "enum": [
                 "csv",
-                "tsv",
-                "json",
+                "tsv"
+            ],
+            "title": "PurpleType",
+            "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
+        },
+        "FluffyType": {
+            "type": "string",
+            "enum": [
+                "json"
+            ],
+            "title": "FluffyType",
+            "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
+        },
+        "TentacledType": {
+            "type": "string",
+            "enum": [
                 "topojson"
             ],
-            "title": "DataFormatType",
+            "title": "TentacledType",
             "description": "Type of input data: `\"json\"`, `\"csv\"`, `\"tsv\"`.\nThe default format type is determined by the extension of the file URL.\nIf no extension is detected, `\"json\"` will be used by default."
         },
         "AggregateOp": {
@@ -5149,13 +6453,13 @@
             "title": "ScaleType",
             "description": "The type of scale.  Vega-Lite supports the following categories of scale types:\n\n1) [**Continuous Scales**](scale.html#continuous) -- mapping continuous domains to continuous output ranges ([`\"linear\"`](scale.html#linear), [`\"pow\"`](scale.html#pow), [`\"sqrt\"`](scale.html#sqrt), [`\"log\"`](scale.html#log), [`\"time\"`](scale.html#time), [`\"utc\"`](scale.html#utc), [`\"sequential\"`](scale.html#sequential)).\n\n2) [**Discrete Scales**](scale.html#discrete) -- mapping discrete domains to discrete ([`\"ordinal\"`](scale.html#ordinal)) or continuous ([`\"band\"`](scale.html#band) and [`\"point\"`](scale.html#point)) output ranges.\n\n3) [**Discretizing Scales**](scale.html#discretizing) -- mapping continuous domains to discrete output ranges ([`\"bin-linear\"`](scale.html#bin-linear) and [`\"bin-ordinal\"`](scale.html#bin-ordinal)).\n\n__Default value:__ please see the [scale type table](scale.html#type)."
         },
-        "SortEnum": {
+        "SortOrderEnum": {
             "type": "string",
             "enum": [
                 "ascending",
                 "descending"
             ],
-            "title": "SortEnum"
+            "title": "SortOrderEnum"
         },
         "Type": {
             "type": "string",
@@ -5199,30 +6503,34 @@
             "title": "Mark",
             "description": "All types of primitive marks.\nThe mark type.\nOne of `\"bar\"`, `\"circle\"`, `\"square\"`, `\"tick\"`, `\"line\"`,\n`\"area\"`, `\"point\"`, `\"geoshape\"`, `\"rule\"`, and `\"text\"`."
         },
-        "ResolveMode": {
+        "StickyType": {
             "type": "string",
             "enum": [
-                "independent",
-                "shared"
+                "single"
             ],
-            "title": "ResolveMode"
+            "title": "StickyType"
         },
-        "BindEnum": {
+        "IndigoType": {
             "type": "string",
             "enum": [
-                "scales"
+                "multi"
             ],
-            "title": "BindEnum",
-            "description": "Establishes a two-way binding between the interval selection and the scales\nused within the same view. This allows a user to interactively pan and\nzoom the view."
+            "title": "IndigoType"
         },
-        "SelectionDefType": {
+        "IndecentType": {
             "type": "string",
             "enum": [
-                "single",
-                "multi",
                 "interval"
             ],
-            "title": "SelectionDefType"
+            "title": "IndecentType"
+        },
+        "ResolveMode": {
+            "type": "string",
+            "enum": [
+                "independent",
+                "shared"
+            ],
+            "title": "ResolveMode"
         }
     }
 }
diff --git a/head/schema-swift/test/inputs/schema/one-of-objects.schema/default/quicktype.swift b/head/schema-swift/test/inputs/schema/one-of-objects.schema/default/quicktype.swift
new file mode 100644
index 0000000..90a7571
--- /dev/null
+++ b/head/schema-swift/test/inputs/schema/one-of-objects.schema/default/quicktype.swift
@@ -0,0 +1,142 @@
+// This file was generated from JSON Schema using quicktype, do not modify it directly.
+// To parse the JSON, add this file to your project and do:
+//
+//   let topLevel = try TopLevel(json)
+
+import Foundation
+
+// MARK: - TopLevel
+struct TopLevel: Codable {
+    let items: [Item]
+
+    enum CodingKeys: String, CodingKey {
+        case items = "items"
+    }
+}
+
+// MARK: TopLevel convenience initializers and mutators
+
+extension TopLevel {
+    init(data: Data) throws {
+        self = try newJSONDecoder().decode(TopLevel.self, from: data)
+    }
+
+    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
+        guard let data = json.data(using: encoding) else {
+            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
+        }
+        try self.init(data: data)
+    }
+
+    init(fromURL url: URL) throws {
+        try self.init(data: try Data(contentsOf: url))
+    }
+
+    func with(
+        items: [Item]? = nil
+    ) -> TopLevel {
+        return TopLevel(
+            items: items ?? self.items
+        )
+    }
+
+    func jsonData() throws -> Data {
+        return try newJSONEncoder().encode(self)
+    }
+
+    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
+        return String(data: try self.jsonData(), encoding: encoding)
+    }
+}
+
+// MARK: - Item
+struct Item: Codable {
+    let aa: String?
+    let bb: String?
+    let cc: String?
+    let dd: String?
+
+    enum CodingKeys: String, CodingKey {
+        case aa = "aa"
+        case bb = "bb"
+        case cc = "cc"
+        case dd = "dd"
+    }
+}
+
+// MARK: Item convenience initializers and mutators
+
+extension Item {
+    init(data: Data) throws {
+        self = try newJSONDecoder().decode(Item.self, from: data)
+    }
+
+    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
+        guard let data = json.data(using: encoding) else {
+            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
+        }
+        try self.init(data: data)
+    }
+
+    init(fromURL url: URL) throws {
+        try self.init(data: try Data(contentsOf: url))
+    }
+
+    func with(
+        aa: String?? = nil,
+        bb: String?? = nil,
+        cc: String?? = nil,
+        dd: String?? = nil
+    ) -> Item {
+        return Item(
+            aa: aa ?? self.aa,
+            bb: bb ?? self.bb,
+            cc: cc ?? self.cc,
+            dd: dd ?? self.dd
+        )
+    }
+
+    func jsonData() throws -> Data {
+        return try newJSONEncoder().encode(self)
+    }
+
+    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
+        return String(data: try self.jsonData(), encoding: encoding)
+    }
+}
+
+// MARK: - Helper functions for creating encoders and decoders
+
+func newJSONDecoder() -> JSONDecoder {
+    let decoder = JSONDecoder()
+    decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
+        let container = try decoder.singleValueContainer()
+        let dateStr = try container.decode(String.self)
+
+        let formatter = DateFormatter()
+        formatter.calendar = Calendar(identifier: .iso8601)
+        formatter.locale = Locale(identifier: "en_US_POSIX")
+        formatter.timeZone = TimeZone(secondsFromGMT: 0)
+        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
+        if let date = formatter.date(from: dateStr) {
+            return date
+        }
+        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
+        if let date = formatter.date(from: dateStr) {
+            return date
+        }
+        throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date"))
+    })
+    return decoder
+}
+
+func newJSONEncoder() -> JSONEncoder {
+    let encoder = JSONEncoder()
+    let formatter = DateFormatter()
+    formatter.calendar = Calendar(identifier: .iso8601)
+    formatter.locale = Locale(identifier: "en_US_POSIX")
+    formatter.timeZone = TimeZone(secondsFromGMT: 0)
+    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
+    encoder.dateEncodingStrategy = .formatted(formatter)
+    return encoder
+}
diff --git a/base/schema-typescript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.ts b/head/schema-typescript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.ts
index ead6805..6e1c2de 100644
--- a/base/schema-typescript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.ts
+++ b/head/schema-typescript/test/inputs/schema/nested-intersection-union.schema/default/TopLevel.ts
@@ -11,11 +11,21 @@ export interface TopLevel {
     input: Item[];
 }
 
-export interface Item {
-    content?: string;
-    id?:      string;
-    output?:  string;
-    summary?: string;
+export type Item = (Message & { "id"?: never; "output"?: never; "summary"?: never; }) | (FunctionOutput & { "content"?: never; "summary"?: never; }) | (ReasoningItem & { "content"?: never; "id"?: never; "output"?: never; });
+
+export interface Message {
+    content: string;
+    [property: string]: unknown;
+}
+
+export interface FunctionOutput {
+    id:     string;
+    output: string;
+    [property: string]: unknown;
+}
+
+export interface ReasoningItem {
+    summary: string;
     [property: string]: unknown;
 }
 
@@ -186,12 +196,16 @@ function r(name: string) {
 
 const typeMap: any = {
     "TopLevel": o([
-        { json: "input", js: "input", typ: a(r("Item")) },
+        { json: "input", js: "input", typ: a(u(r("Message"), r("FunctionOutput"), r("ReasoningItem"))) },
     ], false),
-    "Item": o([
-        { json: "content", js: "content", typ: u(undefined, "") },
-        { json: "id", js: "id", typ: u(undefined, "") },
-        { json: "output", js: "output", typ: u(undefined, "") },
-        { json: "summary", js: "summary", typ: u(undefined, "") },
+    "Message": o([
+        { json: "content", js: "content", typ: "" },
+    ], "any"),
+    "FunctionOutput": o([
+        { json: "id", js: "id", typ: "" },
+        { json: "output", js: "output", typ: "" },
+    ], "any"),
+    "ReasoningItem": o([
+        { json: "summary", js: "summary", typ: "" },
     ], "any"),
 };
diff --git a/base/schema-typescript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.ts b/head/schema-typescript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.ts
index b5c10df..4a5881d 100644
--- a/base/schema-typescript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.ts
+++ b/head/schema-typescript/test/inputs/schema/nullable-optional-one-of.schema/default/TopLevel.ts
@@ -7,23 +7,33 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
-export interface TopLevel {
+export type TopLevel = One | Two;
+
+export interface One {
+    b:    null | string;
+    kind: PurpleKind;
+    [property: string]: unknown;
+}
+
+export type PurpleKind = "one";
+
+export interface Two {
     b?:   null | string;
-    kind: Kind;
+    kind: FluffyKind;
     [property: string]: unknown;
 }
 
-export type Kind = "one" | "two";
+export type FluffyKind = "two";
 
 // Converts JSON strings to/from your types
 // and asserts the results of JSON.parse at runtime
 export class Convert {
     public static toTopLevel(json: string): TopLevel {
-        return cast(JSON.parse(json), r("TopLevel"));
+        return cast(JSON.parse(json), u(r("One"), r("Two")));
     }
 
     public static topLevelToJson(value: TopLevel): string {
-        return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+        return JSON.stringify(uncast(value, u(r("One"), r("Two"))), null, 2);
     }
 }
 
@@ -181,12 +191,18 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
+    "One": o([
+        { json: "b", js: "b", typ: u(null, "") },
+        { json: "kind", js: "kind", typ: r("PurpleKind") },
+    ], "any"),
+    "Two": o([
         { json: "b", js: "b", typ: u(undefined, u(null, "")) },
-        { json: "kind", js: "kind", typ: r("Kind") },
+        { json: "kind", js: "kind", typ: r("FluffyKind") },
     ], "any"),
-    "Kind": [
+    "PurpleKind": [
         "one",
+    ],
+    "FluffyKind": [
         "two",
     ],
 };
diff --git a/head/schema-typescript/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts b/head/schema-typescript/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts
new file mode 100644
index 0000000..2877401
--- /dev/null
+++ b/head/schema-typescript/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts
@@ -0,0 +1,203 @@
+// To parse this data:
+//
+//   import { Convert, TopLevel } from "./TopLevel";
+//
+//   const topLevel = Convert.toTopLevel(json);
+//
+// These functions will throw an error if the JSON doesn't
+// match the expected interface, even if the JSON is valid.
+
+export interface TopLevel {
+    items: ItemElement[];
+}
+
+export type ItemElement = (PurpleItem & { "cc"?: never; "dd"?: never; }) | (FluffyItem & { "aa"?: never; "bb"?: never; });
+
+export interface PurpleItem {
+    aa?: string;
+    bb?: string;
+}
+
+export interface FluffyItem {
+    cc?: string;
+    dd?: string;
+}
+
+// Converts JSON strings to/from your types
+// and asserts the results of JSON.parse at runtime
+export class Convert {
+    public static toTopLevel(json: string): TopLevel {
+        return cast(JSON.parse(json), r("TopLevel"));
+    }
+
+    public static topLevelToJson(value: TopLevel): string {
+        return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+    }
+}
+
+function invalidValue(typ: any, val: any, key: any, parent: any = ''): never {
+    const prettyTyp = prettyTypeName(typ);
+    const parentText = parent ? ` on ${parent}` : '';
+    const keyText = key ? ` for key "${key}"` : '';
+    throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);
+}
+
+function prettyTypeName(typ: any): string {
+    if (Array.isArray(typ)) {
+        if (typ.length === 2 && typ[0] === undefined) {
+            return `an optional ${prettyTypeName(typ[1])}`;
+        } else {
+            return `one of [${typ.map(a => { return prettyTypeName(a); }).join(", ")}]`;
+        }
+    } else if (typeof typ === "object" && typ.literal !== undefined) {
+        return typ.literal;
+    } else {
+        return typeof typ;
+    }
+}
+
+function jsonToJSProps(typ: any): any {
+    if (typ.jsonToJS === undefined) {
+        const map: any = {};
+        typ.props.forEach((p: any) => map[p.json] = { key: p.js, typ: p.typ });
+        typ.jsonToJS = map;
+    }
+    return typ.jsonToJS;
+}
+
+function jsToJSONProps(typ: any): any {
+    if (typ.jsToJSON === undefined) {
+        const map: any = {};
+        typ.props.forEach((p: any) => map[p.js] = { key: p.json, typ: p.typ });
+        typ.jsToJSON = map;
+    }
+    return typ.jsToJSON;
+}
+
+function transform(val: any, typ: any, getProps: any, key: any = '', parent: any = ''): any {
+    function transformPrimitive(typ: string, val: any): any {
+        if (typeof typ === typeof val) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+
+    function transformUnion(typs: any[], val: any): any {
+        // val must validate against one typ in typs
+        const l = typs.length;
+        for (let i = 0; i < l; i++) {
+            const typ = typs[i];
+            try {
+                return transform(val, typ, getProps);
+            } catch (_) {}
+        }
+        return invalidValue(typs, val, key, parent);
+    }
+
+    function transformEnum(cases: string[], val: any): any {
+        if (cases.indexOf(val) !== -1) return val;
+        return invalidValue(cases.map(a => { return l(a); }), val, key, parent);
+    }
+
+    function transformArray(typ: any, val: any): any {
+        // val must be an array with no invalid elements
+        if (!Array.isArray(val)) return invalidValue(l("array"), val, key, parent);
+        return val.map(el => transform(el, typ, getProps));
+    }
+
+    function transformDate(val: any): any {
+        if (val === null) {
+            return null;
+        }
+        const d = new Date(val);
+        if (isNaN(d.valueOf())) {
+            return invalidValue(l("Date"), val, key, parent);
+        }
+        return d;
+    }
+
+    function transformObject(props: { [k: string]: any }, additional: any, val: any): any {
+        if (val === null || typeof val !== "object" || Array.isArray(val)) {
+            return invalidValue(l(ref || "object"), val, key, parent);
+        }
+        const result: any = {};
+        Object.getOwnPropertyNames(props).forEach(key => {
+            const prop = props[key];
+            const v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined;
+            result[prop.key] = transform(v, prop.typ, getProps, key, ref);
+        });
+        Object.getOwnPropertyNames(val).forEach(key => {
+            if (!Object.prototype.hasOwnProperty.call(props, key)) {
+                result[key] = transform(val[key], additional, getProps, key, ref);
+            }
+        });
+        return result;
+    }
+
+    if (typ === "any") return val;
+    if (typ === null) {
+        if (val === null) return val;
+        return invalidValue(typ, val, key, parent);
+    }
+    if (typ === false) return invalidValue(typ, val, key, parent);
+    let ref: any = undefined;
+    while (typeof typ === "object" && typ.ref !== undefined) {
+        ref = typ.ref;
+        typ = typeMap[typ.ref];
+    }
+    if (Array.isArray(typ)) return transformEnum(typ, val);
+    if (typeof typ === "object") {
+        return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val)
+            : typ.hasOwnProperty("arrayItems")    ? transformArray(typ.arrayItems, val)
+            : typ.hasOwnProperty("props")         ? transformObject(getProps(typ), typ.additional, val)
+            : invalidValue(typ, val, key, parent);
+    }
+    // Numbers can be parsed by Date but shouldn't be.
+    if (typ === Date && typeof val !== "number") return transformDate(val);
+    return transformPrimitive(typ, val);
+}
+
+function cast<T>(val: any, typ: any): T {
+    return transform(val, typ, jsonToJSProps);
+}
+
+function uncast<T>(val: T, typ: any): any {
+    return transform(val, typ, jsToJSONProps);
+}
+
+function l(typ: any) {
+    return { literal: typ };
+}
+
+function a(typ: any) {
+    return { arrayItems: typ };
+}
+
+function u(...typs: any[]) {
+    return { unionMembers: typs };
+}
+
+function o(props: any[], additional: any) {
+    return { props, additional };
+}
+
+function m(additional: any) {
+    const props: any[] = [];
+    return { props, additional };
+}
+
+function r(name: string) {
+    return { ref: name };
+}
+
+const typeMap: any = {
+    "TopLevel": o([
+        { json: "items", js: "items", typ: a(u(r("PurpleItem"), r("FluffyItem"))) },
+    ], false),
+    "PurpleItem": o([
+        { json: "aa", js: "aa", typ: u(undefined, "") },
+        { json: "bb", js: "bb", typ: u(undefined, "") },
+    ], false),
+    "FluffyItem": o([
+        { json: "cc", js: "cc", typ: u(undefined, "") },
+        { json: "dd", js: "dd", typ: u(undefined, "") },
+    ], false),
+};
diff --git a/base/schema-typescript/test/inputs/schema/postman-collection.schema/default/TopLevel.ts b/head/schema-typescript/test/inputs/schema/postman-collection.schema/default/TopLevel.ts
index 6a5d984..fec3b03 100644
--- a/base/schema-typescript/test/inputs/schema/postman-collection.schema/default/TopLevel.ts
+++ b/head/schema-typescript/test/inputs/schema/postman-collection.schema/default/TopLevel.ts
@@ -7,11 +7,17 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
+export interface Group {
+    item?: TopLevel[];
+    [property: string]: unknown;
+}
+
 /**
  * Postman collection
  */
-export interface TopLevel {
-    item?:     TopLevel[];
+export type TopLevel = (Group & { "name"?: never; "response"?: never; }) | (Item & { "item"?: never; });
+
+export interface Item {
     name?:     string;
     response?: Response[];
     [property: string]: unknown;
@@ -26,11 +32,11 @@ export interface Response {
 // and asserts the results of JSON.parse at runtime
 export class Convert {
     public static toTopLevel(json: string): TopLevel {
-        return cast(JSON.parse(json), r("TopLevel"));
+        return cast(JSON.parse(json), u(r("Group"), r("Item")));
     }
 
     public static topLevelToJson(value: TopLevel): string {
-        return JSON.stringify(uncast(value, r("TopLevel")), null, 2);
+        return JSON.stringify(uncast(value, u(r("Group"), r("Item"))), null, 2);
     }
 }
 
@@ -188,8 +194,10 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
-        { json: "item", js: "item", typ: u(undefined, a(r("TopLevel"))) },
+    "Group": o([
+        { json: "item", js: "item", typ: u(undefined, a(u(r("Group"), r("Item")))) },
+    ], "any"),
+    "Item": o([
         { json: "name", js: "name", typ: u(undefined, "") },
         { json: "response", js: "response", typ: u(undefined, a(r("Response"))) },
     ], "any"),
diff --git a/base/schema-typescript/test/inputs/schema/union.schema/default/TopLevel.ts b/head/schema-typescript/test/inputs/schema/union.schema/default/TopLevel.ts
index 35fee9c..65eeff5 100644
--- a/base/schema-typescript/test/inputs/schema/union.schema/default/TopLevel.ts
+++ b/head/schema-typescript/test/inputs/schema/union.schema/default/TopLevel.ts
@@ -7,10 +7,17 @@
 // These functions will throw an error if the JSON doesn't
 // match the expected interface, even if the JSON is valid.
 
-export interface TopLevel {
-    one?:   number;
-    two:    boolean;
-    three?: number;
+export type TopLevel = (PurpleTopLevel & { "three"?: never; }) | (FluffyTopLevel & { "one"?: never; });
+
+export interface PurpleTopLevel {
+    one: number;
+    two: boolean;
+    [property: string]: unknown;
+}
+
+export interface FluffyTopLevel {
+    three: number;
+    two:   boolean;
     [property: string]: unknown;
 }
 
@@ -18,11 +25,11 @@ export interface TopLevel {
 // and asserts the results of JSON.parse at runtime
 export class Convert {
     public static toTopLevel(json: string): TopLevel[] {
-        return cast(JSON.parse(json), a(r("TopLevel")));
+        return cast(JSON.parse(json), a(u(r("PurpleTopLevel"), r("FluffyTopLevel"))));
     }
 
     public static topLevelToJson(value: TopLevel[]): string {
-        return JSON.stringify(uncast(value, a(r("TopLevel"))), null, 2);
+        return JSON.stringify(uncast(value, a(u(r("PurpleTopLevel"), r("FluffyTopLevel")))), null, 2);
     }
 }
 
@@ -180,9 +187,12 @@ function r(name: string) {
 }
 
 const typeMap: any = {
-    "TopLevel": o([
-        { json: "one", js: "one", typ: u(undefined, 0) },
+    "PurpleTopLevel": o([
+        { json: "one", js: "one", typ: 0 },
+        { json: "two", js: "two", typ: true },
+    ], "any"),
+    "FluffyTopLevel": o([
+        { json: "three", js: "three", typ: 3.14 },
         { json: "two", js: "two", typ: true },
-        { json: "three", js: "three", typ: u(undefined, 3.14) },
     ], "any"),
 };
diff --git a/head/schema-typescript-zod/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts b/head/schema-typescript-zod/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts
new file mode 100644
index 0000000..87121cc
--- /dev/null
+++ b/head/schema-typescript-zod/test/inputs/schema/one-of-objects.schema/default/TopLevel.ts
@@ -0,0 +1,15 @@
+import * as z from "zod";
+
+
+export const ItemSchema = z.object({
+    "aa": z.string().optional(),
+    "bb": z.string().optional(),
+    "cc": z.string().optional(),
+    "dd": z.string().optional(),
+});
+export type Item = z.infer<typeof ItemSchema>;
+
+export const TopLevelSchema = z.object({
+    "items": z.array(ItemSchema),
+});
+export type TopLevel = z.infer<typeof TopLevelSchema>;
