diff --git a/docs/specs/helpers.md b/docs/specs/helpers.md
index 2ec6092..53974f7 100644
--- a/docs/specs/helpers.md
+++ b/docs/specs/helpers.md
@@ -57,6 +57,47 @@ The anchor point is highlighted with an orange dot.
{schema_object:helpers/marker}
+
Slots
+
+Slots are a way to define a property value once and use the value in multiple
+properties. Slot definitions are in a dictionary, the slot definition key is the
+key that is used to match all properties with an `sid` field to the same key for
+replacement.
+
+Slot
+
+{schema_string:helpers/slot/description}
+
+{schema_object:helpers/slot}
+
+Slotabble Object
+
+{schema_string:helpers/slottable-object/description}
+
+{schema_object:helpers/slottable-object}
+
+Slotabble Property
+
+{schema_string:helpers/slottable-property/description}
+
+{schema_object:helpers/slottable-property}
+
+
+
+ lottie.slots
+
+
+
Mask
{schema_string:helpers/mask/description}
diff --git a/docs/static/examples/slots.json b/docs/static/examples/slots.json
new file mode 100644
index 0000000..006ae9a
--- /dev/null
+++ b/docs/static/examples/slots.json
@@ -0,0 +1,260 @@
+{
+ "v": "5.12.2",
+ "fr": 29.9700012207031,
+ "ip": 0,
+ "op": 900.000036657751,
+ "w": 512,
+ "h": 512,
+ "nm": "SlotDemo",
+ "ddd": 0,
+ "assets": [],
+ "layers": [
+ {
+ "ddd": 0,
+ "ind": 1,
+ "ty": 4,
+ "nm": "Shape Layer 1",
+ "sr": 1,
+ "ks": {
+ "o": { "a": 0, "k": 100, "ix": 11 },
+ "r": { "a": 0, "k": 0, "ix": 10 },
+ "p": { "a": 0, "k": [256, 256, 0], "ix": 2, "l": 2 },
+ "a": { "a": 0, "k": [0, 0, 0], "ix": 1, "l": 2 },
+ "s": { "a": 0, "k": [100, 100, 100], "ix": 6, "l": 2 }
+ },
+ "ao": 0,
+ "shapes": [
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "ty": "sr",
+ "sy": 2,
+ "d": 1,
+ "pt": { "a": 0, "k": 3, "ix": 3 },
+ "p": { "a": 0, "k": [0, 0], "ix": 4 },
+ "r": { "a": 0, "k": 0, "ix": 5 },
+ "or": { "a": 0, "k": 100, "ix": 7 },
+ "os": { "a": 0, "k": 0, "ix": 9 },
+ "ix": 1,
+ "nm": "Polystar Path 1",
+ "mn": "ADBE Vector Shape - Star",
+ "hd": false
+ },
+ {
+ "ty": "st",
+ "c": {
+ "a": 0,
+ "k": [0.271324008119, 0.323676015816, 0.880510995902, 1],
+ "ix": 3
+ },
+ "o": { "a": 0, "k": 100, "ix": 4 },
+ "w": { "a": 0, "k": 6, "ix": 5 },
+ "lc": 1,
+ "lj": 1,
+ "ml": 4,
+ "bm": 0,
+ "nm": "Stroke 1",
+ "mn": "ADBE Vector Graphic - Stroke",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": { "a": 0, "k": [-128, 128], "ix": 2 },
+ "a": { "a": 0, "k": [0, 0], "ix": 1 },
+ "s": { "a": 0, "k": [100, 100], "ix": 3, "sid": "scale" },
+ "r": { "a": 0, "k": 0, "ix": 6, "sid": "rotation" },
+ "o": { "a": 0, "k": 100, "ix": 7, "sid": "opacity"},
+ "sk": { "a": 0, "k": 0, "ix": 4 },
+ "sa": { "a": 0, "k": 0, "ix": 5 },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Polystar 2",
+ "np": 3,
+ "cix": 2,
+ "bm": 0,
+ "ix": 1,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ },
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "d": 1,
+ "ty": "el",
+ "s": { "a": 0, "k": [149.971, 150], "ix": 2 },
+ "p": { "a": 0, "k": [0, 0], "ix": 3 },
+ "nm": "Ellipse Path 1",
+ "mn": "ADBE Vector Shape - Ellipse",
+ "hd": false
+ },
+ {
+ "ty": "st",
+ "c": {
+ "a": 0,
+ "k": [0.271324008119, 0.323676015816, 0.880510995902, 1],
+ "ix": 3
+ },
+ "o": { "a": 0, "k": 100, "ix": 4 },
+ "w": { "a": 0, "k": 6, "ix": 5 },
+ "lc": 1,
+ "lj": 1,
+ "ml": 4,
+ "bm": 0,
+ "nm": "Stroke 1",
+ "mn": "ADBE Vector Graphic - Stroke",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": { "a": 0, "k": [128, -128], "ix": 2 },
+ "a": { "a": 0, "k": [0, 0], "ix": 1 },
+ "s": { "a": 0, "k": [100, 100], "ix": 3, "sid": "scale" },
+ "r": { "a": 0, "k": 0, "ix": 6, "sid": "rotation" },
+ "o": { "a": 0, "k": 100, "ix": 7, "sid": "opacity"},
+ "sk": { "a": 0, "k": 0, "ix": 4 },
+ "sa": { "a": 0, "k": 0, "ix": 5 },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Ellipse 1",
+ "np": 3,
+ "cix": 2,
+ "bm": 0,
+ "ix": 2,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ },
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "ty": "sr",
+ "sy": 1,
+ "d": 1,
+ "pt": { "a": 0, "k": 5, "ix": 3 },
+ "p": { "a": 0, "k": [0, 0], "ix": 4 },
+ "r": { "a": 0, "k": 0, "ix": 5 },
+ "ir": { "a": 0, "k": 50, "ix": 6 },
+ "is": { "a": 0, "k": 0, "ix": 8 },
+ "or": { "a": 0, "k": 100, "ix": 7 },
+ "os": { "a": 0, "k": 0, "ix": 9 },
+ "ix": 1,
+ "nm": "Polystar Path 1",
+ "mn": "ADBE Vector Shape - Star",
+ "hd": false
+ },
+ {
+ "ty": "fl",
+ "c": {
+ "a": 0,
+ "k": [0.271324008119, 0.323676015816, 0.880510995902, 1],
+ "ix": 4
+ },
+ "o": { "a": 0, "k": 100, "ix": 5 },
+ "r": 1,
+ "bm": 0,
+ "nm": "Fill 1",
+ "mn": "ADBE Vector Graphic - Fill",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": { "a": 0, "k": [128, 128], "ix": 2 },
+ "a": { "a": 0, "k": [0, 0], "ix": 1 },
+ "s": { "a": 0, "k": [100, 100], "ix": 3, "sid": "scale" },
+ "r": { "a": 0, "k": 0, "ix": 6, "sid": "rotation" },
+ "o": { "a": 0, "k": 100, "ix": 7, "sid": "opacity"},
+ "sk": { "a": 0, "k": 0, "ix": 4 },
+ "sa": { "a": 0, "k": 0, "ix": 5 },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Polystar 1",
+ "np": 3,
+ "cix": 2,
+ "bm": 0,
+ "ix": 3,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ },
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "ty": "rc",
+ "d": 1,
+ "s": { "a": 0, "k": [150, 150], "ix": 2 },
+ "p": { "a": 0, "k": [0, 0], "ix": 3 },
+ "r": { "a": 0, "k": 0, "ix": 4 },
+ "nm": "Rectangle Path 1",
+ "mn": "ADBE Vector Shape - Rect",
+ "hd": false
+ },
+ {
+ "ty": "fl",
+ "c": {
+ "a": 0,
+ "k": [0.271324008119, 0.323676015816, 0.880510995902, 1],
+ "ix": 4
+ },
+ "o": { "a": 0, "k": 100, "ix": 5 },
+ "r": 1,
+ "bm": 0,
+ "nm": "Fill 1",
+ "mn": "ADBE Vector Graphic - Fill",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": { "a": 0, "k": [-128, -128], "ix": 2 },
+ "a": { "a": 0, "k": [0, 0], "ix": 1 },
+ "s": { "a": 0, "k": [100, 100], "ix": 3, "sid": "scale" },
+ "r": { "a": 0, "k": 0, "ix": 6, "sid": "rotation" },
+ "o": { "a": 0, "k": 100, "ix": 7, "sid": "opacity"},
+ "sk": { "a": 0, "k": 0, "ix": 4 },
+ "sa": { "a": 0, "k": 0, "ix": 5 },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Rectangle 1",
+ "np": 3,
+ "cix": 2,
+ "bm": 0,
+ "ix": 4,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ }
+ ],
+ "ip": 0,
+ "op": 900.000036657751,
+ "st": 0,
+ "ct": 1,
+ "bm": 0
+ }
+ ],
+ "markers": [],
+ "props": {},
+ "slots": {
+ "rotation": {
+ "p": {
+ "a": 0,
+ "k": 0
+ }
+ },
+ "opacity": {
+ "p": {
+ "a": 0,
+ "k": 100
+ }
+ },
+ "scale": {
+ "p": {
+ "a": 0,
+ "k": [100,100]
+ }
+ }
+ }
+}
diff --git a/schema/assets/image.json b/schema/assets/image.json
index 7272f76..c8d514e 100644
--- a/schema/assets/image.json
+++ b/schema/assets/image.json
@@ -7,6 +7,9 @@
{
"$ref": "#/$defs/assets/asset"
},
+ {
+ "$ref": "#/$defs/helpers/slottable-object"
+ },
{
"type": "object",
"properties": {
@@ -50,7 +53,12 @@
}
}
],
- "required": ["w", "h", "p"]
+ "if": {
+ "required": ["sid"]
+ },
+ "else": {
+ "required": ["w", "h", "p"]
+ }
}
]
}
diff --git a/schema/composition/animation.json b/schema/composition/animation.json
index 518f624..96cdfc8 100644
--- a/schema/composition/animation.json
+++ b/schema/composition/animation.json
@@ -50,6 +50,14 @@
"items": {
"$ref": "#/$defs/helpers/marker"
}
+ },
+ "slots": {
+ "title": "Slots",
+ "description": "Dictionary of slot ids that that will replace matching properties.",
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/helpers/slot"
+ }
}
},
"required": ["w", "h", "fr", "op", "ip"]
diff --git a/schema/helpers/slot.json b/schema/helpers/slot.json
new file mode 100644
index 0000000..941a9ef
--- /dev/null
+++ b/schema/helpers/slot.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "title": "Slot",
+ "description": "Defines a property value that will be set to all matched properties",
+ "properties": {
+ "p": {
+ "title": "Property Value",
+ "description": "Property Value"
+ }
+ },
+ "required": ["p"]
+}
diff --git a/schema/helpers/slottable-object.json b/schema/helpers/slottable-object.json
new file mode 100644
index 0000000..1f3bd77
--- /dev/null
+++ b/schema/helpers/slottable-object.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "title": "Slottable Object",
+ "description": "Object that may have it's value replaced with a slot value",
+ "properties": {
+ "sid": {
+ "title": "Slot Id",
+ "description": "Identifier to look up the slot",
+ "type": "string"
+ }
+ }
+}
\ No newline at end of file
diff --git a/schema/helpers/slottable-property.json b/schema/helpers/slottable-property.json
new file mode 100644
index 0000000..d07016b
--- /dev/null
+++ b/schema/helpers/slottable-property.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "title": "Slottable Property",
+ "description": "Property that may have it's value replaced with a slot value",
+ "allOf": [
+ {
+ "$ref": "#/$defs/helpers/slottable-object"
+ }
+ ],
+ "if": {
+ "required": ["sid"]
+ },
+ "else": {
+ "required": ["a", "k"]
+ }
+}
\ No newline at end of file
diff --git a/schema/properties/color-property.json b/schema/properties/color-property.json
index d6cbfb4..62461ac 100644
--- a/schema/properties/color-property.json
+++ b/schema/properties/color-property.json
@@ -3,6 +3,11 @@
"type": "object",
"title": "Color Property",
"description": "An animatable property that holds a Color",
+ "allOf": [
+ {
+ "$ref": "#/$defs/helpers/slottable-property"
+ }
+ ],
"oneOf": [
{
"$comment": "Not animated",
@@ -38,6 +43,5 @@
}
}
}
- ],
- "required": ["a", "k"]
+ ]
}
diff --git a/schema/properties/scalar-property.json b/schema/properties/scalar-property.json
index 1edd019..0f87353 100644
--- a/schema/properties/scalar-property.json
+++ b/schema/properties/scalar-property.json
@@ -3,6 +3,11 @@
"type": "object",
"title": "Scalar Property",
"description": "An animatable property that holds a float",
+ "allOf": [
+ {
+ "$ref": "#/$defs/helpers/slottable-property"
+ }
+ ],
"oneOf": [
{
"$comment": "Not animated",
@@ -39,5 +44,11 @@
}
}
],
- "required": ["a", "k"]
+ "properties": {
+ "sid": {
+ "title": "Slot Id",
+ "description": "Identifier for a property that can be replaced at runtime",
+ "type": "string"
+ }
+ }
}
diff --git a/schema/properties/vector-property.json b/schema/properties/vector-property.json
index 0a8b6f9..020be30 100644
--- a/schema/properties/vector-property.json
+++ b/schema/properties/vector-property.json
@@ -3,6 +3,11 @@
"type": "object",
"title": "Vector Property",
"description": "An animatable property that holds an array of numbers",
+ "allOf": [
+ {
+ "$ref": "#/$defs/helpers/slottable-property"
+ }
+ ],
"oneOf": [
{
"$comment": "Not animated",
@@ -39,6 +44,5 @@
}
}
}
- ],
- "required": ["a", "k"]
+ ]
}