("root");
let themeSettings = useThemeSettings();
let productSwatches: SwatchesConfigs = themeSettings.productSwatches;
let { options, swatches } = productSwatches;
+ let colorsSwatches: ColorSwatch[] = colorsConfigs?.length
+ ? colorsConfigs
+ : swatches.colors;
let optionConf = options.find((opt) => {
return opt.name.toLowerCase() === name.toLowerCase();
});
@@ -99,9 +109,7 @@ export function VariantOption(props: VariantOptionProps) {
{type === "color" && (
{values.map(({ value, isAvailable }) => {
- let swatchColor = swatches.colors.find(
- ({ name }) => name === value,
- );
+ let swatchColor = colorsSwatches.find(({ name }) => name === value);
return (
diff --git a/app/root.tsx b/app/root.tsx
index bbb397cc..7cbcb9dd 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -27,20 +27,25 @@ import type {
MetaArgs,
} from "@shopify/remix-oxygen";
import { defer } from "@shopify/remix-oxygen";
-import { useThemeSettings, withWeaverse } from "@weaverse/hydrogen";
+import {
+ type ColorSwatch,
+ useThemeSettings,
+ withWeaverse,
+} from "@weaverse/hydrogen";
import type { CSSProperties } from "react";
-import type { LayoutQuery } from "storefrontapi.generated";
+import type { ColorsConfigsQuery, LayoutQuery } from "storefrontapi.generated";
import invariant from "tiny-invariant";
import { seoPayload } from "~/lib/seo.server";
import { CustomAnalytics } from "~/modules/custom-analytics";
import { GlobalLoading } from "~/modules/global-loading";
import { Layout as PageLayout } from "~/modules/layout";
import { TooltipProvider } from "./components/tooltip";
+import { COLORS_CONFIGS_QUERY } from "./data/queries";
import { DEFAULT_LOCALE, parseMenu } from "./lib/utils";
-import { GenericError } from "./modules/generic-error";
import { NotFound } from "./modules/not-found";
-import styles from "./styles/app.css?url";
import { GlobalStyle } from "./weaverse/style";
+import { GenericError } from "./modules/generic-error";
+import styles from "./styles/app.css?url";
export type RootLoader = typeof loader;
@@ -111,8 +116,9 @@ export async function loader(args: LoaderFunctionArgs) {
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
*/
async function loadCriticalData({ request, context }: LoaderFunctionArgs) {
- let [layout] = await Promise.all([
+ let [layout, colorsConfigs] = await Promise.all([
getLayoutData(context),
+ getColorsConfigs(context),
// Add other queries here, so that they are loaded in parallel
]);
@@ -138,6 +144,7 @@ async function loadCriticalData({ request, context }: LoaderFunctionArgs) {
selectedLocale: storefront.i18n,
weaverseTheme: await context.weaverse.loadThemeSettings(),
googleGtmID: context.env.PUBLIC_GOOGLE_GTM_ID,
+ colorsConfigs,
};
}
@@ -372,3 +379,31 @@ async function getLayoutData({ storefront, env }: AppLoadContext) {
return { shop: data.shop, headerMenu, footerMenu };
}
+
+async function getColorsConfigs(context: AppLoadContext) {
+ let {
+ METAOBJECT_COLORS_TYPE: type,
+ METAOBJECT_COLOR_NAME_KEY: nameKey,
+ METAOBJECT_COLOR_VALUE_KEY: valueKey,
+ } = context.env;
+ if (!type || !nameKey || !valueKey) {
+ return [];
+ }
+ let { metaobjects } = await context.storefront.query(
+ COLORS_CONFIGS_QUERY,
+ {
+ variables: {
+ type,
+ nameKey,
+ valueKey,
+ },
+ },
+ );
+ return metaobjects.nodes.map(({ id, name, value }) => {
+ return {
+ id,
+ name: name.value,
+ value: value.value,
+ };
+ }) as ColorSwatch[];
+}
diff --git a/app/sections/collection-filters/filter-item.tsx b/app/sections/collection-filters/filter-item.tsx
index 540e0925..9c51253c 100644
--- a/app/sections/collection-filters/filter-item.tsx
+++ b/app/sections/collection-filters/filter-item.tsx
@@ -1,6 +1,15 @@
-import { useLocation, useNavigate, useSearchParams } from "@remix-run/react";
+import {
+ useLocation,
+ useNavigate,
+ useRouteLoaderData,
+ useSearchParams,
+} from "@remix-run/react";
import type { Filter } from "@shopify/hydrogen/storefront-api-types";
-import { type SwatchesConfigs, useThemeSettings } from "@weaverse/hydrogen";
+import {
+ type ColorSwatch,
+ type SwatchesConfigs,
+ useThemeSettings,
+} from "@weaverse/hydrogen";
import clsx from "clsx";
import { useState } from "react";
import { Checkbox } from "~/components/checkbox";
@@ -9,6 +18,7 @@ import { cn } from "~/lib/cn";
import type { AppliedFilter } from "~/lib/filter";
import { getAppliedFilterLink, getFilterLink } from "~/lib/filter";
import { variants as productOptionsVariants } from "~/modules/product-form/options";
+import type { RootLoader } from "~/root";
export function FilterItem({
displayAs,
@@ -25,6 +35,7 @@ export function FilterItem({
let [params] = useSearchParams();
let location = useLocation();
let themeSettings = useThemeSettings();
+ let { colorsConfigs } = useRouteLoaderData("root");
let { options, swatches }: SwatchesConfigs = themeSettings.productSwatches;
let filter = appliedFilters.find(
@@ -45,7 +56,10 @@ export function FilterItem({
}
if (displayAs === "color-swatch") {
- let swatchColor = swatches.colors.find(({ name }) => name === option.label);
+ let colors: ColorSwatch[] = colorsConfigs?.length
+ ? colorsConfigs
+ : swatches.colors;
+ let swatchColor = colors.find(({ name }) => name === option.label);
let optionConf = options.find(({ name }) => {
return name.toLowerCase() === option.label.toLowerCase();
});
diff --git a/env.d.ts b/env.d.ts
index c06cbeb0..75151fc8 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -22,6 +22,10 @@ declare global {
// declare additional Env parameter use in the fetch handler and Remix loader context here
PUBLIC_GOOGLE_GTM_ID: string;
JUDGEME_PRIVATE_API_TOKEN: string;
+ CUSTOM_COLLECTION_BANNER_METAFIELD: string;
+ METAOBJECT_COLORS_TYPE: string;
+ METAOBJECT_COLOR_NAME_KEY: string;
+ METAOBJECT_COLOR_VALUE_KEY: string;
}
}
diff --git a/storefrontapi.generated.d.ts b/storefrontapi.generated.d.ts
index f799f5b4..9642f0c4 100644
--- a/storefrontapi.generated.d.ts
+++ b/storefrontapi.generated.d.ts
@@ -284,6 +284,27 @@ export type CartApiQueryFragment = Pick<
>;
};
+export type ColorsConfigsQueryVariables = StorefrontAPI.Exact<{
+ type: StorefrontAPI.Scalars['String']['input'];
+ nameKey: StorefrontAPI.Scalars['String']['input'];
+ valueKey: StorefrontAPI.Scalars['String']['input'];
+}>;
+
+export type ColorsConfigsQuery = {
+ metaobjects: {
+ nodes: Array<
+ Pick & {
+ name?: StorefrontAPI.Maybe<
+ Pick
+ >;
+ value?: StorefrontAPI.Maybe<
+ Pick
+ >;
+ }
+ >;
+ };
+};
+
export type ShopQueryQueryVariables = StorefrontAPI.Exact<{
country?: StorefrontAPI.InputMaybe;
language?: StorefrontAPI.InputMaybe;
@@ -1816,6 +1837,10 @@ export type OurTeamQuery = {
};
interface GeneratedQueryTypes {
+ '#graphql\n query colorsConfigs($type: String!, $nameKey: String!, $valueKey: String!) {\n metaobjects(first: 100, type: $type) {\n nodes {\n id\n name: field(key: $nameKey) {\n value\n }\n value: field(key: $valueKey) {\n value\n }\n }\n }\n }\n': {
+ return: ColorsConfigsQuery;
+ variables: ColorsConfigsQueryVariables;
+ };
'#graphql\n query shopQuery($country: CountryCode, $language: LanguageCode)\n @inContext(country: $country, language: $language) {\n shop {\n name\n description\n }\n }\n': {
return: ShopQueryQuery;
variables: ShopQueryQueryVariables;