diff --git a/packages/core/index.js b/packages/core/index.js index 1c70ac58..ee2bf185 100644 --- a/packages/core/index.js +++ b/packages/core/index.js @@ -163,21 +163,27 @@ export const buildValue = (property, value, config, vars) => { // Build mixin styles export const buildMixin = (styles, theme, prev) => { prev = prev || new Set(); - if (typeof styles.apply === "string" && styles.apply) { - // Check for circular mixins found - if (prev.has(styles.apply)) { - const items = Array.from(prev); - throw new Error(`Circular mixins found: ${items.join("->")}->${styles.apply}`); - } - // Apply styles from this mixin - prev.add(styles.apply); - let appliedStyles = getInObject(theme, styles.apply) || {}; - if (appliedStyles.default && typeof appliedStyles.default === "object") { - appliedStyles = appliedStyles.default; - } + if (styles.apply && (typeof styles.apply === "string" || Array.isArray(styles.apply))) { + const mixinsList = [styles.apply].flat().filter(n => n && typeof n === "string"); return { ...excludeInObject(styles, "apply"), - ...buildMixin(appliedStyles, theme, prev), + ...toObject(mixinsList, (newStyles, mixinName) => { + // Check for circular mixins found + if (prev.has(mixinName)) { + const items = Array.from(prev); + throw new Error(`Circular mixins found: ${items.join("->")}->${mixinName}`); + } + // Apply styles from this mixin + prev.add(mixinName); + let appliedStyles = getInObject(theme, mixinName) || {}; + if (appliedStyles.default && typeof appliedStyles.default === "object") { + appliedStyles = appliedStyles.default; + } + return { + ...newStyles, + ...buildMixin(appliedStyles, theme, prev), + }; + }), }; } // No mixin to apply --> return styles diff --git a/test/mixins.test.js b/test/mixins.test.js index ce04a46b..1a7b8041 100644 --- a/test/mixins.test.js +++ b/test/mixins.test.js @@ -8,7 +8,7 @@ describe("buildMixin", () => { }, "basic": { color: "black", - display: "none" + display: "none", }, "circular1": { display: "none", @@ -18,6 +18,12 @@ describe("buildMixin", () => { display: "block", apply: "test.circular1", }, + "list": { + apply: ["test.default", "test.basic"], + }, + "listCircular": { + apply: ["test.default", "test.circular1"], + }, }, }; it("should apply styles defined in the mixin", () => { @@ -51,4 +57,29 @@ describe("buildMixin", () => { const finalStyles = buildMixin(initialStyles, theme); expect(finalStyles.color).toBe("red"); }); + + it("should apply a list of mixins", () => { + const initialStyles = { + color: "white", + apply: "test.list", + }; + const finalStyles = buildMixin(initialStyles, theme); + expect(finalStyles.color).toBe("black"); + expect(finalStyles.display).toBe("none"); + }); + + it("should throw an error if circular mixins are found in the list of mixins", () => { + expect.assertions(1); + try { + const styles = { + display: "flex", + apply: "test.listCircular", + }; + buildMixin(styles, theme); + } + catch (error) { + // const msg = "Circular mixins found: test.circular1->test.circular2->test.circular1" + expect(error.message).toBeDefined(); + } + }); });