diff --git a/.github/scripts/medusa-config.js b/.github/scripts/medusa-config.js index 57a0b296f..e4203c05d 100644 --- a/.github/scripts/medusa-config.js +++ b/.github/scripts/medusa-config.js @@ -1,111 +1,76 @@ -const dotenv = require("dotenv") +const { defineConfig, loadEnv } = require("@medusajs/utils") -let ENV_FILE_NAME = "" -switch (process.env.NODE_ENV) { - case "production": - ENV_FILE_NAME = ".env.production" - break - case "staging": - ENV_FILE_NAME = ".env.staging" - break - case "test": - ENV_FILE_NAME = ".env.test" - break - case "development": - default: - ENV_FILE_NAME = ".env" - break -} - -try { - dotenv.config({ path: process.cwd() + "/" + ENV_FILE_NAME }) -} catch (e) {} +loadEnv(process.env.NODE_ENV || "development", process.cwd()) // CORS when consuming Medusa from admin -const ADMIN_CORS = - process.env.ADMIN_CORS || "http://localhost:7000,http://localhost:7001" +// Medusa's docs are added for a better learning experience. Feel free to remove. +const ADMIN_CORS = `${ + process.env.ADMIN_CORS?.length + ? `${process.env.ADMIN_CORS},` + : "http://localhost:7000,http://localhost:7001," +}https://docs.medusajs.com,https://medusa-docs-v2-git-docs-v2-medusajs.vercel.app,https://medusa-resources-git-docs-v2-medusajs.vercel.app` // CORS to avoid issues when consuming Medusa from a client -const STORE_CORS = process.env.STORE_CORS || "http://localhost:8000" +// Medusa's docs are added for a better learning experience. Feel free to remove. +const STORE_CORS = `${ + process.env.STORE_CORS?.length + ? `${process.env.STORE_CORS},` + : "http://localhost:8000," +}https://docs.medusajs.com,https://medusa-docs-v2-git-docs-v2-medusajs.vercel.app,https://medusa-resources-git-docs-v2-medusajs.vercel.app` const DATABASE_URL = process.env.DATABASE_URL || "postgres://medusa:password@localhost/medusa" const REDIS_URL = process.env.REDIS_URL || "redis://localhost:6379" -const plugins = [ - `medusa-fulfillment-manual`, - `medusa-payment-manual`, - { - resolve: `@medusajs/file-local`, - options: { - upload_dir: "uploads", - }, - }, - { - resolve: "@medusajs/admin", - /** @type {import('@medusajs/admin').PluginOptions} */ - options: { - autoRebuild: true, - develop: { - open: process.env.OPEN_BROWSER !== "false", +export default defineConfig({ + plugins: [ + `medusa-fulfillment-manual`, + `medusa-payment-manual`, + { + resolve: `@medusajs/file-local`, + options: { + upload_dir: "uploads", }, }, - }, - { - resolve: `medusa-plugin-meilisearch`, - options: { - config: { - host: process.env.MEILISEARCH_HOST, - apiKey: process.env.MEILISEARCH_API_KEY, - }, - settings: { - products: { - indexSettings: { - searchableAttributes: ["title", "description", "variant_sku"], - displayedAttributes: [ - "id", - "title", - "description", - "variant_sku", - "thumbnail", - "handle", - ], + { + resolve: `medusa-plugin-meilisearch`, + options: { + config: { + host: process.env.MEILISEARCH_HOST, + apiKey: process.env.MEILISEARCH_API_KEY, + }, + settings: { + products: { + indexSettings: { + searchableAttributes: ["title", "description", "variant_sku"], + displayedAttributes: [ + "id", + "title", + "description", + "variant_sku", + "thumbnail", + "handle", + ], + }, + primaryKey: "id", }, - primaryKey: "id", }, }, }, + ], + admin: { + backendUrl: "http://localhost:9000", }, -] - -const modules = { - /*eventBus: { - resolve: "@medusajs/event-bus-redis", - options: { - redisUrl: REDIS_URL - } + projectConfig: { + databaseUrl: DATABASE_URL, + http: { + storeCors: STORE_CORS, + adminCors: ADMIN_CORS, + authCors: process.env.AUTH_CORS || ADMIN_CORS, + jwtSecret: process.env.JWT_SECRET || "supersecret", + cookieSecret: process.env.COOKIE_SECRET || "supersecret", + }, + redisUrl: REDIS_URL, }, - cacheService: { - resolve: "@medusajs/cache-redis", - options: { - redisUrl: REDIS_URL - } - },*/ -} - -const projectConfig = { - jwtSecret: process.env.JWT_SECRET, - cookieSecret: process.env.COOKIE_SECRET, - store_cors: STORE_CORS, - database_url: DATABASE_URL, - admin_cors: ADMIN_CORS, - // Uncomment the following lines to enable REDIS - redis_url: REDIS_URL, -} - -module.exports = { - projectConfig, - plugins, - modules, -} +}) diff --git a/.github/workflows/test-e2e.yaml b/.github/workflows/test-e2e.yaml index 789445114..2f1f8363b 100644 --- a/.github/workflows/test-e2e.yaml +++ b/.github/workflows/test-e2e.yaml @@ -88,7 +88,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: "18" + node-version: "20" - name: Initialize PostgreSQL run: | @@ -97,13 +97,15 @@ jobs: psql -h localhost -U postgres -d test -c "CREATE DATABASE ${{ env.TEST_POSTGRES_DATABASE }} OWNER ${{ env.TEST_POSTGRES_USER }};" - name: Install Medusa CLI - run: npm install @medusajs/medusa-cli -g + run: npm install @medusajs/medusa-cli@preview -g - name: Setup medusa backend server working-directory: ../ # https://docs.medusajs.com/cli/reference#options run: | medusa new backend \ -y \ + --v2 \ + --branch feat/v2 \ --skip-db \ --skip-migrations \ --skip-env \ @@ -113,10 +115,6 @@ jobs: --db-host ${{ env.TEST_POSTGRES_HOST }} \ --db-port ${{ env.TEST_POSTGREST_PORT }} - - name: Build the backend - working-directory: ../backend - run: yarn build:admin - - name: Setup search in the backend working-directory: ../backend run: yarn add medusa-plugin-meilisearch @@ -130,7 +128,7 @@ jobs: - name: Run backend server working-directory: ../backend - run: medusa develop & + run: medusa develop - name: Install packages run: yarn install -y diff --git a/src/lib/data/products.ts b/src/lib/data/products.ts index 10358a37b..b3fcda8d0 100644 --- a/src/lib/data/products.ts +++ b/src/lib/data/products.ts @@ -2,6 +2,8 @@ import { sdk } from "@lib/config" import { HttpTypes } from "@medusajs/types" import { cache } from "react" import { getRegion } from "./regions" +import { SortOptions } from "@modules/store/components/refinement-list/sort-products" +import { sortProducts } from "@lib/util/sort-products" export const getProductsById = cache(async function ({ ids, @@ -85,3 +87,53 @@ export const getProductsList = cache(async function ({ } }) }) + +/** + * This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter. + * It will then return the paginated products based on the page and limit parameters. + */ +export const getProductsListWithSort = cache(async function ({ + page = 0, + queryParams, + sortBy = "created_at", + countryCode, +}: { + page?: number + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams + sortBy?: SortOptions + countryCode: string +}): Promise<{ + response: { products: HttpTypes.StoreProduct[]; count: number } + nextPage: number | null + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams +}> { + const limit = queryParams?.limit || 12 + + const { + response: { products, count }, + } = await getProductsList({ + pageParam: 0, + queryParams: { + ...queryParams, + limit: 100, + }, + countryCode, + }) + + const sortedProducts = sortProducts(products, sortBy) + + const pageParam = (page - 1) * limit + + const nextPage = count > pageParam + limit ? pageParam + limit : null + + const paginatedProducts = sortedProducts.slice(pageParam, pageParam + limit) + + return { + response: { + products: paginatedProducts, + count, + }, + nextPage, + queryParams, + } +}) diff --git a/src/lib/util/sort-products.ts b/src/lib/util/sort-products.ts new file mode 100644 index 000000000..2b996cccc --- /dev/null +++ b/src/lib/util/sort-products.ts @@ -0,0 +1,57 @@ +import { HttpTypes } from "@medusajs/types" +import { SortOptions } from "@modules/store/components/refinement-list/sort-products" + +interface PricedVariant extends HttpTypes.StoreProductVariant { + calculated_price: { + calculated_amount: number + } +} + +interface PricedProduct extends HttpTypes.StoreProduct { + variants: PricedVariant[] + _minPrice: number +} + +/** + * Helper function to sort products by price until the store API supports sorting by price + * @param products + * @param sortBy + * @returns products sorted by price + */ +export function sortProducts( + products: HttpTypes.StoreProduct[], + sortBy: SortOptions +): PricedProduct[] { + let sortedProducts = products as PricedProduct[] + + if (["price_asc", "price_desc"].includes(sortBy)) { + // Precompute the minimum price for each product + sortedProducts.forEach((product) => { + if (product.variants && product.variants.length > 0) { + product._minPrice = Math.min( + ...product.variants.map( + (variant) => variant?.calculated_price?.calculated_amount + ) + ) + } else { + product._minPrice = Infinity + } + }) + + // Sort products based on the precomputed minimum prices + sortedProducts.sort((a, b) => { + const diff = a._minPrice - b._minPrice + return sortBy === "price_asc" ? diff : -diff + }) + } + + if (sortBy === "created_at") { + sortedProducts.sort((a, b) => { + return ( + new Date(b.created_at!).getTime() - new Date(a.created_at!).getTime() + ) + }) + } + + return sortedProducts +} diff --git a/src/modules/checkout/components/addresses/index.tsx b/src/modules/checkout/components/addresses/index.tsx index 464e2857d..e506b7abd 100644 --- a/src/modules/checkout/components/addresses/index.tsx +++ b/src/modules/checkout/components/addresses/index.tsx @@ -29,7 +29,7 @@ const Addresses = ({ const isOpen = searchParams.get("step") === "address" - const { state: sameAsSBilling, toggle: toggleSameAsBilling } = useToggleState( + const { state: sameAsBilling, toggle: toggleSameAsBilling } = useToggleState( cart?.shipping_address && cart?.billing_address ? compareAddresses(cart?.shipping_address, cart?.billing_address) : true @@ -68,12 +68,12 @@ const Addresses = ({
- {!sameAsSBilling && ( + {!sameAsBilling && (
- {sameAsSBilling ? ( + {sameAsBilling ? ( Billing- and delivery address are the same. diff --git a/src/modules/checkout/components/billing_address/index.tsx b/src/modules/checkout/components/billing_address/index.tsx index 2df1b93c0..5c81c5b06 100644 --- a/src/modules/checkout/components/billing_address/index.tsx +++ b/src/modules/checkout/components/billing_address/index.tsx @@ -102,6 +102,7 @@ const BillingAddress = ({ cart }: { cart: HttpTypes.StoreCart | null }) => { autoComplete="address-level1" value={formData["billing_address.province"]} onChange={handleChange} + required data-testid="billing-province-input" /> void }) => { - const [formData, setFormData] = useState({}) + const [formData, setFormData] = useState>({}) const countriesInRegion = useMemo( () => cart?.region?.countries?.map((c) => c.iso_2), @@ -34,9 +34,13 @@ const ShippingAddress = ({ [customer?.addresses, countriesInRegion] ) - const setFormAddress = useCallback( - (address?: HttpTypes.StoreCartAddress, email?: string) => { - setFormData({ + const setFormAddress = ( + address?: HttpTypes.StoreCartAddress, + email?: string + ) => { + address && + setFormData((prevState: Record) => ({ + ...prevState, "shipping_address.first_name": address?.first_name || "", "shipping_address.last_name": address?.last_name || "", "shipping_address.address_1": address?.address_1 || "", @@ -45,32 +49,26 @@ const ShippingAddress = ({ "shipping_address.city": address?.city || "", "shipping_address.country_code": address?.country_code || "", "shipping_address.province": address?.province || "", - email: email || "", "shipping_address.phone": address?.phone || "", - }) - }, - [] - ) + })) - useEffect(() => { - setFormAddress(cart?.shipping_address, cart?.email) - }, [setFormAddress, cart?.shipping_address, cart?.email]) + email && + setFormData((prevState: Record) => ({ + ...prevState, + email: email, + })) + } useEffect(() => { - if (!formData.email && customer?.email) { - return setFormData({ - ...formData, - email: customer.email, - }) + // Ensure cart is not null and has a shipping_address before setting form data + if (cart && cart.shipping_address) { + setFormAddress(cart?.shipping_address, cart?.email) } - if (!formData.email && cart?.email) { - return setFormData({ - ...formData, - email: cart.email, - }) + if (cart && !cart.email && customer?.email) { + setFormAddress(undefined, customer.email) } - }, [formData, customer?.email, cart?.email]) + }, [cart]) // Add cart as a dependency const handleChange = ( e: React.ChangeEvent< @@ -170,6 +168,7 @@ const ShippingAddress = ({ autoComplete="address-level1" value={formData["shipping_address.province"]} onChange={handleChange} + required data-testid="shipping-province-input" />
diff --git a/src/modules/checkout/components/shipping/index.tsx b/src/modules/checkout/components/shipping/index.tsx index 2d0b73178..74b36b204 100644 --- a/src/modules/checkout/components/shipping/index.tsx +++ b/src/modules/checkout/components/shipping/index.tsx @@ -32,7 +32,8 @@ const Shipping: React.FC = ({ const isOpen = searchParams.get("step") === "delivery" const selectedShippingMethod = availableShippingMethods?.find( - (method) => method.id === cart.shipping_methods?.[0]?.shipping_option_id + // To do: remove the previously selected shipping method instead of using the last one + (method) => method.id === cart.shipping_methods?.at(-1)?.shipping_option_id ) const handleEdit = () => { diff --git a/src/modules/checkout/templates/checkout-form/index.tsx b/src/modules/checkout/templates/checkout-form/index.tsx index 73dadf166..263b541dd 100644 --- a/src/modules/checkout/templates/checkout-form/index.tsx +++ b/src/modules/checkout/templates/checkout-form/index.tsx @@ -1,37 +1,28 @@ -"use client" - -import { retrieveCart } from "@lib/data/cart" -import { getCustomer } from "@lib/data/customer" import { listCartShippingMethods } from "@lib/data/fulfillment" import { listCartPaymentMethods } from "@lib/data/payment" -import { HttpTypes, StoreCart, StoreCustomer } from "@medusajs/types" +import { HttpTypes } from "@medusajs/types" import Addresses from "@modules/checkout/components/addresses" import Payment from "@modules/checkout/components/payment" import Review from "@modules/checkout/components/review" import Shipping from "@modules/checkout/components/shipping" -import { useState } from "react" -export default function CheckoutForm({ +export default async function CheckoutForm({ cart, customer, }: { cart: HttpTypes.StoreCart | null customer: HttpTypes.StoreCustomer | null }) { - const [shippingMethods, setAvailableShippingMethods] = useState([]) - const [paymentMethods, setPaymentMethods] = useState([]) - if (!cart) { return null } - listCartShippingMethods(cart.id).then((methods: any) => - setAvailableShippingMethods(methods) - ) + const shippingMethods = await listCartShippingMethods(cart.id) + const paymentMethods = await listCartPaymentMethods(cart.region?.id ?? "") - listCartPaymentMethods(cart.region?.id ?? "").then((payments: any) => - setPaymentMethods(payments) - ) + if (!shippingMethods || !paymentMethods) { + return null + } return (
diff --git a/src/modules/common/components/filter-radio-group/index.tsx b/src/modules/common/components/filter-radio-group/index.tsx index 727759384..dc70edeb4 100644 --- a/src/modules/common/components/filter-radio-group/index.tsx +++ b/src/modules/common/components/filter-radio-group/index.tsx @@ -1,6 +1,5 @@ import { EllipseMiniSolid } from "@medusajs/icons" import { Label, RadioGroup, Text, clx } from "@medusajs/ui" -import { ChangeEvent } from "react" type FilterRadioGroupProps = { title: string @@ -23,23 +22,17 @@ const FilterRadioGroup = ({ return (
{title} - + {items?.map((i) => (
{i.value === value && } - handleChange( - e as unknown as ChangeEvent, - i.value - ) - } className="hidden peer" id={i.value} value={i.value} diff --git a/src/modules/products/components/product-preview/price.tsx b/src/modules/products/components/product-preview/price.tsx index fbf549fe1..f8fa5866f 100644 --- a/src/modules/products/components/product-preview/price.tsx +++ b/src/modules/products/components/product-preview/price.tsx @@ -2,6 +2,10 @@ import { Text, clx } from "@medusajs/ui" import { VariantPrice } from "types/global" export default async function PreviewPrice({ price }: { price: VariantPrice }) { + if (!price) { + return null + } + return ( <> {price.price_type === "sale" && ( diff --git a/src/modules/store/components/refinement-list/sort-products/index.tsx b/src/modules/store/components/refinement-list/sort-products/index.tsx index d43fa52ce..384896aa1 100644 --- a/src/modules/store/components/refinement-list/sort-products/index.tsx +++ b/src/modules/store/components/refinement-list/sort-products/index.tsx @@ -1,7 +1,5 @@ "use client" -import { ChangeEvent } from "react" - import FilterRadioGroup from "@modules/common/components/filter-radio-group" export type SortOptions = "price_asc" | "price_desc" | "created_at" @@ -9,7 +7,7 @@ export type SortOptions = "price_asc" | "price_desc" | "created_at" type SortProductsProps = { sortBy: SortOptions setQueryParams: (name: string, value: SortOptions) => void - 'data-testid'?: string + "data-testid"?: string } const sortOptions = [ @@ -27,10 +25,13 @@ const sortOptions = [ }, ] -const SortProducts = ({ 'data-testid': dataTestId, sortBy, setQueryParams }: SortProductsProps) => { - const handleChange = (e: ChangeEvent) => { - const newSortBy = e.target.value as SortOptions - setQueryParams("sortBy", newSortBy) +const SortProducts = ({ + "data-testid": dataTestId, + sortBy, + setQueryParams, +}: SortProductsProps) => { + const handleChange = (value: SortOptions) => { + setQueryParams("sortBy", value) } return ( diff --git a/src/modules/store/templates/paginated-products.tsx b/src/modules/store/templates/paginated-products.tsx index 83e9ed98e..5a0b5aaa8 100644 --- a/src/modules/store/templates/paginated-products.tsx +++ b/src/modules/store/templates/paginated-products.tsx @@ -1,4 +1,4 @@ -import { getProductsList } from "@lib/data/products" +import { getProductsListWithSort } from "@lib/data/products" import { getRegion } from "@lib/data/regions" import ProductPreview from "@modules/products/components/product-preview" import { Pagination } from "@modules/store/components/pagination" @@ -30,7 +30,7 @@ export default async function PaginatedProducts({ countryCode: string }) { const queryParams: PaginatedProductsParams = { - limit: PRODUCT_LIMIT, + limit: 12, } if (collectionId) { @@ -45,19 +45,8 @@ export default async function PaginatedProducts({ queryParams["id"] = productsIds } - if (sortBy) { - // TODO: Currently sorting by price doesn't work, fix it - switch (sortBy) { - case "price_asc": - queryParams["order"] = "price" - break - case "price_desc": - queryParams["order"] = "-price" - break - case "created_at": - queryParams["order"] = "created_at" - break - } + if (sortBy === "created_at") { + queryParams["order"] = "created_at" } const region = await getRegion(countryCode) @@ -66,11 +55,12 @@ export default async function PaginatedProducts({ return null } - const { + let { response: { products, count }, - } = await getProductsList({ - pageParam: page, + } = await getProductsListWithSort({ + page, queryParams, + sortBy, countryCode, }) diff --git a/yarn.lock b/yarn.lock index fe791bec4..a0ca4f960 100644 --- a/yarn.lock +++ b/yarn.lock @@ -538,37 +538,37 @@ resolved "https://registry.yarnpkg.com/@medusajs/client-types/-/client-types-0.2.12-preview-20240505115807.tgz#5090e140d4ade84668eedc81222ab35366088831" integrity sha512-f7T/7WUAGOFfsNsjdCcVoWLlAqryaQB+hF0v/Dzst2hv+PdJGqHfHwTNdeK3ZYhUwzSQ8YdnCYsj9OEJR9SPiQ== -"@medusajs/icons@1.2.2-preview-20240703120635": - version "1.2.2-preview-20240703120635" - resolved "https://registry.yarnpkg.com/@medusajs/icons/-/icons-1.2.2-preview-20240703120635.tgz#0af56888a4c8d847eb3c6407976dc68234f1c245" - integrity sha512-TloJclvm9Zg/PDZYJQIQ80+hsBJqNTQe+g5qdve/uuyMdjUyKICrHJ5s9vgBjWqaolgSpnaoFKcDW8IMHsXmjg== +"@medusajs/icons@1.2.2-preview-20240704090504": + version "1.2.2-preview-20240704090504" + resolved "https://registry.yarnpkg.com/@medusajs/icons/-/icons-1.2.2-preview-20240704090504.tgz#7919b28f370b4b88f0b37d681b598a20d4ae79b4" + integrity sha512-iqwPVbIUUuUy9F2OUuHI7tpXbBz7Go9OD40NP4CzN0/zoWzplxxiUKShya2lmKcTY1DO93nz4naUb8uBm/r/Zg== "@medusajs/js-sdk@preview": - version "0.0.2-preview-20240703120635" - resolved "https://registry.yarnpkg.com/@medusajs/js-sdk/-/js-sdk-0.0.2-preview-20240703120635.tgz#d3728ee36cd40a8f618fd83daa4d10d70f25793b" - integrity sha512-FyhRKwf51Rm1oc5exUNoU/egLd2zrmY5q5LN5fCz/sMJQd7+6jiAMlGnEZ8FbsMfqRh9XIfISj7bjVQiDfxtBw== + version "0.0.2-preview-20240704090504" + resolved "https://registry.yarnpkg.com/@medusajs/js-sdk/-/js-sdk-0.0.2-preview-20240704090504.tgz#30b3ad7fbed4dbdd34efb7c62e3f0158ffa659f7" + integrity sha512-P2S7soZLCxkTLrbjeKhZO6KH/cvN9LSyLWOg5/HhaF6+pF/l95gC+4fY0uIhCc3PGa/IJ0bwXxFHhJaw/8xJfQ== dependencies: qs "^6.12.1" "@medusajs/types@preview": - version "1.12.0-preview-20240703120635" - resolved "https://registry.yarnpkg.com/@medusajs/types/-/types-1.12.0-preview-20240703120635.tgz#1cf315e20ede52399ec74fe29eee8173978a4896" - integrity sha512-Sy+K2mtbNAjjGdALdZK9Cm1J8askcTN2VPL1A+kichfTnDZkGNsJ+ngf8V83e03QtNw3QjqKs1YxwfRK/9OYXg== + version "1.12.0-preview-20240704090504" + resolved "https://registry.yarnpkg.com/@medusajs/types/-/types-1.12.0-preview-20240704090504.tgz#18876ef1fd177fbae2de4711219c21dd6e0d3685" + integrity sha512-OGbhOf8urxXzqNz+Sxl4/4LvD8+pW6kb4S7pGySJpcJOQwg+E7kHSfIbEdkkv9EPI2JDSCrvny/y0dBpG0eA2g== "@medusajs/ui-preset@preview": - version "1.1.4-preview-20240703120635" - resolved "https://registry.yarnpkg.com/@medusajs/ui-preset/-/ui-preset-1.1.4-preview-20240703120635.tgz#c5d0ab18cfdbff7911e86638c9b112aebe77815d" - integrity sha512-o0JD/ZEkHvSk2VyK6mYR/8oK+HoNMuqyo9OIqs4kT0WrKe5yQWjGgsKJlWR35BTLNR6XkIWUHQnDn5sFIg9hvg== + version "1.1.4-preview-20240704090504" + resolved "https://registry.yarnpkg.com/@medusajs/ui-preset/-/ui-preset-1.1.4-preview-20240704090504.tgz#c246b4fc4b5daba053a6347a54117eeaa11c06a2" + integrity sha512-yZzDMHYk3zDsubzzUFL0LvlJtkliYa526WOT1Be2hnVSk5czZowvBpddu2O6X6/PON7F/ddjeorUmd0bzjlBOA== dependencies: "@tailwindcss/forms" "^0.5.3" tailwindcss-animate "^1.0.6" "@medusajs/ui@preview": - version "3.0.1-preview-20240703120635" - resolved "https://registry.yarnpkg.com/@medusajs/ui/-/ui-3.0.1-preview-20240703120635.tgz#6752df071f13e0e69a194864c5d2e874d1a10f4a" - integrity sha512-TAFKgvjLvC+pmjcFESenTyq4sQrUTer5cLxTng6r9zxMpn/mHg4b3wbCPr1bGG1o1bPMp7TydrDDLonMP1ZxIQ== + version "3.0.1-preview-20240704090504" + resolved "https://registry.yarnpkg.com/@medusajs/ui/-/ui-3.0.1-preview-20240704090504.tgz#7950a19b9575951e1fe86d45630c88decd244dea" + integrity sha512-ppGxvAXsr4qe4jsLGNxIqwGOBwPBO2JUkrBRlmiwyOVKbaGGyvEnqdVAiuwtYhqM8CtTcWHWVWb1N38vbCM4UQ== dependencies: - "@medusajs/icons" "1.2.2-preview-20240703120635" + "@medusajs/icons" "1.2.2-preview-20240704090504" "@radix-ui/react-accordion" "1.2.0" "@radix-ui/react-alert-dialog" "1.1.1" "@radix-ui/react-avatar" "1.1.0"