diff --git a/CHANGELOG.md b/CHANGELOG.md index 06b65c8..32d60b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [3.1.0] + +### Added + +- `postcss-container-query` + - Allowing for one `@define-container;` declaration to override the container + selector detected automatically in singleContainer mode + ## [3.0.1] +### Changed + - readme updates ## [3.0.0] diff --git a/packages/postcss-container-query/src/containerQuery.js b/packages/postcss-container-query/src/containerQuery.js index 248f8aa..de6d8b2 100644 --- a/packages/postcss-container-query/src/containerQuery.js +++ b/packages/postcss-container-query/src/containerQuery.js @@ -15,13 +15,14 @@ const walkRules = (root, opts, ruleHandler) => { containerSelectors.indexOf(selector) !== -1; const handleRule = (rule, parentCQAtRule) => { + const definedContainer = hasContainerDefinition(rule); const isContainer = - hasContainerDefinition(rule) || + definedContainer || hasContainerSelector(rule.selector) || rule.selector === ":self" || (opts.singleContainer && containerSelectors.length === 0); - const data = { rule, isContainer }; + const data = { rule, isContainer, definedContainer }; if (isContainer && !hasContainerSelector(rule.selector)) { containerSelectors.push(rule.selector); @@ -103,20 +104,33 @@ function containerQuery(options = {}) { if (!meta) { const containers = {}; let currentContainerSelector = null; + let containerDefinitionCount = 0; walkRules( root, { singleContainer }, - ({ rule, isContainer, parentCQAtRule }) => { + ({ rule, isContainer, definedContainer, parentCQAtRule }) => { if ( isContainer && rule.selector !== ":self" && !containers[rule.selector] ) { + if (definedContainer) { + containerDefinitionCount++; + } + const nextContainerSelector = rule.selector; - if (singleContainer && currentContainerSelector) { + if ( + // We allow for a single custom definition to be used in + // singleContainer mode so that the user can select the container + // selector themselves, instead that being picked up as the first + // one automatically. + containerDefinitionCount > 1 && + singleContainer && + currentContainerSelector + ) { throw rule.error( - `define-container declaration detected in singleContainer mode. ` + + `More than one @define-container declaration was detected in singleContainer mode. ` + `Tried to override "${currentContainerSelector}" with "${nextContainerSelector}".` ); } diff --git a/packages/postcss-container-query/src/containerQuery.spec.js b/packages/postcss-container-query/src/containerQuery.spec.js index 68a44b0..be41ae0 100644 --- a/packages/postcss-container-query/src/containerQuery.spec.js +++ b/packages/postcss-container-query/src/containerQuery.spec.js @@ -2,6 +2,7 @@ import postcss from "postcss"; import * as regularTest from "./test/regular"; import * as customPropertiesTest from "./test/custom-properties"; import * as exessContainerDeclarationTest from "./test/exess-container-declaration"; +import * as singleContainerOverrideTest from "./test/single-container-override"; import * as containerAutoDetectionTest from "./test/container-auto-detection"; import * as unrecognisedAtRulesTest from "./test/unrecognised-at-rules"; import * as missingContainerDelcarationTest from "./test/missing-container-declaration"; @@ -92,12 +93,15 @@ test("should properly process CSS", () => test("should detect the first class as the container by default", () => assertProcessingResult(containerAutoDetectionTest)); -test("should throw in non singleContainer mode for defining a different container", () => { +test("should allow for one @define-container declaration in singleContainer mode", () => + assertProcessingResult(singleContainerOverrideTest)); + +test("should throw in singleContainer mode for defining a different container more than one time", () => { expect.assertions(1); return processCss(exessContainerDeclarationTest.cssInput).catch(e => { expect(e.reason).toBe( - "define-container declaration detected in singleContainer mode. " + + "More than one @define-container declaration was detected in singleContainer mode. " + 'Tried to override ".Container" with ".AnotherContainer".' ); }); @@ -121,7 +125,6 @@ test("should be able to disable the css meta export", () => exportMetaInCss: false })); -// todo rename test to reexport // In parcel bundler postcss plugins run multiple times for some reason over the // same css file. If we respect the meta export, then subsequent runs become noop. test("should be able to reexport meta from a previously processed css file", () => diff --git a/packages/postcss-container-query/src/test/container-auto-detection.js b/packages/postcss-container-query/src/test/container-auto-detection.js index dbf2f05..7d13d46 100644 --- a/packages/postcss-container-query/src/test/container-auto-detection.js +++ b/packages/postcss-container-query/src/test/container-auto-detection.js @@ -2,10 +2,11 @@ import { SELECTOR, QUERIES, ELEMENTS, - VALUES, - CONDITIONS + VALUES } from "@zeecoder/container-query-meta-builder"; +// These container definitions should be merged together, as they use the same +// selector export const cssInput = ` .Container { line-height: 3rh; diff --git a/packages/postcss-container-query/src/test/exess-container-declaration.js b/packages/postcss-container-query/src/test/exess-container-declaration.js index f87f383..ce9d3a2 100644 --- a/packages/postcss-container-query/src/test/exess-container-declaration.js +++ b/packages/postcss-container-query/src/test/exess-container-declaration.js @@ -1,10 +1,17 @@ export const cssInput = ` +body { + /* This would be picked up as the container normally in singleContainer mode. */ +} + .Container { + /* One override is allowed */ + @define-container; line-height: 3rh; border: none; } .AnotherContainer { + /* Two override is not allowed */ @define-container; font-size: 2rh; } diff --git a/packages/postcss-container-query/src/test/single-container-override.js b/packages/postcss-container-query/src/test/single-container-override.js new file mode 100644 index 0000000..3a913f8 --- /dev/null +++ b/packages/postcss-container-query/src/test/single-container-override.js @@ -0,0 +1,41 @@ +import { + SELECTOR, + QUERIES, + ELEMENTS, + VALUES +} from "@zeecoder/container-query-meta-builder"; + +export const cssInput = ` +body { + background: red; +} + +.Container { + @define-container; + font-size: 1rh; +}`; + +export const meta = { + [SELECTOR]: ".Container", + [QUERIES]: [ + { + [ELEMENTS]: [ + { + [VALUES]: { + "font-size": `1rh` + } + } + ] + } + ] +}; + +export const cssOutput = ` +body { + background: red; +} + +.Container { +} + +:export { meta: '${JSON.stringify(meta)}' }`; diff --git a/tests/react/hoc/Test/Test.pcss b/tests/react/hoc/Test/Test.pcss index e22830e..787b134 100644 --- a/tests/react/hoc/Test/Test.pcss +++ b/tests/react/hoc/Test/Test.pcss @@ -1,4 +1,9 @@ +body { + background: rgb(200, 200, 200); +} + .Test { + @define-container; position: absolute; width: 100%; height: 100%; diff --git a/tests/react/hoc/index.js b/tests/react/hoc/index.js index f9f5d74..830462c 100644 --- a/tests/react/hoc/index.js +++ b/tests/react/hoc/index.js @@ -5,7 +5,8 @@ import { clearDOM, waitForTestComponentToHaveStyle, changeRootSize, - waitForTestComponentToHaveCustomProperties + waitForTestComponentToHaveCustomProperties, + waitForElementToHaveStyle } from "../../utils"; // Features covered: @@ -20,6 +21,12 @@ describe("withContainerQuery", () => { }); }); + it("should apply styles to the body", async () => { + await waitForElementToHaveStyle(document.body, { + backgroundColor: "rgb(200, 200, 200)" + }); + }); + it("should not have any of the container queries applied", async () => { await waitForTestComponentToHaveStyle({ backgroundColor: "rgb(255, 0, 0)" diff --git a/tests/react/manual/Test/Test.js b/tests/react/manual/Test/Test.js deleted file mode 100644 index 49f5b84..0000000 --- a/tests/react/manual/Test/Test.js +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; -import { withContainerQuery } from "../../../../packages/react-container-query/dist/bundle.esm"; -import { meta } from "./Test.pcss"; - -const Test = () =>
; - -export default withContainerQuery(Test, meta); diff --git a/tests/react/manual/Test/Test.pcss b/tests/react/manual/Test/Test.pcss deleted file mode 100644 index 66546c1..0000000 --- a/tests/react/manual/Test/Test.pcss +++ /dev/null @@ -1,10 +0,0 @@ -.Test { - position: absolute; - width: 100%; - height: 100%; - background-color: rgb(255, 0, 0); - - @container (width > 100px) { - background-color: rgb(0, 255, 0); - } -}