Skip to content

Commit

Permalink
fix(vue-demo-store): visibility classes (#545)
Browse files Browse the repository at this point in the history
* fix(helpers): visibility css classes

* fix(vue-demo-store): add visibility classes to safe list

* chore: generate changeset

* chore: improve code, add tests and fix linter error

---------

Co-authored-by: Marc Peternell <[email protected]>
  • Loading branch information
itscark and Marc Peternell authored Jan 29, 2024
1 parent a595552 commit 6664aa2
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 28 deletions.
6 changes: 6 additions & 0 deletions .changeset/unlucky-turkeys-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"vue-demo-store": minor
"@shopware-pwa/helpers-next": minor
---

Fix visibility classes
68 changes: 68 additions & 0 deletions packages/helpers/src/cms/getCmsLayoutConfiguration.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { describe, expect, it } from "vitest";
import { _getVisibilityClasses } from "./getCmsLayoutConfiguration";
type FunctionParams = Parameters<typeof _getVisibilityClasses>;

describe("getVisibilityClasses", () => {
it("should return an empty object if content is a CmsSlot or has no visibility property", () => {
const apiAlias = "cms_slot";
const content: FunctionParams[0] = { apiAlias };
const result = _getVisibilityClasses(content);
expect(result).toEqual({});
});

it("should return an empty object if content visibility is an empty object", () => {
const apiAlias = "cms_block";
const content: FunctionParams[0] = { apiAlias, visibility: {} };
const result = _getVisibilityClasses(content);
expect(result).toEqual({});
});

it("should return an empty object if there is no content visibility", () => {
const apiAlias = "cms_block";
const content: FunctionParams[0] = { apiAlias };
const result = _getVisibilityClasses(content);
expect(result).toEqual({});
});

it("should return the correct visibility CSS classes for tablet", () => {
const apiAlias = "cms_block";
const content: FunctionParams[0] = {
apiAlias,
visibility: {
mobile: true,
tablet: false,
desktop: true,
},
};
const result = _getVisibilityClasses(content);
expect(result).toEqual({ "md:max-lg:hidden": true });
});

it("should return the correct visibility CSS classes for desktop", () => {
const apiAlias = "cms_block";
const content: FunctionParams[0] = {
apiAlias,
visibility: {
mobile: true,
tablet: true,
desktop: false,
},
};
const result = _getVisibilityClasses(content);
expect(result).toEqual({ "lg:hidden": true });
});

it("should return the correct visibility CSS classes for mobile", () => {
const apiAlias = "cms_section";
const content: FunctionParams[0] = {
apiAlias,
visibility: {
mobile: false,
tablet: true,
desktop: true,
},
};
const result = _getVisibilityClasses(content);
expect(result).toEqual({ "max-md:hidden": true });
});
});
48 changes: 21 additions & 27 deletions packages/helpers/src/cms/getCmsLayoutConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,40 +56,34 @@ function isCmsSection(
return content.apiAlias === "cms_section";
}

const deviceMap: { [key in CmsVisibility]: "md" | "xl" | "lg" } = {
mobile: "md",
tablet: "lg",
desktop: "xl",
};

/**
* Get css object for visibility classes
* Get CSS classes for visibility based on device type.
*
* mobile -> "md"
* tablet -> "lg"
* desktop -> "xl"
* i.e. if tablet device is set to hidden, the output class will be "md:max-lg:hidden"
*
* i.e. if tablet device is set to hidden, the output class will be "lg:hidden"
* @internal
*/
function getVisibilityClasses(content: CmsBlock | CmsSection | CmsSlot) {
if (
isCmsSlot(content) ||
!content?.visibility ||
Object.keys(content?.visibility).length === 0
)
return {};
export function _getVisibilityClasses(
content: CmsBlock | CmsSection | CmsSlot,
): Record<string, boolean> {
const visibilityCssClasses: Record<string, boolean> = {};

const visibilityCssClasses: {
"md:hidden"?: boolean;
"xl:hidden"?: boolean;
"lg:hidden"?: boolean;
} = {};
if (isCmsSlot(content) || !content?.visibility) {
return visibilityCssClasses;
}

Object.entries(content?.visibility)?.forEach(([device, isVisible]) => {
if (!isVisible) {
visibilityCssClasses[`${deviceMap[device]}:hidden`] = true;
const visibilityMap: Record<CmsVisibility, string> = {
mobile: "max-md:hidden", // TODO: #549 - create exported helper classes to be included in safelist
tablet: "md:max-lg:hidden",
desktop: "lg:hidden",
};

Object.entries(content.visibility).forEach(([device, isVisible]) => {
if (!isVisible && visibilityMap[device]) {
visibilityCssClasses[visibilityMap[device]] = true;
}
});

return visibilityCssClasses;
}

Expand All @@ -109,7 +103,7 @@ export function getCmsLayoutConfiguration<
layoutStyles: {},
} as LayoutConfiguration;
}
const visibilityCssClasses = getVisibilityClasses(content);
const visibilityCssClasses = _getVisibilityClasses(content);
// convert css classes string into object in format { "css-class-name": true }
const mappedCssClasses =
typeof content.cssClass === "string"
Expand Down
3 changes: 2 additions & 1 deletion packages/helpers/src/cms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ type CmsPageResponse = {
landingPage: LandingPage;
};

export * from "./getCmsLayoutConfiguration";
export { getCmsLayoutConfiguration } from "./getCmsLayoutConfiguration";
export type { LayoutConfiguration } from "./getCmsLayoutConfiguration";
export * from "./getBackgroundImageUrl";
export * from "./buildUrlPrefix";

Expand Down
1 change: 1 addition & 0 deletions templates/vue-demo-store/uno.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,5 @@ export default defineConfig({
`,
},
],
safelist: ["max-md:hidden", "md:max-lg:hidden", "lg:hidden"],
});

1 comment on commit 6664aa2

@vercel
Copy link

@vercel vercel bot commented on 6664aa2 Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.