From ad25544dcb9813a321dd105bc7c07304357a0dd7 Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Wed, 23 Oct 2024 17:48:36 -0700 Subject: [PATCH 01/15] Make src in PrintAPI non-optional Provide additional clarity on coment Add change set Update hot-years-relate.md --- .changeset/hot-years-relate.md | 5 +++++ .../src/surfaces/point-of-sale/api/print-api/print-api.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/hot-years-relate.md diff --git a/.changeset/hot-years-relate.md b/.changeset/hot-years-relate.md new file mode 100644 index 000000000..589a64109 --- /dev/null +++ b/.changeset/hot-years-relate.md @@ -0,0 +1,5 @@ +--- +'@shopify/ui-extensions': patch +--- + +POS UI Ext PrintAPI src non-optional diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts index 1886b0480..36a4d0300 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts @@ -3,9 +3,9 @@ */ export interface PrintApiContent { /** Trigger a print dialog - * @param src the source to print. Omit to use the current PrintPreview contents. + * @param src the source URL of the content to print. This URL must be a path of the app backend. Valid document types are text, HTML, image, and PDF. */ - print(src?: string): void; + print(src: string): void; } /** From 9ac908787a77f7914386ed9918777ef3dbacf9fa Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Tue, 29 Oct 2024 13:10:02 -0700 Subject: [PATCH 02/15] Make print api print action async --- .changeset/hot-shirts-clean.md | 5 +++++ .../src/surfaces/point-of-sale/api/print-api/print-api.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/hot-shirts-clean.md diff --git a/.changeset/hot-shirts-clean.md b/.changeset/hot-shirts-clean.md new file mode 100644 index 000000000..8e6d8aaea --- /dev/null +++ b/.changeset/hot-shirts-clean.md @@ -0,0 +1,5 @@ +--- +'@shopify/ui-extensions': patch +--- + +Make POS UI Ext PrintAPI async diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts index 36a4d0300..7b92e010a 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts @@ -5,7 +5,7 @@ export interface PrintApiContent { /** Trigger a print dialog * @param src the source URL of the content to print. This URL must be a path of the app backend. Valid document types are text, HTML, image, and PDF. */ - print(src: string): void; + print(src: string): Promise; } /** From 2522d3e64a633f65eaece9cbe3ee0714efdc72b1 Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Tue, 29 Oct 2024 13:23:21 -0700 Subject: [PATCH 03/15] Add promise comment --- .../src/surfaces/point-of-sale/api/print-api/print-api.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts index 7b92e010a..d1c7cff84 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/api/print-api/print-api.ts @@ -2,8 +2,10 @@ * Access the print API for printing functionality */ export interface PrintApiContent { - /** Trigger a print dialog + /** + * Trigger a print dialog. * @param src the source URL of the content to print. This URL must be a path of the app backend. Valid document types are text, HTML, image, and PDF. + * @returns Promise that resolves when content is ready and native print dialog appears. */ print(src: string): Promise; } From 0040772c6010b9f184bd274c900099b19632d431 Mon Sep 17 00:00:00 2001 From: merkoyep Date: Thu, 31 Oct 2024 11:56:09 -0400 Subject: [PATCH 04/15] fix typo in localApi --- .../surfaces/point-of-sale/reference/apis/locale-api.doc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/locale-api.doc.ts b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/locale-api.doc.ts index cb7e3d0f3..72939773b 100644 --- a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/locale-api.doc.ts +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/locale-api.doc.ts @@ -7,7 +7,7 @@ const generateCodeBlockForLocaleApi = (title: string, fileName: string) => const data: ReferenceEntityTemplateSchema = { name: 'Locale API', description: - 'The Locale API allows the extension to retreive the merchants locale.', + "The Locale API allows the extension to retrieve the merchant's locale.", isVisualComponent: false, type: 'APIs', definitions: [ From cc96bc544f5a7c9b528d55739a33f3c10e64d1dc Mon Sep 17 00:00:00 2001 From: jffortier <739905+jffortier@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:43:42 +0000 Subject: [PATCH 05/15] [checkout] Update to 8a702e0c1ea83ccac07e2f79c060d23fd68038f9 --- packages/ui-extensions-react/README.md | 2 +- .../Chat/examples/basic-chat.example.tsx | 16 ++ .../surfaces/checkout/hooks/buyer-journey.ts | 20 +- .../checkout/hooks/cart-line-target.ts | 2 - .../checkout/hooks/delivery-groups.ts | 7 - .../checkout/hooks/payment-options.ts | 22 +- .../src/surfaces/checkout/hooks/target.ts | 5 +- .../hooks/tests/buyer-journey.test.ts | 42 ---- packages/ui-extensions/README.md | 2 +- .../docs/surfaces/checkout/build-docs.sh | 6 +- .../default.example.ts | 18 ++ .../default.example.tsx | 15 ++ .../default.example.ts | 18 ++ .../default.example.tsx | 15 ++ .../reference/examples/query-fetch.example.ts | 18 +- .../examples/query-fetch.example.tsx | 19 +- .../checkout/reference/helper.docs.ts | 8 + .../purchase.checkout.chat.render.doc.ts | 21 ++ .../purchase.thank-you.chat.render.doc.ts | 21 ++ .../screenshots/chat-component-maximized.png | Bin 0 -> 31220 bytes .../screenshots/chat-component-minimized.png | Bin 0 -> 19044 bytes .../checkout/screenshots/chat-thumbnail.png | Bin 0 -> 17241 bytes .../supported-locations-chat-thank-you.png | Bin 0 -> 74462 bytes .../screenshots/supported-locations-chat.png | Bin 0 -> 61700 bytes .../checkout/staticPages/configuration.doc.ts | 42 +++- .../configuration/preloads.example.toml | 10 + .../configuration/preloads.example.tsx | 10 + .../staticPages/extension-overview.doc.ts | 34 ++- packages/ui-extensions/src/extension.ts | 8 +- packages/ui-extensions/src/index.ts | 9 +- packages/ui-extensions/src/shared.ts | 2 +- .../ui-extensions/src/surfaces/checkout.ts | 4 + .../api/address-autocomplete/standard.ts | 2 +- .../checkout/api/standard/standard.ts | 12 +- .../checkout/components/Badge/Badge.ts | 2 +- .../checkout/components/Button/Button.ts | 2 +- .../checkout/components/Chat/AppBridge.ts | 89 ++++++++ .../checkout/components/Chat/Chat.doc.ts | 215 ++++++++++++++++++ .../surfaces/checkout/components/Chat/Chat.ts | 32 +-- .../app-bridge-communication.example.js | 15 ++ .../app-bridge-communication.example.tsx | 58 +++++ .../Chat/examples/app-bridge-css.example.css | 16 ++ .../examples/app-bridge-resize.example.html | 48 ++++ .../examples/app-bridge-resize.example.tsx | 9 + .../app-bridge-shopify-config.example.js | 2 + .../Chat/examples/basic-chat.example.ts | 13 ++ .../chat-custom-properties-css.example.css | 11 + .../examples/chat-media-query.example.css | 9 + .../examples/include-app-bridge.example.html | 3 + .../shopify-extension-toml.example.toml | 5 + .../surfaces/checkout/components/Icon/Icon.ts | 1 + .../surfaces/checkout/components/shared.ts | 27 ++- .../src/surfaces/checkout/extension.ts | 7 +- .../style/examples/defaultstyle.example.tsx | 2 +- .../style/examples/hiding.example.tsx | 2 +- .../examples/simplecondition.example.tsx | 2 +- .../src/surfaces/checkout/targets.ts | 139 +---------- 57 files changed, 813 insertions(+), 306 deletions(-) create mode 100644 packages/ui-extensions-react/src/surfaces/checkout/components/Chat/examples/basic-chat.example.tsx create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.ts create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.tsx create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.ts create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.tsx create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.checkout.chat.render.doc.ts create mode 100644 packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.thank-you.chat.render.doc.ts create mode 100644 packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-maximized.png create mode 100644 packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-minimized.png create mode 100644 packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-thumbnail.png create mode 100644 packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat-thank-you.png create mode 100644 packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat.png create mode 100644 packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.toml create mode 100644 packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.tsx create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.doc.ts create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.js create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.tsx create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-css.example.css create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.html create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.tsx create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-shopify-config.example.js create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/basic-chat.example.ts create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-custom-properties-css.example.css create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-media-query.example.css create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/include-app-bridge.example.html create mode 100644 packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/shopify-extension-toml.example.toml diff --git a/packages/ui-extensions-react/README.md b/packages/ui-extensions-react/README.md index efd3a97b5..f0b4a0433 100644 --- a/packages/ui-extensions-react/README.md +++ b/packages/ui-extensions-react/README.md @@ -6,7 +6,7 @@ This package contains the public type definitions and utilities needed to create Currently, this package only contains the extension APIs for the [`checkout` surface](./src/surfaces/checkout), but other Shopify surfaces will be added here soon. -All extensions, regardless of where they appear in Shopify, make use of the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. +All extensions, regardless of where they appear in Shopify, make use the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. A checkout extension using React would be written as follows: diff --git a/packages/ui-extensions-react/src/surfaces/checkout/components/Chat/examples/basic-chat.example.tsx b/packages/ui-extensions-react/src/surfaces/checkout/components/Chat/examples/basic-chat.example.tsx new file mode 100644 index 000000000..90f1e6fd2 --- /dev/null +++ b/packages/ui-extensions-react/src/surfaces/checkout/components/Chat/examples/basic-chat.example.tsx @@ -0,0 +1,16 @@ +import { + reactExtension, + Chat, +} from '@shopify/ui-extensions-react/checkout'; + +export default reactExtension( + 'purchase.checkout.chat.render', + () => , +); + +// This component requires the configuration of the `extensions.targeting.preloads.chat` in the extensions configuration file. +// Its value will be used as the `src` attribute of the Chat component. + +function Extension() { + return ; +} diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts index 4ad30a1a2..b7dca165d 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts @@ -19,14 +19,7 @@ export function useBuyerJourney< >(): BuyerJourney { const api = useApi(); - if ('buyerJourney' in api) { - return api.buyerJourney; - } - - throw new ExtensionHasNoMethodError( - 'applyAttributeChange', - api.extension.target, - ); + return api.buyerJourney; } /** @@ -38,12 +31,7 @@ export function useBuyerJourneyCompleted< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): boolean { const api = useApi(); - - if ('buyerJourney' in api) { - return useSubscription(api.buyerJourney.completed); - } - - throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target); + return useSubscription(api.buyerJourney.completed); } /** @@ -60,10 +48,6 @@ export function useBuyerJourneyIntercept< >(interceptor: Interceptor): void { const api = useApi(); - if (!('buyerJourney' in api)) { - throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target); - } - const interceptorRef = useRef(interceptor); interceptorRef.current = interceptor; diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts index 7100fde56..ae4fae955 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts @@ -11,14 +11,12 @@ import {useSubscription} from './subscription'; * - `purchase.cart-line-item.line-components.render` * - `purchase.checkout.cart-line-item.render-after` * - `purchase.thank-you.cart-line-item.render-after` - * - 'customer-account.order-status.cart-line-item.render-after' */ export function useCartLineTarget(): CartLine { const api = useApi< | 'purchase.cart-line-item.line-components.render' | 'purchase.checkout.cart-line-item.render-after' | 'purchase.thank-you.cart-line-item.render-after' - | 'customer-account.order-status.cart-line-item.render-after' >(); if (!api.target) { throw new ExtensionHasNoTargetError( diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts index f7465b5b6..cede53520 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts @@ -3,8 +3,6 @@ import type { RenderExtensionTarget, } from '@shopify/ui-extensions/checkout'; -import {ExtensionHasNoMethodError} from '../errors'; - import {useApi} from './api'; import {useSubscription} from './subscription'; @@ -16,10 +14,5 @@ export function useDeliveryGroups< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): DeliveryGroup[] { const api = useApi(); - - if (!('deliveryGroups' in api)) { - throw new ExtensionHasNoMethodError('deliveryGroups', api.extension.target); - } - return useSubscription(api.deliveryGroups); } diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts index bea0176b4..b50763e13 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts @@ -4,8 +4,6 @@ import type { SelectedPaymentOption, } from '@shopify/ui-extensions/checkout'; -import {ExtensionHasNoMethodError} from '../errors'; - import {useApi} from './api'; import {useSubscription} from './subscription'; @@ -16,15 +14,7 @@ export function useAvailablePaymentOptions< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): PaymentOption[] { const api = useApi(); - - if ('availablePaymentOptions' in api) { - return useSubscription(api.availablePaymentOptions); - } - - throw new ExtensionHasNoMethodError( - 'availablePaymentOptions', - api.extension.target, - ); + return useSubscription(api.availablePaymentOptions); } /** @@ -34,13 +24,5 @@ export function useSelectedPaymentOptions< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): SelectedPaymentOption[] { const api = useApi(); - - if ('selectedPaymentOptions' in api) { - return useSubscription(api.selectedPaymentOptions); - } - - throw new ExtensionHasNoMethodError( - 'selectedPaymentOptions', - api.extension.target, - ); + return useSubscription(api.selectedPaymentOptions); } diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts index c6995fcfe..6f7f1d579 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts @@ -15,8 +15,8 @@ class ExtensionHasNoTargetError extends Error { /** * Returns the cart line the extension is attached to. This hook can only be used by extensions in the - * `purchase.cart-line-item.line-components.render`, `purchase.checkout.cart-line-item.render-after`, - * `purchase.thank-you.cart-line-item.render-after`, and `customer-account.order-status.cart-line-item.render-after` + * `purchase.cart-line-item.line-components.render`, `purchase.checkout.cart-line-item.render-after`, and + * `purchase.thank-you.cart-line-item.render-after` * extension targets. Until version `2023-04`, this hook returned a `PresentmentCartLine` object. * * > Caution: Deprecated as of version `2023-10`, use `useCartLineTarget()` instead. @@ -28,7 +28,6 @@ export function useTarget(): CartLine { | 'purchase.cart-line-item.line-components.render' | 'purchase.checkout.cart-line-item.render-after' | 'purchase.thank-you.cart-line-item.render-after' - | 'customer-account.order-status.cart-line-item.render-after' >(); if (!api.target) { throw new ExtensionHasNoTargetError(api.extension.target); diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts index 6907b18a9..aeb4f70e7 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts @@ -151,18 +151,6 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourney()', () => { - it('raises an exception when buyerJourney api is not available', () => { - expect(() => { - mount.hook(() => useBuyerJourney(), { - extensionApi: { - extension: { - target: 'purchase.checkout.header.render-after', - }, - }, - }); - }).toThrow(ExtensionHasNoMethodError); - }); - it('returns the buyer journey when the api is available', () => { const hook = mount.hook(() => useBuyerJourney(), { extensionApi: { @@ -178,18 +166,6 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourneyCompleted()', () => { - it('raises an exception when buyerJourney api is not available', () => { - expect(() => { - mount.hook(() => useBuyerJourneyCompleted(), { - extensionApi: { - extension: { - target: 'purchase.checkout.header.render-after', - }, - }, - }); - }).toThrow(ExtensionHasNoMethodError); - }); - it.each([true, false])( 'returns the buyer journey completed value: %s', (completed) => { @@ -210,24 +186,6 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourneyIntercept()', () => { - it('raises an exception when buyerJourney api is not available', () => { - expect(() => { - mount.hook( - () => - useBuyerJourneyIntercept(() => ({ - behavior: 'allow', - })), - { - extensionApi: { - extension: { - target: 'purchase.checkout.header.render-after', - }, - }, - }, - ); - }).toThrow(ExtensionHasNoMethodError); - }); - it('calls the interceptor function', () => { const mockIntercept = jest.fn(() => Promise.resolve({behavior: 'allow'} as const), diff --git a/packages/ui-extensions/README.md b/packages/ui-extensions/README.md index e84b5e73f..6bbd66fe7 100644 --- a/packages/ui-extensions/README.md +++ b/packages/ui-extensions/README.md @@ -6,7 +6,7 @@ This package contains the public type definitions and utilities needed to create Currently, this package only contains the extension APIs for the [`checkout`](./src/surfaces/checkout) and [`admin`](./src/surfaces/admin) surfaces, but other Shopify surfaces will be added here soon. -All extensions, regardless of where they appear in Shopify, make use of the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. +All extensions, regardless of where they appear in Shopify, make use the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. A checkout extension using “vanilla” JavaScript would be written as follows: diff --git a/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh b/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh index d65549413..59e246a1c 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh +++ b/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh @@ -22,15 +22,15 @@ run_sed() { if [ -z $API_VERSION ] then API_VERSION="unstable" - echo "Building docs for 'unstable' checkout UI extensions API. You can add a calver version argument (e.g. 'yarn docs:checkout 2023-07') to generate the docs for a stable version." + echo "Building docs for 'unstable' checkout UI extensions API. You can add a calver version argument (e.g. 'pnpm docs:checkout 2023-07') to generate the docs for a stable version." else echo "Building docs for '$API_VERSION' checkout UI extensions API." echo "When generating docs for a stable version, 'unstable' docs are not regenerated. This avoids overwriting other unstable changes that are not included in this version." echo "If you need to update the 'unstable' version, run this command again without the '$API_VERSION' parameter." fi -COMPILE_DOCS="yarn tsc --project $DOCS_PATH/tsconfig.docs.json --types react --moduleResolution node --target esNext --module CommonJS && yarn generate-docs --overridePath ./$DOCS_PATH/typeOverride.json --input ./$DOCS_PATH/reference ./$SRC_PATH --typesInput ./$SRC_PATH ../ui-extensions-react/$SRC_PATH --output ./$DOCS_PATH/generated" -COMPILE_STATIC_PAGES="yarn tsc $DOCS_PATH/staticPages/*.doc.ts --types react --moduleResolution node --target esNext --module CommonJS && yarn generate-docs --isLandingPage --input ./$DOCS_PATH/staticPages --output ./$DOCS_PATH/generated" +COMPILE_DOCS="pnpm tsc --project $DOCS_PATH/tsconfig.docs.json --types react --moduleResolution node --target esNext --module CommonJS && pnpm generate-docs --overridePath ./$DOCS_PATH/typeOverride.json --input ./$DOCS_PATH/reference ./$SRC_PATH --typesInput ./$SRC_PATH ../ui-extensions-react/$SRC_PATH --output ./$DOCS_PATH/generated" +COMPILE_STATIC_PAGES="pnpm tsc $DOCS_PATH/staticPages/*.doc.ts --types react --moduleResolution node --target esNext --module CommonJS && pnpm generate-docs --isLandingPage --input ./$DOCS_PATH/staticPages --output ./$DOCS_PATH/generated" if echo "$PWD" | grep -q '\checkout-web'; then diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.ts new file mode 100644 index 000000000..b55e0ca25 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.ts @@ -0,0 +1,18 @@ +import { + Chat, + extension, +} from '@shopify/ui-extensions/checkout'; + +// 1. Choose an extension target +export default extension( + 'purchase.checkout.chat.render', + (root) => { + // 2. Render a Chat UI. This target only accepts the Chat component. Any other components will not render. + root.appendChild( + root.createComponent(Chat, { + inlineSize: 100, + blockSize: 50, + }), + ); + }, +); diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.tsx b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.tsx new file mode 100644 index 000000000..eef12b7d1 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.checkout.chat.render/default.example.tsx @@ -0,0 +1,15 @@ +import { + Chat, + reactExtension, +} from '@shopify/ui-extensions-react/checkout'; + +// 1. Choose an extension target +export default reactExtension( + 'purchase.checkout.chat.render', + () => , +); + +function Extension() { + // 2. Render a Chat UI. This target only accepts the Chat component. Any other components will not render. + return ; +} diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.ts new file mode 100644 index 000000000..e77c25bf4 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.ts @@ -0,0 +1,18 @@ +import { + Chat, + extension, +} from '@shopify/ui-extensions/checkout'; + +// 1. Choose an extension target +export default extension( + 'purchase.thank-you.chat.render', + (root) => { + // 2. Render a Chat UI. This target only accepts the Chat component. Any other components will not render. + root.appendChild( + root.createComponent(Chat, { + inlineSize: 100, + blockSize: 50, + }), + ); + }, +); diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.tsx b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.tsx new file mode 100644 index 000000000..df712285d --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/purchase.thank-you.chat.render/default.example.tsx @@ -0,0 +1,15 @@ +import { + Chat, + reactExtension, +} from '@shopify/ui-extensions-react/checkout'; + +// 1. Choose an extension target +export default reactExtension( + 'purchase.thank-you.chat.render', + () => , +); + +function Extension() { + // 2. Render a Chat UI. This target only accepts the Chat component. Any other components will not render. + return ; +} diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts index f132cdaa1..d7cf051b0 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts @@ -6,8 +6,7 @@ import { export default extension( 'purchase.checkout.block.render', - (root, {shop}) => { - const apiVersion = 'unstable'; + (root) => { const getProductsQuery = { query: `query ($first: Int!) { products(first: $first) { @@ -20,16 +19,13 @@ export default extension( variables: {first: 5}, }; - fetch( - `${shop.storefrontUrl}api/${apiVersion}/graphql.json`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(getProductsQuery), + fetch('shopify:storefront/api/graphql.json', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', }, - ) + body: JSON.stringify(getProductsQuery), + }) .then((response) => response.json()) .then(({data}) => { const listItems = diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx index 0a8dc709a..95649e813 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx @@ -28,22 +28,17 @@ function Extension() { variables: {first: 5}, }; - const apiVersion = 'unstable'; - - fetch( - `${shop.storefrontUrl}api/${apiVersion}/graphql.json`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(getProductsQuery), + fetch('shopify:storefront/api/graphql.json', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', }, - ) + body: JSON.stringify(getProductsQuery), + }) .then((response) => response.json()) .then(({data, errors}) => setData(data)) .catch(console.error); - }, [shop]); + }); return ( diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts index caf8663d9..2de039224 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts @@ -145,6 +145,8 @@ export function getExamples( ...createExample('purchase.checkout.footer.render-after/default'), ...createExample('purchase.thank-you.header.render-after/default'), ...createExample('purchase.thank-you.footer.render-after/default'), + ...createExample('purchase.checkout.chat.render/default'), + ...createExample('purchase.thank-you.chat.render/default'), 'analytics-publish': { description: 'You can publish analytics events to the Shopify analytics frameworks and they will be propagated to all web pixels on the page.', @@ -337,6 +339,12 @@ Ensure your extension can use this API by [enabling the \`api_access\` capabilit description: ` You can access the [Storefront GraphQL API](/docs/api/storefront) using global \`fetch()\`. Ensure your extension can access the Storefront API via the [\`api_access\` capability](/docs/api/checkout-ui-extensions/configuration#api-access). + +The \`shopify:storefront\` protocol will automatically infer your Storefront URL and API version declared in your extension config. + +By omitting the API version (recommended), Shopify will use your API version configured in \`shopify.extension.toml\`. To change the API version, simply add it to the URL like \`shopify:storefront/api/2024-04/graphql.json\`. + +See [Storefront GraphQL API endpoints](/docs/api/storefront#endpoints) for more information. `, codeblock: { title: 'Accessing the Storefront API with fetch()', diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.checkout.chat.render.doc.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.checkout.chat.render.doc.ts new file mode 100644 index 000000000..59e71f8fb --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.checkout.chat.render.doc.ts @@ -0,0 +1,21 @@ +import type {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'; + +import {CHECKOUT_API, getExample, getLinksByTag} from '../helper.docs'; + +const data: ReferenceEntityTemplateSchema = { + name: 'purchase.checkout.chat.render', + description: ` +A static extension target that floats above the checkout in the bottom right corner of the screen. + +> Note: This target only accepts the [Chat](https://shopify.dev/docs/api/checkout-ui-extensions/latest/components/overlays/chat) component. Any other components will not render. + `, + defaultExample: getExample('purchase.checkout.chat.render/default', [ + 'jsx', + 'js', + ]), + subCategory: 'Overlays', + related: getLinksByTag('targets'), + ...CHECKOUT_API, +}; + +export default data; diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.thank-you.chat.render.doc.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.thank-you.chat.render.doc.ts new file mode 100644 index 000000000..15a321a40 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/targets/purchase.thank-you.chat.render.doc.ts @@ -0,0 +1,21 @@ +import type {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'; + +import {THANK_YOU_API, getExample, getLinksByTag} from '../helper.docs'; + +const data: ReferenceEntityTemplateSchema = { + name: 'purchase.thank-you.chat.render', + description: ` +A static extension target that floats above the Thank you page in the bottom right corner of the screen. + +> Note: This target only accepts the [Chat](https://shopify.dev/docs/api/checkout-ui-extensions/latest/components/overlays/chat) component. Any other components will not render. + `, + defaultExample: getExample('purchase.thank-you.chat.render/default', [ + 'jsx', + 'js', + ]), + subCategory: 'Overlays', + related: getLinksByTag('targets'), + ...THANK_YOU_API, +}; + +export default data; diff --git a/packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-maximized.png b/packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-maximized.png new file mode 100644 index 0000000000000000000000000000000000000000..ce98baa0325ebf9be3a2cb40b19f3a19a427aaff GIT binary patch literal 31220 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 literal 0 HcmV?d00001 diff --git a/packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-minimized.png b/packages/ui-extensions/docs/surfaces/checkout/screenshots/chat-component-minimized.png new file mode 100644 index 0000000000000000000000000000000000000000..40fd4e8388503e10d9b507754681c1f84b4f42d9 GIT binary patch literal 19044 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 I&}V`FAMZR(^b literal 0 HcmV?d00001 diff --git a/packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat-thank-you.png b/packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat-thank-you.png new file mode 100644 index 0000000000000000000000000000000000000000..fe544aa1bf27da2843097db926208b9b556a38cf GIT binary patch literal 74462 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

jBAeO3kR^v5gKPWe zC@mou`xkq8fd!I$FkpVI_`CeRNOgTN2;=9G;^&3?uQ;z<=VBakh^`M!=VwA=C8k$3my}djdtE6V zjuMwqNlZUA-hZjR1}h}F_^*}3xMttH=>;C*3{u@$9G`bl+X3|TG0#&Iw$awXVJQvn z2%j`yd794!3!wlzTWRf29zymSOgT9ap@7=mUxBg^GQ{*&%8TR0u;Jt61iy&&DO10l zoxRmJHCG>OtT&HW?2Q-kUn#M0J6j%k_lFj87 z+u8ekhaMwZsHvGhQt!h2caawM$rPrDQU6qnOuIZrr4lWP)8hoErbl=B1Z|yS93oB0 zEOr84i^9t;op_FQu8W;)_9vYhJjwcKgDdZiYgBpx0*yw7t!=;mGjv{r`o@kH#qtbC z`jjH1T@=GZt`Ds|(-lzz|5PNRB{vue! zt;=IZ2I`}?R#KWn0;36KCbNTfrVuLSy!jN}&^SZw&CsYUbGD@usR-D-1j+?&HhP8N zngs`T2~Fv|yOP-FA+!CLfq$~EVR6`5qlP$IF{-SmNl@1zDtp@@Me|9SDfFT!84pR~ z7)d|AE%>$5>C*IcZX??!xR{amd3%M zUjE`EfQ7}0MDG-0={e2^_l?RQ<_I(CFe&sZKYsVo(YiTP zP9x7Is_{8Lc@Iy+6jKyp$pij)3Su*Q#|QRoG^o#1z|NX8p$~tOD{wRSe$=ZD5co3XLy!SaW?k-^=;ZZoVX$;JVYq_r9X*C{Idhw3*AS zL$K#s;zrgDqmZV7=Qo<6W^*vBgLi*OK;Y?@9i19z>uZEa;-i%q+9Q{-48x$&=kU_{ zcCMy-HaM`9_7vigiu*fkmqugW%--O(>k45?vFu5i(O0INeSKJcvRzbnNpsi{;2dB(LUO z!+f5sNKJu3@JxVf;n1r)D*|^d91&2EQJF#KDDTjru(pT;$Hkjs2gQQ`oxheB^sNr` zl31L9*vN@p@0TKLvdqoXp2zb2A$2L&XcL{nG#OBSLWlajj=QE@>2ddmA1zF7b?;T# zKGSR5K7!^YU*|{fX7Wif3;8l7OAESBe9rC^(0G|Ue&*=)`8X7lIwpFH6vLBQUp

o$u6@Kw`&&4IBo)&|^rBb;$MAw+8n=u-9nf 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 literal 0 HcmV?d00001 diff --git a/packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat.png b/packages/ui-extensions/docs/surfaces/checkout/screenshots/supported-locations-chat.png new file mode 100644 index 0000000000000000000000000000000000000000..47cebf2b246de5903cfd7431a6a6d191f450299f GIT binary patch literal 61700 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଒ zxFXZj(_;)a;VWnrRn=|izkOInPa%4+%BrgW=HUR)ABg{a__v_{^!jf=|LOJrS0CLa zN50>R7xWtiNYCL8cnY`w)9sywhY) z4FE{8QH=ID-N@;WVhzd7|Ha)U;4Xdq_roTc$-Mp7D!utOT2CV71J6ml3oj7$OS#`C z0lC;(`c42Q0%LlL_=aiaZ!#DBbSsk8=tg+;i;@#B8Qm2l{XfL0PeHrk+2~x;NeyN> z`Hr2P@&FR|3Z(*y=s$0q@S)H^R;JS~V%B&F>yBze7LzUY6!cs@<_4obr<`)@u{XEx zVFz*CZA`Qf&0~boO+oL9Hz*r?WKH`#874D8r=W7+LYr>{0CIsS68BTK z)P!~ctUd5R&D7l-8ivPZZ>PzQ?v0oHjlUVx3=IvJ%9V3> z1@Rl@i};Pz@$vD+i3{1Yagiq9T$a9#J@P1YSR>nL3YVcro{^e^zIWfu=V26Zak}=o zcs_qLIi!_)c30yF;a!o?43aj*7=+p+IV_M^Cs%H&bZ18$x-o$FJJWL9-1z)U#x%Fm+tt zHc23&FdKm2Z}{;tDcx36OINE}{poAhs#dX`ot-`(sYtQJ-l4bTUY|RnX8{9uMJ0XM zry5jn+`i}IH)*GLKNh#qDJgG@xDs=}p}z(ftx}J|sd$l-rR!f! z(Vy>^*qxc(nOU8X$y({GrzxNF^!d0zf+gNi%#Hw^;1eMO%(%-QPn zsTYQwy9%#d#oBAd7oTs^53m}~e9s+nMmYy$rZupd+S!P4*QJQTes%)o2%j>CD3V7lha~AlAc__Q7scG5GmO;GF#~Yw~x-ew`UoYyYxA_ca`=ue5XTCi^9@$(-w10hmuX- zr?i8c1P_M$k$gA~=H*azIrr^%&2Q)O_2uhDy>pD(l5sA4CY_&rKDHjk5x6j_)T_O{6^3BJ8mqbyO#Tx z7uoy@>K7T9*YUnXigmGFUBKW)`pdT|E6hhWm%AT{lq+w(aLiug1XH%RhLpE`MCaXi zrx-W;|0T$(eYFru$nrPdEscpDs=00Ri(TUJ##1GdVb+CLLz7%qv-Xg&<5?4t0t zua#IX`~2DFuDC5QGF@ZzF??4i2>b)C?GuF=NV!fHF$Y4Wwl*8yZZF64ZOT*oqMMwr zO~cz2+JFB1+13^$q9!rnckNYx1Fv$j*^QugoU!(EPFMd)31RCzU7A*k)S+{bQSy#c-_Vjy4VARZ*9{lERH6;q zlb9|hX3dZZT(*&Lv@!5PCoVwg!WJlXqBR=zOoSCGu-PLaoAEq*qXgWW&X_Y$T&5`P zu(NK(u{B~4B!Zy}y{bA7#Xa*7Dhy;VR-bh>?9De7@=u5eeI=@kSs1JPq|9uOJeu9^ z&{&<9CfblT>AG-!<0oDR)(;6GK3SJpi|6DG_<=qSk9@|c;YPbHE*W9V2d=XutPW-0 zk26@0U`)gkvJiLs-F)JC<|mO<(KS;=XhbC6yT??VAk;l z@#-j_qLRqws7mxmBG%R9dhtV*SMhj-?@SdpQ;1{CPE(V~PSl8kJ8xp`$iRh(_S9d| zDk8%o{_UW?wRgiY9(zQ8?3>K_Q8??J%J&1-JaCn$_^VvTXB?;Vx)kynats<2 zOq4Y=G^lC%KuIo2t2yX(gPAfJh;x;Q&2mKaj zl}6x7Mav_%e_mpFr98VXqE21w6z+cN$~Q!?wptiT{m*{U)tPSBT2+OS(*sH~2>IMkfWrP-VEl2wt}9QryYEd&o%NGR0D{ z!d?%5Fc_9^%qUO1dzW9~E1Nx%QYhlMMz=CPsK73TsrZbp0yR$$t<&Q>1p)GU+NLFO z4nsf6gRE8MtvY-QZVF_!Uv=>|u-5l86JHEE;%d`%cbbbLsdyv4e=DHZD%dU1{F&sc zZ<>Nbfr-}Chxm6d6PU^hB&qIjtV|2F?sl2wz8A`+8{f4qcah;L(q?UX_ukd;`hm(y zv;N-lwnV6q$CSrfydk?S3p%x#QvFuRANu5>b)rw>r(JCI`?JdzS!DR1)<_taX-sl| zvSPQVey24NRj&8l&E|d&B+s_vrz1knc+CC#OO|c>{`{Iak@{as@ztXD3uD_ADo7iP zNjPrqMCX3(UTXOU@GI11)sev@e?hXCB;vWpnI}qAvCLF z8CtQdxsLyROSy{5Of6AGT|>i0z6>UpHMM++F4ScB-OEr;qZYn9rB^?|k4M*hRmM97 z$|IMm6kU!4Ya2`QX}MIH3dfpFzh9EE?_hZqAGyKK?zU>?RU9Uqno852K~)icrLu2q zCNH|?{`B%$^D;kRiiuLdP<7E=Q7So!OvM8iV~d%}*tJ!U=6*=U26TxqtJbBgv9s?& zL?WJq31m24kYmzme1;U>)Xp^E5obcb`0iuDE3mAn;F^Y}_tjQBa%hs>`;O>xP1LDc z5Qvemo;1NnJ6C}Xr(X2VxzP7A3gu}H_DBV}>@K0(`KG;{BJM}AgBM>XS{ifw&cTEO zg{i{%e59Q!-NXi&s! zrZ>O(IE9XMA~{W#Qu{zhs{Z@6i%-+691jJg*zm;owom2un?4z>qRG}YRM&mSg>--V zTl}!#3mQ9#(fR?eukHz|PV^cHb^y{TbXJtYW1KabH%MTrKsUTt+W^WTKG(3*Yf~xq zZFGIpFRnx56w8Z~!k1M1>>2dt6cx&CzE8#bjnk4>R@x)W^`5ILC%!K#VrOaNUmEYy zppr+<3H%Nfo?Laj$+lDMqUp~ydepu2Y41J3+W7LQOKkQe zY~iw}j>C9-ZQt9zG5ViYpMra!jYP@s>t%!dke(-PPdMnFd1cny@>|0#@ncTQ{Ko8e z*Z43~nbv!bH%}fQmvn=d%FbB4WDYD1Lb2FkHd+yxi(QaO=yA|ODOlme+ zi8lSE_`0@>$aWJ)RjR;5tt+y~<~Th~AD(kJV5lZrQ*_^Y`Lws*sRjz~L~aE|$#V9Z zOB83(?L`?TnQ)t6!d=~aW3B(_{}QFk3JdG7tTfO=7oHG$G4`$okHxKTl6`=a&qEm) z7y$7>@tkvP#^=%*Mgtc`2QrWox5XLg0AhawLNjy-goUx%>ds5)g9SyV-RV5>5sWe6?MRxyq(2PxNd#V1iCRC ztNT_y;b_tzg@#{@ka8YZvan%w4w+My?TnQG_W7oA;4|dlBz*YJpf|h}!7D(%Hv@Mn zmGO@XtV8qlt~7^fJnX3VYvLS^T*>IhYuwktWg`Nbcw;=n@l^f1=g{pvvt)tVEk#8J zy@szII)9NSqpW2*aj2eLzmtXfX5?LSecsUB%hNoFU><(Fq*sw+xFL;Q;e_AA z7KuQYC zJfrtDV+f3RKSTRNR55J>+WAJn%}$o=~uHSzb1jc&L;^iyg#|dX<7|S{Hx-`KFA3saM5Yl6A-@ zI#L)u&4l|-&0j=Gzj`lIbHg>wYO5|T{$fAxFiN(Pq#pFkgc+nc|E0Z1b`IJ>y5~&l zw@0MCNmOr_=AY!NptBXq&`Y()QdL9?-5Gi!}Zw<6w%sUG)k5AT8d2h2VeY`&fKN zp^4ZN2fFTfIvd*rGkIXri|D)JYyye55>rxS3LY3!K2QZ$+ThS(fz*Yd+WPtOEPP9lcCX87o{Mxv z3!e7j@vlAI$?4l+@mbCHvd%R_k{qtoI|U>+maO_u1m~uD*X6DgbnLxBJD8L1fXV$6 zuCkeht0S8e;*Bp0)@8Hk7}|dG0X8T2YQWczPm;2{Y{ce$Y{aJNLo= zRNFV<8hdIh8iHX#GU0HvYEA?9E&$q~?W{d=0(hK(YqUO&Osb#S)2Y)qE40=5OolGT zie4+24<)AvYvY#PS(@b9yopnDJFj~mZE}18?XHR5MUsWsyyYFXYx4}!j6J?f4bf8JK3pcsP2Se;ADod7JEIpFrZ%BTeBeZ!e&Njv zosjy#qxW8ilHa&rKP|x|y+r01M{q$ZO!kdBK@n=}Gv1TfY3D=}42Q3c{Jc@^8(NEO zLQ^AL21kNLzt>t{yGB(0zPk2F9P~3~66B{Hw6(@b)&ko8u*S3{X}2dnCTwA z_9OxxrQhi@0p}-u;>Yr~(`o62mUoId=zDS}-~Yr1sHNEmAB2l!qyF z)`$s`n?$sHmDQDp$DYt2agR?SqTZCucN!wE5^S?~%pfDv(?Fp*MoYXG7>Lyd0oBv0 zSxYPLjWuonQ|a_8_|CJHg~!ywUi(2VQ3@br;#)(s_t@$NZ6@ehUh z6{UMu74HFVUpafSkZV^N0X`Q!l#I+k!p5EhI#QdirY(1J{?#vHl`m3tr_WIy#I2+V zq1Y=C5?hra#teaSX>X4eo+u6TB-c7v@fhrFj2b8CI_-|PT~~e6l)+e5JTdQL3~3H#oP@9nYiY4=o<7l2>&}H zPeEcxVo01pFdj=RiAVoNgG`*<0vs~tOzliP2SWS+N;sAnzyX1L#5l+Veg$v>Sl6Kp z5CZ5u;7Lcm0?;ITz^y^L?>B&R2%G>10M8+H$G!$|4xtd>96~ujkpSfoMFNz6fnqBW z0m0XMC<;Re2=1W>1Hk`3pg0Af91fHKg#br6Ffj)3Fo112)kkDFtPQD~r)QS={*ahF z*721aZ*yV>iMfgPm45bFHAqi@PQQ3B!!6g6f_5|KeV+~3c19_>>-%28e@dwW|gB1wWaQX z>m%y#b=iaR51z)a3j&tjsCS+B-LS9F6{0VuYM%pSz<`uvJ#5v%6oDlBqj%lJ^# zUBZ`^%3U@@l5`v8{%EHnyYv87e=kB$-!X&o6q2~~^bbr$t(WC~X8!pR^5{g>>0OJY zyMaqXyJ0N*h`qQKnFFPOj9R(4Fa#|u^^nN~j=pf=9ch5>V>j=3+`ahokc>8^T%h)h zUj9C`8^vX1T#zt5{hrxX-rH{r1h?!atUOuAXP`6XH39qhEx1X7G%eBBG*BwGrrOj@ z$+7q&E7lXoG<0+yw4AN6QExuv_nI3GIde61YlpFmMn*ziHZYocevXbK8w};L2yDXy z*2XVW+)MmBuDLKvn8KRdh^4{-SbUpyzd^@ z-8u*BJe4(+av`R|Pv&*q{lLU=Q?pt!k%1WUZG*Z~gd{cO=(by*FC^*w`oGLpvw{{% zgk-fd*f{|CTh{t8`JJK!-Z)bezCU z@BIf9c=NX$dg58|%ioZ(2GZa+NYMun#KPXg{~)tZB7Sf>fIyIkQ+>Q9z3Q}e16iL` z^=@<~%y#=NT=8A*_EXP0CVVcF8&w({ze)AE0X8y8uk^vYa&eBy^4mPu1vh#IQ)58y ze^Ux#uOvd(-;eDy*nsx`>X6KTeI&;m_4mRF!2r@fPWK3+l!gRPRhbLY?>JCPIB%`Z zkB=K&B|7XaHD<5<*pD)3P;bXa;Z9Uq8Wy zVskYqx_Vg&BeuTy=S0;-FeGxO?xFzoQHRg7(0YEw^|U0CgL6_nry+0Q5v+HSq025Y zF^uVxP?L3ToMQPsy2EbF!;&V8lO)SOvq_Ae-CdUvhW+Yj)$|!E+&{7grs{=Md3e&` zd5Hj}mx$mG7%J16^IV5B`*lT|uU&I$bu&p5b7j4S85}V|)!gcXH>MLwx=L}lYNu~G zT3>O!G6fw$=qDSggHtL+y@W~_shz9alV(xda|2br9RAm4zcuL`hX^Y!wxCPus$n4@f=23E}LoaMPJ#i=l@bXX;R@^uaCli*_5l26=YRyPw}b zigs&=0yHak>3xiNPp8}sA6#p+R}7BOrCs2Rm+oI}aH-MR0WE|ZG@=NL5DcbQ0;~La zvUmgoc1!LZRm(S$fT*pnFXDB^q4-6IG^+bY&i}$Hr<(PkAhD&MLp zDlX0)my6b{kP}F6B0gM{*+NBuxu%;xLQjItAYd;rKb?#^AjHlNfr9qSs)a)4?YkTN ziXA96H)xFaUrWbl>+xvc%O^HrY;^%2Fo8je8?1k3Y?P7V2X^X2Rd%otN@<-Yp{v~v zX=28{FvxtcW{93TEqn{k_d-}y<>{*RRhhe^Dz&VUnU08!z)Fx zAt-|ovk2DRi(qOAT!L(Z%q=y)EHH^4`FX=n&m*u6Z4@z>3KO;Zo?fuI(x)ds8i)RpQ8H|94Z>@o$i zLD-wO;i6vqdC9k&X+M>nG%&!xGZFR%&EdV{)<2$*m0>~g7h0B5p8kH@+AqWaR%1G< zCd{*=Hb}>HePoXJTEF1QQv;Xi3;1?N)rf%jGX!QrV`ad|bvfe}!YMhRsc2C(W6-kI zDmLTZhLl~K7V0q5UQNkFupb-(;jyMpK+~c}<#sSmIk}zD(a{rloeHVh?SX-TZ0SDz zRn6uDC}YstPl)^aMwzM<-E9;r?MTPxOBV<=hX?}%eLe%Fc{XA~k9S}dUVO9={{+B; z{WW{zVM4*bYfQHZ=p&b3?k^$6KAA)w$SoDK)yb@i@}c;| z52vPOwEH22bho)!%sT2RuDES4KiPb1+FQwCoYhVY3Wx|}GV`QWDD3U+Q(2rdO9T6t z;?2@e*>4t1GI1VsgECM?jbO}fh4-|!s`u)swaRT?M2*G!on;JKvO`?ZYnR*HA!*Nf zG#t^a9x3!(sBj5~SXnEbjil4_puFMsi9oJKlr6O$GQdv%*KZ6mJ6O3QLhlj*jL*R+Qz?n(U& z^Jmx;f%!pu=Iu)j5NSzX86Q_D`Y|?EYHNS{66bhYDcg)q;`7)>8k-%m{@sI^ky|JO zpMc8^BWVUcyqhOx-|&4vr@ls zQpOTdZ-z3d!FIqaD?Vf|Y($!z|FW>=wGq)t@QL;q--7Aa#mG+*LMV@me#1M)%|h$^ftDZl51s_<(i-kQCyWsoT4_WN#i1^Fp6O||z*{S07S)q)nsZZMl~hVlEg3x=zhoI@qKf8R)kGYQ zgbnfT;tM0Pn<=feo3`b_^<0c)s|Lcboy6seDc}cA+FU>U@E!s_&>9zt?&Pgi zs3S{CXq9v&S1z}j#^BE29A9Aq-2`43hF3IRW5R9kzF63pE&7X6LgWgl)VG#rY{fj5 zJ#f5kWv%ikwu+&~m6$Ezjz{1!`BfBe?cg7(dDq`e%>8?Df?0YV+pGq0}nVz^!JQ-F`q}z=a-9RCh*CHF0|MBZi3UNX^W=v3$vr@ycX51KQv5)@;syk zYLC~6GOc9)9-6l=7yC0kI!CDTWpg_x@RPqvBJQF(J7Y|qNPS=#*b=giQ8S(x_!hS? z+yq_ifiEydm3j&9tUnf%*jnbj*DV(OI9fouY$JIGTjI~_SEuJEvi>3EnxKf^`9q~^ znT2I6MjBsvqS=^lnwhs@CfJLu8D2rL@mxv`Q_gzeIhbTVBH%JTEBttZl38^)1b+ot zkruch|B_9JVpNZ0f5-{wU){7UX5L||BMqTe;T3w{t4sP#5#wb{wkDZcVnM3@_WeI3 z+;*G`({Y<4q(XnG$q{XyOXQUu_jEOG%W`%3LRWvmTYZgebKkU$^A};C8;vl zU$I!f^~OZ4^7}pY;k6>}R~JDk;eSU9!_tO%+fF&o7Abi0T*-1SZdP=Dv{(mfgY4TJ zML|Co%K7jcnZhR-^|st>Vmj5k=`Bc62I-G;J4gLhO)_2ATsSFbwY8vGyUVsIbBbEa z!0loR4M+I{L70^}UiHqlJfr!n13xa+lrP_nYPRo8Kj zrs+!+Ql=_KncLT2mC?tqhmbCFuJ<=4^{af`RVA2b`$m#wg;L5R)WxoFQ&er&t+yLy z+eNF<0xp_;v_rkj93?U zYjki=a8=X*O6Z`3@zaF=sydIQGoau9VhGXsf9<+fkO^e>rmT)8tPZtwL{Jr8X54LLDBnk~Sgi;*ibSwB2IbUVq?> zBrx`+oT$OFdK!^jrxATJWv@n58(jXX1c_Mf+S*Sm@M`zSXaQ3uZmoTg(oDtvjBD97h&AV`NR{H@qSMlroenUWNuI1{|RToZ8@@0neB$hwdY4;O5r-CFnAQ2=Y#M zr)H3dY~$Zvk^+P@fh0(JfuKyoxdRp^@Z2Skhyy_g10dlD%qvTX&zyFqt_K-` z8^F^dqz^z65FGOq_a+?W3kN6=atmMoX<~##Q}d$f!?G+5 z`&X~m(2|zUC7nAZgeQW`#uJuxG8&qi=f%b}_eoLys_2y@f{zZo^u5%^I8?adL#Mi6 zHEj$o07Iw&0r|Se3;B|W_q;os`M6EQR(y#j_hz|-Rz*B;{DJB+-xFyXvFOC$W1#pD zIQ_dPw7|um0K#62IhMU5W7^38;NB0{_i`oMjKZ+YoA;A~gLvg?bfIG?$lWd? zvDJ!uiVWV?8vJPgszw zjfm{y545NUec_Gga@lTlxw&pGE@e|(t}|w*OEQ%%$v-ikyv{r#S3gOL&^ITObL=j% z7Df$HtsRNx_!(OC12cSkgvz;A?m{ldOT0s=7**p~!fZi5B{V5mc^}mVHiTT?LLI66 zo6PhIsFN*;P?m*Ys9WqgskCOK6%yPYYRY!OBS}UVp*%Fr&4h=ZspAU@xy3@(ycjqh zNuTTUo#94)w;r9+>_rQt^F8i$DbCsCCIw93z`{9kG^s?igzJ{zpn})t%JfCjC@Z5Q z(ky2ShM;|sQFpHRKmBGV@E|5OJ z#0M)=atnF0BU*Aj1JQ|(<(4gHvMI*7trMo*+Di=6auyyx5%-ae2f_9jr!l3$`!w+x zf-oB27EtQi&QmkGwxhgXvl5fov~DI~Qn(ln=4Qu?_>LG4(}*OU zCPS_g6}kEsf83W=y^*`g5}|n;1`;54Gvb%(g6q_uPt;!$iejVW4n0#-u)=W)502`c zPGW_KpcNHo*n&UN8# z?9D;hX5}O%a`pKL|63uf(Jpqs&M%!6sI?mX-5OTDebns~f++OH(3FEe30d>W>!cq7 zRQbky-;iyqT=zaL76K5chw}@0Cu=ba!9INK(jy=JEv&Dz9HN|{j85-~o%8P9-GRAZ z+?Z({aK;2?tQi74>MmTPsS|?LTrfQPK|vPs{ngV@q1)bqs%tY;R^+a6$m}=Y*tkeJ zlIlJ@X%nO<%w2D5vhNfQn?8Y;6u`tvnmYDAq_g7w7LlwpJ0-NS{X$v(DjT8&kiph- z7z+KoU3_YMFucKLjjes@>pKq>&*!`Tj^YS8UsB$Iyt}^@o#YuD@p2- z8!72hV zWxIO3sjdGi;oe8*e&b{A2pL9JOi{bH6DE+G;lYkrJA0c0Vwo)eAv9JQ> z#a`ZDqMWPt zL_m@RfkA@Aksvu|i6Tm75P`t}2qK~kISV3TfI%eZjO3itzX$w%e`)vCZoS=l?^Qjj zwC>#7_w-5KxBK+zPdm|=-vN|0c>Xy5I`dF-D$mtlvmnUqAD=LEIbu?_OHrY97E)ys z?C>;+PjwPv7`mQ8uDca1hc2Czo3tPaS~Tf2RlvC?>rCfJL}2?yLe!Wt8&eUB;s;|n z)MID5r8(7hPI$zI(XRqtN5t9@my`2Fc=N9Zsg`~nVvO^7lX0jQj&yyC^@@GlrByw1 zrBe{luTDV*;(;^Aqncm^fzy;-vobvJSny*C!Yv*N%nTgu)ZJ32kB+4BcixiE-P(!E zeJ3fN&Vz*ZRlgnSLivwUom6AQ;NvCs0^($n^&ejvc{yr}al$qKc*y|mt5k*dID_(l zM!v+os`TK8-IsGqm6;Rq{UHFHofq)5 z+C#(3Lb+AZ?qs#MB2hv)nQ94rd^4hC7Gn5$R0gj6jA*AcZvyi4F;~q(D=GUwzwEg5 z-J>KB#mzf}pA>mRoa{m&i(vL3u^4(Em~P5|NXrA9T}J67DTC74-5V_k&%HuvY+UPKCBVuH; zvVrskU4B%ach@b~O^cgg|I|x-Y&>Dsy^{JMmFHgD=*_;*>7^cmUBB!&;BzD%F&-mC zrWv*7eb=9&QsrZ7l8Art)~!8{JfUtcfIdzo_uF?4UvQ4R7q)OK%^C3Kt3~rQx{je_ zW!o3g{?sV0aIp5i!~==?irm#p=PIyYo&>BnJs!9ihho;#Q``_&ad`IIdvQr)=~f)j z+~SkxU~@`QiP3cXEX1fNOH8JMUZ&#ytkDf%PyY^fM$f!+1Rrg;rc*=f`@WS8j=Hsn z?|1GQ6>eN8eteTlGH%>S7W*N&*S>D}$1^hpT6KFh86O|7NZ{M_w}`KnsfWI5gVC(& ze0(TtU^HEq@X`gbC->e0rwi{Rtrxuu!an$3g7ea_Gva=naZCZdJYwGE;U)Z*F8aF( zXI6nmSYtn*oba5_0M+@pSbt#t^Hyr+GCzlnV@IgjP%fUsd3b;7VUzswlT_5F^OyMK zb9ac1W{l4lzD9kipI(x3p(_oYl8vF8!tpn+{oed{gEYg4Hb-+eOCmSMjqHC!P1D#T zE}p+EhB_QS90f-^FxR}V_Dy}#fDvP!{uUNuK%4sXiqsJRY{ zafsAnGZ5k5PBw3+Xv8eVYbDjb*<5a`A@D3!4<5oJPOYy{Gd!NTz8NenkeT3(clONy zd|aA^Namb;^&q|!<>JH;zH;)sx*}pS`}uro&K;dQQ%o<7Ab}ng*3f9SbL6$22O9VQ zh5#gs!CSFV1UP{>l98t=Z}`{%o;zJL$o>L=12{Os03872c_GNZfFL43AiyTB!5)DL z3jiI!W`D8ohRvP$_nSN+1KUr~3RKQwR;1nEp|+*B>R%K_t=TpP9gH*5TB8(gt}&J}`tONOp)a zMb0i~_Sj(k#T^m-bH{H-n7kfLznSaBqK461-bJU`g6PJ_d2T{}qYhwddVR>gWO;hc z^DL2a+8mmWSjHs4My+oN!g2oP4V$SLyQ*5DsF&DOMpfzX9q7MPk}D_A^1 z44&ScCfA_sHW>AK0|FwdzjW@256~W+B|wr^zB}28-2Y%b02EMjm^gdPe)2g1q}vpu z&ZMyxyy%gcP`&cdHoDPV6->)nqZMuQRt}EBrb`SKpqRh0Is3|BdB+DJ^HlbNzw*z2 zyU+LVp?%52ydt2$<1DR~ogEK<)30ZwaoaYaYTC9-{xzewLG3*QVo?FrI@pX$EHsa- z6;?B#8L^*o0_2Z5wFqFL37Y|mO`f#C3c(F7gt0oI0T;>GmIA_rfvx|qBy-x3ErC$A zSoVa0P^aBbGTD^d0xM+#Hui~?vIXeo|1mPZBBatWJqDvY zHm?(#N&aT2rzQeq%CjV$-CA;swo<-5_+405@mY-s8je_BP^Ui+7cOuWKhR zCw5&78&X4;sdT@8sQ)@kS(K_FKS@Hpq&TC17I60`4)-Gwf}R$pNBA$gS9IIBZR-^Q zO`k>0>`De<3v+Xq{o}K&t*)la1J$2BNS*#bHa+OBoBQBUckd&@HN*7_Xj*5fn$A%k zlzHvZ7?FGMK*9FDDQ9S0 zWMm}g!D@(`QIaL>u$S~6|7kW@KWxzM7OHB?TdGid>x2<=S@1%@H1Q$s#`yT#-we@> z!Sj$S`aiE9Q;s#uc^m^S6+y3OxHGBM? z@~CAAa(#tdvFe1yHCx1)JQ7j6k=_K>4r+QT|HW;nU0z}BnUrB?U+pG_TW?E67gIx_=bV{^ z(7E#8*|lfLZ%*pU8dILwd!5r*ZHgeY{}KEFQ>kwhm_XWR{g|NjikZ~WEL*~XRdc{v z10OivaT+$zf+{RZgkQ!?w5mdcOUYTs2~N3z-ys6*mwX(lXb?6cxUchVqs z=_sZ4XT#Qdn+LDgHxe_%Y#>@oc$hSgLGEMqo^u;4sXdmkmA^V_-%d+1wq^Bw=ap`j zay#bN(wg^(IQ+lYCA>z~xbRbZRTG(+2UQvTri-+Ex(*Sq{usHlvoqufM}P>D%X`&}2{-gg z5(4x}4$)#4TK(zOyOZ`gxUP}>YGx1jLa2JMe82Py(q+zUUS&;p`Be_n*Coqj@;LLX zU?=@BH3CFA%anlNRcU8rC|`r%8+DOs3o6To-sH`1V!!A+j8zUS&RzJvLNiMf-gE*t z@Oq>=?04=1#>{K~yS;GTR)?Cpv82mn&h$sRS1s0B(BF%!cj`CW(_>}zi3G24l_qg9 zNF_nZl5g^0aN{=S3dfH&IeHnAFKUS6cd8BD`EE?({hjE>QL;q+%)%aj)3-%7$2HY4 zg)i(ISt!FOa5^b)oaIdXOh~@V!m8kG=TdVLFsXiV?N#7(~D!xkp zKm~#*sWl=sBiQx5biyU!t>{5SO9$FVG3$q1@=vwd?k?s=FT|0L<6J46~BYzh$Nn$C^$$sZ|uGT z@uG_hVz}#^OwE<*Nx95vW-0NCJ-tgS#g(h*L=bRnaIF|{EP&BMhNiz+;qdrsjOX-W zp)%MNtyT;X*j<|pr+3q?fc;3Hg}qXEOctR2^ryZO=O%6OmXlfLOXII^yV5V`DePol z>lUv?l{$Sf{bI7h^#VuYwn7AtU#h;w@3#bDLY<~nILFT)aV`}W>wQ5+M~RbZ^7V&E z*lR_fv`)C!8-iW#K+zRbCMK%aXl(61>;rUdnp5 zoZuoGUes4Yhl}qC(A&k}9Sa;~kw?A#J{*g?uYAvhqnA4egKwfJr16eQbtnC#y#7gq z$2K%ln?cx|W{Ck)5Unqr_=W}@gZitFz;+SqTF}UofyEXc`M4XkMX)pkZ?!_`)s%P%TTcxTcqn>D63wfglUo3s-46z=d? z&Tx`kwsg_zdsojs^^ExgS12K^%#SAFC@Pzb*091YYN`?IH&Pg9b~9yt42&x(@^8+D zHQh9!C*shf8ATvekGj@yTw*p0$l%caATa~Zx3uh zeu;e!+HF!%GpPzyqT-KF43rwL`Mu2brlF5)?*i1BE{VM+@Q&JbCHA8vMta*7l|Dm;lTn{By6ufs2=(Ql>GtD+PEMtluZ5i1PS&Ah zog=>86w`$|cPQ@G7JtG2!l$E+>O*J9Pvb+$q$pP*5<$6vp~?uRCX#~esdYTxb4u`! z{biMw?(t`GX8Om>47nyl*o@EAh$A9~ZdnFW8r?~Ug>piaR7RUXp7XG*(xHmMG z-Oa~~ZgHDHI6*(~3XA0$o<`}jhp@L?6%n{Z(V{z%hB2$0+K-}mDOMqSN_d{)E62`v zh|;EDW|@B9@9q2OwEB9D8MZF|RV&s#w2(X=trtk6)*%#O1BbOyt*KMQHoB#c?kW+K zJn=&K7UmdO(q?liIL3#3y7Oth2W z$@y_owJ1AIcMK|!KSjyYaE*JgoL)gQ0ozw}0*yjdyb!j6&r@Ig+8N`#>b8h`$F5b< z!xicNrcQ%HBwhRpW@yXnX*6RN`wPA z1D;S1iboY8cb>7u+mn#WaZ%;gtzVn8(lgiFz`=ALg$3SOG({@JbTp(KZe0f5-6`+j z^W=qChZI|XKEXSD4UJ5A@FAv*>cCVHe$C^nGI9UUGH7J@zVxWP*Zqqc+XNqjxEs*w z{9>Nb~k@Ig)rV0gZ%eCZ3#Y z=5$D+dM0n)${%^Iy{Yx3!!0P8#W%85h*=1;(87E;UtkDVU~GhrO9g-P(eLVjbp?LP zY>9x!zi}`@*PRMYA`wtB^=~BPoHy17dhwy?TW0jo$XLnhp{#%L#a1(}!pH-4Pk2I6p`eG3C+gG`Hd*5CDw2bwclZ*erg0qEn7_;97Zh)Z~iqrIPI}7r_RDc)LxB=cIKl-sbp<&Z}t%{n{nBv^}MkkU4_t)CjTb% zq>JGpCI8(-SG>bkyQVze;0x!EkWf}lax@RuS%+`C{kTWPMvIGH=5C~y6wRaY#h@0s zZb_x91UTh#b@iRd{!3E=2k9{K={s$7d(zp|WY2_}w4}Hmtn!!VTR~7$Fi#T=UO!W0 z==HRwCb2n}bb2l!-?HuwX*RJu%nvFnd~lN#x0otl7?>Wt@};aM3X-sd(bq`S$|_uE8=wfvPd z%BP8K*k0PK8lZt@XT4tb_VvuZbzFzKslMJ@Eq z^G41}LJ#!4T-O>q=6NrZwqf;5Y$`KtH>gM&sd+QGI4ApKb{X}<`S$U?;j}rwbeSGb z(!g}pbAKjr;R#xOAdoija{HQTyw*n$Za7PIk#7ww%q`$;a0`!4&^<6h+bI1|=Id+vIHb+1zT3`irlYN&d!GPLIJf z{_HN}ZX!bKp3G0UQ7=etIh)-IBhb?{NQ1fEwWiKO#lLgH^*U<~uB~#J2g(wSP4@d! zdU@_`f|lp=>;8jqr@@!T4#UUxl-hp<9>UbGiqEccW{O}oj{NgY-WU}d`PPhv)Bh5Q z03qW)vZsipW5C-1y~m6)&7+@JQvUv^0@izTmbqF*0Frs3Mob%SV118}`m!d#o%pb3bycFp>41GwgK%`^#|N1`!VB7DUK-BK%(~msLaU-2*m; zTcfbXE&NB`s9uC4zin5IqvKUA-8h;1q>!q5@ojLTYWE%+ijuT4getE2K94~ zibVPpgsD?1CUPs!cewQf{NqqOQsuaGoRwpICmv;Iqhi1*$5ZaPp^0A&Z7Z`Ak>5+& zqk2W7_Z@y@3qNO*WOI3z%qnsGf-pQPAU97QE+z3{tiwrIhcV4X%k4zfB}@EQs&#we zzUD+?bGhIkz-oR3x8_s6;?rsT^xLe7F5?sF-K??S5AG7n92z?QPVl(1rf`me<>cFg zyM*B*hx5vbKgR}!RlLsVh`~N19Nt{+;CH_kgizQ8VgG2fC z`?Tr#G)f=hwj-w%r*A*CDXK~~3&uL?M{G9aDSZS0wGM?YwPUc^p?r<6~jJwg6 zJafwKBE%JI9IfLWkl{ZP@42&Zdi%9gR@=Zpof_7zR=2e@!J2g3c}pKBFORv#(vxGE z@Z6frp^P8B5&5_B66B+a9LOk+{3nez1Jj*r#Cms5zQq`lQPn2gkq0sixV@YvWt|l>)4)vB=u41ywc0j=8JK zKIwkr^^gc0cEL|hURV9_mh*P6MFN$npuuWX#&D)ysD_nS`C^zDJ&v7>k-DdFWExLe z8llx|ZZG!bp5D>&i$sC2XOWAAz0;)$da+n#qqvk`Z);zrJ;u@WMfUT-a9-U^w}~KI z4v`TQnTdzEBShTkVsv7lxje{p(PJz7qaS`4i!ufrPhAzL!*S}u`ck+#vKj2S2Jqj? zT5AI|qjU$qcc{*P9*MwQYg|cj?e+PF^QHJZhM*yI_q`X-G3Hl&P>GZ~LJQF4zIoYx z_;^DEp@C!12{2j89PhG9If(wmYRb9f+#Tq^*VZwSB9k zKWbA}JQCeHC^L2FmJ-A%wCsDBW0Eu}?DrFEYNB%G3*2Ac=QUUpJWK~Z4CvNO@ zVA?5UKENaIhn>j{JPerlR55>W)j`-k!}Ju29W0cdLbU&L@r)xA|0R<$f2+QSZa_^> z7`Jujf#a#3bt17?ka(;eZu|TTX|T%z+slA;tus!50kJKlJ&y9U_DBB>2G8*1|I6~6 zp}~XVwVCFiek_tX#}0m3zX{55xM@<8WZU z2^MyDy2?25MF8Tm2*I`}PvU23mhGUc5J#bQ4~1*u%7hf80qs967F&#EpX)nVr#QSf zQ+;9Y?{8vT>eLrhAE16l%%)TGqzzh0*wAhU{|fGZL4}w)WFB*Vw;TXw#Df2W&cL7E zVaOJ_msEAbs%W9~-Kq(?#?dDJR$gr)6PebJ%Uc6))I$mHU7YH?lE%qf$00{`fj}7d z=&8lG+B?20!SQ1ytdoWVIM0i3{t8dw$Pp&f6|T_mGX=ASz}jZ^7Y)xqg{m6 zhdUe>lyUT2a~dSRe^ZBva@2Q?+kvkw5x~!@J{e>j`vlja$%yMJgBf~CrK&DGY^mGx zltfd^QZoukr?7IYN0IfI3rMKkp8D!WY~`y(il!kr+@Xq)z)5J$CC_#HzUG zq>S`|vwyXeXuC9e`+VppBQ9R^&`Ocg!O0ox)wMf)*M233e|shU8RdEC$NJW2uHl4B zH!U-}UF$-PQf{|R(LAK|C$k5pjPiI}uO^v|VhYl%Vjo`LiZ%||-`fsz{3XNG!dI3U zO}R@|vhJ}jJ}gUHhf~jX-?wo0c(0eHoDEr{D!_je{X-P4O*+6cyU`sT_fw2rq%?{@eUNh|f6{i(@Z+i_vqa=(+S=%~eMTppcH6buL|stG)6MN> z4Qs!RM_K8!{{i2XZnb%^H6E&1N1-Or^>-$5-ZrA^BO_=kRR zlnb6EvyQR3-v4t)Wxg+3aPpxmVo{=5FUoLILZ$Z3$963p_~qvj26@|5pLEkKukeP5 z*VMG*A<1VL>E3QekDS9llnf0FTncLVHkfm1Xin>Q4?o`Q&pYmujkLbfDL0RDvwor8={8ETQjamQOZ{SsYCh(*SeN zXb(~y3(7(skgq2?`j~`;vpPbycnfy5g1rdR2vy|V5bq>ZG;xXymN@jmVRK#g)`Q{8 z!ISV~9C@6Y;Ro=yOb+SLNc?X)=Q|9kt_V*i+nj72$ds3OtQIzk=5Scn`zt!FK3T=6 z9FuhJbq>(GB0tdqzos5=A68zi&Nh|z=!%#*N;y&Ip&B+6wT ze)JuR{3wG?>{q_BTv$`z`HdfWW1XL3n~WHGF<3M@-B)$> z&SEV}@8Mly6Atl)TtjlTZ&H;0yYtiK?FA<)?&>mV=!Jzy5HD!L^Hdm$Au`6#pyL)N z5H`W^-Lb5P22lmCnn`q=e*=t>mdS5ZG$8-Qz>SUu>Wtqx>6X@z^NH5rZk*0{Hi2sn zw8UjZs}p@Lu>-2`{`*%wFUQQ>33KGW&%hON)tlH^koAXvu{?3i^R758eA>XN)Y&k0 zqw&DskUhN{@#~D9IiARCBid=xhbX&%vqT$^dxe@Ys|K&?5Sdj;fLJQ#&hlsupSPu9i4Pnytp zg^5hLnanfCIZGmj>NN>CXGZV}vYMpsO4)nk0A=+6m-~)7C2V!xjLJk?#GzH<>fN}LrqjutMk6`f(xOWa?!&W+Pm$g=?X|Dymx+w zt_LvTsNIz`W=Xjj7kR#3Si1~5su$Mx9xU@X#aUe)4v<05Yz?^~2)xXNtn{&+u^Yk+ zxHhQv0sMNSw{&D>$xZ5q0gIfj{9746HDess#+u12?k~I<+!^ylkhitWAxp1}L zk^L5#EsxBc6x0+yzq|)oKrK3^DbOizH+@ZNkE_}8r6U@}z}Gf12+srqjR$o5A5mgV z9J#m=4Ob(X}0+vAFF)qwSC+?baNM9+wo5tOlS$7r4q>iGH>A#YbyT3RtHO2mle zFF=lwV@pcZA@)3??;_YCj;iXbRh&LwBV?@>a3#=t@cuQ4NP!E)bC9*A=UdRRW5`PW zd(dJ*=l&4|Oaxl&VHl5jyVJ&UZJ@5Ni?-uvTiiVmA5SM z2){ZIJ`EzLrnFS$>zv5cE7`Rt+m8A=eM7k7HzXpFFOE#gnmU$VoHQ9yMlC9PZ=*Je zjJ93?XHA)!RN8{9xZo4YlQ-2BftwYj%ny!uqn3Aq&8POMz@Hu#`bkk5)(=#7>A*R# z#{Qd5Uhr|rayzo~91<%KWa4_2s>5*=aARd3WWRipcfGbyaFHUFxwi?Qmqyipx@N#4u68TJCa|LA$NEtng~y z6tfWwnMhp{QZiotp?C*hy5$8jhI4BnZ~H!@WXTntI7$bjpMs6<&FhiON|Dt_V(HRU z#d#Yyx_A7ieKb%Z_z0C+Q>=OJY$_;Ow<8loD+4XmGjv+Q7_;K!W_w)esy`8Dh<0(Z zGz)cFJKg7X-nvOd!b%t<>QAJxFt`3Dpj7txho(jiqG>ad^Xft_-*$P#^JXbSB!prR z{!cW&1K_9BuL?(w4hnE;;!b-54K~_YYBuG>MUm!NN18H@1|HGFH;C&6+0dKcXK^B) zcE}CLt~PSli6oFjhh3x9#utoocr*z*E%z2xsUHKcHJ2fph{jP_VUD-Ek83nqoRS30Hl8ci! zd?*R_uVB8LXCYOLmOz)|-+#Z|c3wPN!5N>x|Gq6f72J0WrO1FEs~mp$aJw0$a*4pl zX&Lsz)1I7=pw!lluHA|M15cG^uvoiRo}C3ko>%OGh=rZ8o)gx&>*@WBjEM*2i-CYj?)-u%X;}6 z%=WXE zrDLhs_A^NSiBSJRSK_@yj_;oxz)W-hS0{FA}ShRh+4Lv+O+#Or#vtxgft8*SL6wTJ?B*Y1jdBG_p;3OCL z-c`o1w?p5{rO+a3jZpzx^ABRwK&2q{6g$pd2kSZZUi83z@ekCr!)mantYAE@|grLQQ2z`ek7 z$r;1qcHO>^!6kQwFo~?<-m-I~MXW+YC}tfMBh9_{!KP(pW!KG>Lg1INY@AlN7x}TU z=bk8(&SMH-EndQKo=OjZ%CStUC|z_7Sx0zsU$O={=(F(E4|2W2vV zGGtRuJDM}y>NQs+3Z}igrElvc^g;2PW=RnR1-^d$L$$4uGyn!>#HO5_&{%&jr;AS} zeQlMW)z*|D%rBs2lG)aA4`6kHARX4j095)06J`ls@BE!2Ln;IHBzX?zoYNj52~QuV zSV#7IkLc zVf%dNcWtm9l+KC#jyInKVSkqanLF>$GYX@d<~X^Od&*53Dt=WZtF!vrZip(ZyFT(d zQ{8_2MS!AdR6!p)m3#*VH*7)?h{rKew#<=RyLmIJJg&6=o{IY^A3ljlM;IQ&AHLzZ zK9gN8tkdg{{Bi4$+hI%YKHE_WRg7V#Aa|r!IDkS0!AndU=de8e(O?~iwLJDAg$CLy z@?(YzDc0D>B4<2%FUdNx?LGW% zYNArJ*hDDCLi;|5yyZi?d5U&$vK|>7fEouq*%+*c5>tno@>n!{(Q)%AL)zp!N~gS4 zVcFPGquby!(d!dC9Z4f(W>HVT%0$kFhuS~Y8RzlbI&bT94O14y)iKzFMe2N~DqO@w zXF6-W>+Q8bnB$aBl7pgupYzWctS4eyMS(xI#lL!Xqn&9c8ZrU8tY*W_gQ$6Tu?A+% zMEZoh!3#u=S)4s~NgqJ%;Yp$EP?8k>8xz7a6JU8GDF;H@O)>`pU?mgvf+{GnFWA?iM zi2bzB{k9H;u0q6>X#qt4Hfi~?Mrk2P{z;Sg9h_XiMNeR~^TA%Rhwcdf)s2#CA0$%$ zGze^`br>-;x&eWIE{fG#F7-wvllhQ}#_NW4TFA_GawJdhhbg|c43589bv17H zI1NrpI?r8+li!aDDMpX)b{T@YZm(Fkkc}wJ|lUjJ+!*#5ygQ( z{s@YIiDpyoypkcSo*IzrT z1}piNQYw21hr=DYm87ocyT1NJ`r8Vwz~ZbwN+gv>?A85I1`%>Pm;UZ5WLL-sj=I#i zrr;zK#Foi69^EtJQ1di2LhY7SLEAlH3n4hY&!mEEKR3A;L;hk+Vijo~J4r14S5-6O z0D|Bk_@;PT@P$;;>}Y6-&qrH{8a86Caa}zRHMwpnmxZ3i0hUQrDmYGfQ<>*S(slY0 zb?~QFf$}I@0eOdy&7U0y|`|us&PAv0v$OxYUg*@ zzv*qiQRfD`x^gT1OQ!-Lu4S_`moE$xq1M3GVB+r)G3ejh_;b3<9Y6%s^!o8&D)x4!h9*DaUZ zgH~bp&#|y<_ro=p>$O#2i07Z(lAC2C7*^YNTgh(r6axbmv1hmO|s=e7?Q={ z5;xaxR%#W7(k+O*zq)h8BR%^KlYzkF3XSLs%NPC&Nq;nSh{y-n%JYyqa$tha}@1-nbP{qZ#` ziVU!7usQqrGr7oM`w|^oZWluGQgIjJ6yM;ow{96wPpc@u$DZ5RB*y=|&d?4T1PrP? zLMl@kz;*IA8`(a8ozF{oB#l}?Kwu8Tv|c7-cd3QB8?zC4D?dH|(-&TQ6~K1Pe4A); z(gRF&!3#x#2$FQ3h(3uBjF~E3eC+snlIR_h@(tJo+f(vb#ES?q=Yl#Gu@8CjfRIeG zf^9)qr&l~A@*&VGM;z=m1|2TB^6^qs6bU7@G@04LeVTO3YYe-SA%4k;1iUIG(m=^; zYVvD^Z%Sc3i5Si-Ed=v?=ehO#*0=yUY;$|o0;y&fObP2q^`-mX^R}5FJ+sH@u|BW- zQ$NiMOUaPo1IRJIt#)OP=L6O%9|1OyLo@pHa=1WBSi$Z7hPGap6#CC-8!wlg@j>F~ z7X$n6Fe2A`vl5GG9~%U8Klt?|v7J<;YU6jK?&}e+N>hWmUrOc~*E<=kUlb-S>{t{$ zzV}30$ksXiAd4de6V&kyS6ZdRRC(+I|NJeDxCqQU4b#s|roPsLH?AU!ii&h4uSHcN zU04HH#ku(maYe@(TuW`M60=P5M#)5uw!cm4z6+B5Xb!I8ysK^G$nZW925sZ03nDvlDK zXo?r_mtX3Ug-zY*b=-w~=e|?(LgelxuB-fa4e%a(_$tYJ?G9+{Hl>aHfhJJ}-Y@X% zhPl-ob9K8?hnNGLQS&wJuhrf!B-v(HB+emTja!zNZ)sHWpZoQ+T=obOZfVcLFbn2T zU+-0QxTGtL<`sS0eknA8ZnLV~+dh!}6>z+&-OVt}-BHL|nk!dO<(+F2+!h&p{1VH< z%h(@ED(qLrIDzxuQ;~@!TOGb$Z@w99_$v7muEZAzddDw2V9WNHg+J-4@l`R3sp=Un zUJhQ4eallD1jQm`nN;+00wY1Y7Saj=`C8!Zcmxc9oM%B;j(K<+Ju zC*6f+-93zbPqVsjJTP~S|NNQ`T~vI|~?a6!fQ3ev{0; z<3EIT=~y+hJ&_#MFQ>~Z^mu83umhv;nd$oAJw<&`{Oy`jnahI;ocoJCHyFsTG`#|T zn9~Xd%^fH&FJa9^d7NiJ8#GHRppsS)5qlRTO*ir@UFWRI${LN|;o$pL5su?Mi)yma z+(OvMjSZqGRdsqSEefW{!7f!H?PEINV(yf=Hn?4DKTZtZZ|W)ldmjU1!9K}k13={k_MDWi z3D{61m>*M)ddGtYd;K>+ks31Wn`lrP=P-9L3cJ-c*^e6hN)~0q?&iIldSZy35Pa@f zod+kYIEOz5*?fWCBSsuxv*qunauthenticated_read_metaobjects `, }, + { + title: 'Protocol Links', + sectionContent: ` +Protocol links are an easy way for Shopify to infer the type of request you are trying to make. If you would like to make a request to the [Storefront GraphQL API](/docs/api/storefront), you can use our [Storefront Protocol](/docs/api/checkout-ui-extensions/unstable/apis/storefront-api#examples) to infer your Storefront URL and API version. + `, + }, ], }, { @@ -463,6 +469,38 @@ You retrieve these metafields in your extension by reading [\`appMetafields\`](/ ], }, }, + { + type: 'Generic', + anchorLink: 'preloads-definition', + title: 'Preloads definition', + sectionContent: ` +For specific targets, you must provide the URL of assets or pages loaded by UI components within its extension. This allows Shopify to preload them as early as possible and ensure a performant experience for buyers. + +Currently, the only supported component is \`chat\`. + +The URL for the iframe used in this extension target. The URL can be absolute or relative. Relative URLs are resolved against the app URL. + +For example, + +* if the app URL is \`https://example.com\` and \`chat = "/my-chat-application"\`, the resolved URL will be \`https://example.com/my-chat-application\`. +* if \`chat = "https://my-chat-application.com"\`, the resolved URL will be \`https://my-chat-application.com\`. + `, + codeblock: { + title: 'Extension target preloads', + tabs: [ + { + title: 'shopify.extension.toml', + code: './examples/configuration/preloads.example.toml', + language: 'toml', + }, + { + title: 'Block.jsx', + code: './examples/configuration/preloads.example.tsx', + language: 'jsx', + }, + ], + }, + }, ], }; diff --git a/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.toml b/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.toml new file mode 100644 index 000000000..10bf81f8e --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.toml @@ -0,0 +1,10 @@ +# ... + +[[extensions.targeting]] +target = "purchase.checkout.chat.render" +module = "./Block.jsx" + + [extensions.targeting.preloads] + chat = "https://my-chat-application.com" + +# ... diff --git a/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.tsx b/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.tsx new file mode 100644 index 000000000..038579ea4 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/checkout/staticPages/examples/configuration/preloads.example.tsx @@ -0,0 +1,10 @@ +// ... + +export default reactExtension( + 'purchase.checkout.chat.render', + , +); + +function Extension() { + // ... +} diff --git a/packages/ui-extensions/docs/surfaces/checkout/staticPages/extension-overview.doc.ts b/packages/ui-extensions/docs/surfaces/checkout/staticPages/extension-overview.doc.ts index cc291a392..4f1fa2a6a 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/staticPages/extension-overview.doc.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/staticPages/extension-overview.doc.ts @@ -28,7 +28,7 @@ You register for targets in your [configuration file](/docs/api/checkout-ui-exte description: ` This is the first step in the checkout process where the buyer enters contact information and a delivery address. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-information.png', }, @@ -37,7 +37,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Point in checkout where the buyer selects a shipping method. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-shipping.png', }, @@ -46,7 +46,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Point in checkout where the buyer enters their payment information. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-payment.png', }, @@ -55,7 +55,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Summary of the cart contents, discounts, and order totals. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-order-summary.png', }, @@ -64,7 +64,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Accelerated checkout where Shopify pre-fills buyer information using their Shop Pay account. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-shop-pay.png', }, @@ -73,7 +73,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` When multiple shipments are expected, a checkout will render split shipping options. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-split-shipping.png', }, @@ -82,7 +82,7 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Point in checkout where the buyer can select a store location to pick up their purchase. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-local-pickup.png', }, @@ -91,10 +91,19 @@ See [all extensions targets](/docs/api/checkout-ui-extensions/targets). description: ` Point in checkout where the buyer can select a pickup point to have their purchase delivered to. -See [all extensions targets](/docs/api/checkout-ui-extensions/targets). +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). `, image: 'supported-locations-pickup-points.png', }, + { + title: 'Overlays', + description: ` +Static extension targets that floats above the checkout. + +Review [all extensions targets](/docs/api/checkout-ui-extensions/targets). +`, + image: 'supported-locations-chat.png', + }, { title: 'One-page checkout', description: ` @@ -131,6 +140,15 @@ Review [all **Thank you** page extensions targets](/docs/api/checkout-ui-extensi `, image: 'supported-locations-order-summary-thank-you.png', }, + { + title: 'Overlays', + description: ` +Static extension targets that floats above the Thank you page. + +Review [all **Thank you** page extensions targets](/docs/api/checkout-ui-extensions/targets). +`, + image: 'supported-locations-chat-thank-you.png', + }, ], }, { diff --git a/packages/ui-extensions/src/extension.ts b/packages/ui-extensions/src/extension.ts index 6047d1e38..f4d1251a8 100644 --- a/packages/ui-extensions/src/extension.ts +++ b/packages/ui-extensions/src/extension.ts @@ -37,10 +37,10 @@ export interface RenderExtensionWithRemoteRoot< any > = RemoteComponentType, > { - (root: RemoteRoot, api: Api): - | void - | Promise - | Promise<() => void>; + ( + root: RemoteRoot, + api: Api, + ): void | Promise; } export interface RunnableExtension { diff --git a/packages/ui-extensions/src/index.ts b/packages/ui-extensions/src/index.ts index bcf51eb95..c5d0da7b3 100644 --- a/packages/ui-extensions/src/index.ts +++ b/packages/ui-extensions/src/index.ts @@ -1,2 +1,7 @@ -export * from './api'; -export * from './extension'; +export type {I18n, I18nTranslate} from './api'; +export type { + RenderExtension, + RenderExtensionConnection, + RenderExtensionWithRemoteRoot, + RunnableExtension, +} from './extension'; diff --git a/packages/ui-extensions/src/shared.ts b/packages/ui-extensions/src/shared.ts index 68758d4e9..fa36f06ba 100644 --- a/packages/ui-extensions/src/shared.ts +++ b/packages/ui-extensions/src/shared.ts @@ -38,7 +38,7 @@ export type ApiVersion = * * * [`collect_buyer_consent.customer_privacy`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#collect-buyer-consent): the extension can register buyer consent decisions that will be honored on Shopify-managed services. * - * * `iframe.sources`: the extension can embed an external URL in an iframe. + * * [`iframe.sources`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#iframe): the extension can embed an external URL in an iframe. */ export type Capability = diff --git a/packages/ui-extensions/src/surfaces/checkout.ts b/packages/ui-extensions/src/surfaces/checkout.ts index 9539e9657..50835de82 100644 --- a/packages/ui-extensions/src/surfaces/checkout.ts +++ b/packages/ui-extensions/src/surfaces/checkout.ts @@ -186,8 +186,11 @@ export type { } from './checkout/api/payment/payment-option-item'; export * from './checkout/components'; + export * from './checkout/targets'; + export * from './checkout/extension'; + export * from './checkout/shared'; export { Style, @@ -209,4 +212,5 @@ export type { export type {IdProps} from './checkout/components/shared'; export * from './checkout/globals'; + export * from '../shared'; diff --git a/packages/ui-extensions/src/surfaces/checkout/api/address-autocomplete/standard.ts b/packages/ui-extensions/src/surfaces/checkout/api/address-autocomplete/standard.ts index 41be95039..179a68347 100644 --- a/packages/ui-extensions/src/surfaces/checkout/api/address-autocomplete/standard.ts +++ b/packages/ui-extensions/src/surfaces/checkout/api/address-autocomplete/standard.ts @@ -194,7 +194,7 @@ interface Extension< * * * [`collect_buyer_consent.customer_privacy`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#collect-buyer-consent): the extension can register customer consent decisions that will be honored on Shopify-managed services. * - * * `iframe.sources`: the extension can embed an external URL in an iframe. + * * [`iframe.sources`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#iframe): the extension can embed an external URL in an iframe. */ capabilities: Capability[]; diff --git a/packages/ui-extensions/src/surfaces/checkout/api/standard/standard.ts b/packages/ui-extensions/src/surfaces/checkout/api/standard/standard.ts index dd1953003..11ca039ea 100644 --- a/packages/ui-extensions/src/surfaces/checkout/api/standard/standard.ts +++ b/packages/ui-extensions/src/surfaces/checkout/api/standard/standard.ts @@ -79,7 +79,7 @@ export interface Extension { * * * [`collect_buyer_consent.customer_privacy`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#collect-buyer-consent): the extension can register customer consent decisions that will be honored on Shopify-managed services. * - * * `iframe.sources`: the extension can embed an external URL in an iframe. + * * [`iframe.sources`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#iframe): the extension can embed an external URL in an iframe. */ capabilities: StatefulRemoteSubscribable; @@ -1358,6 +1358,16 @@ export interface Customer { * {% include /apps/checkout/privacy-icon.md %} Requires level 1 access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data). */ image: ImageDetails; + /** + * Defines if the customer email accepts marketing activities. + * + * {% include /apps/checkout/privacy-icon.md %} Requires level 1 access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data). + * + * > Caution: This field is deprecated and will be removed in a future version. Use `acceptsEmailMarketing` or `acceptsSmsMarketing` instead. + * + * @deprecated Use `acceptsEmailMarketing` or `acceptsSmsMarketing` instead. + */ + acceptsMarketing: boolean; /** * Defines if the customer accepts email marketing activities. * diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts b/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts index a2bd251c4..b76e5f229 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts @@ -3,7 +3,7 @@ import {createRemoteComponent} from '@remote-ui/core'; import type {Size, VisibilityProps} from '../shared'; import type {IconSource} from '../Icon/Icon'; -type Tone = 'default' | 'critical' | 'subdued'; +type Tone = 'default' | 'accent' | 'critical' | 'subdued'; export interface BadgeProps extends VisibilityProps { /** diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Button/Button.ts b/packages/ui-extensions/src/surfaces/checkout/components/Button/Button.ts index d097833bd..30fbf229b 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Button/Button.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Button/Button.ts @@ -38,7 +38,7 @@ export interface ButtonProps */ submit?: boolean; /** - * Destination URL to link to. If this value is set, the button will render as a Link. + * Destination URL to link to. */ to?: string; /** diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts b/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts new file mode 100644 index 000000000..5e54e0c1d --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts @@ -0,0 +1,89 @@ +interface AppBridge { + /** + * The static configuration values that will not change during runtime. + */ + config?: Config; + + /** + * The Shopify surface that the app is embedded within. + */ + surface?: 'checkout'; + + /** + * The platform or application that the app is embedded within. + */ + platform?: 'browser' | 'shop-app' | 'pos'; + + /** + * The ID token providing a set of claims as a signed [JSON Web Token (JWT)](https://openid.net/specs/openid-connect-core-1_0.html#IDToken%5C) + * with a TTL of 5 minutes. It can be used can be used to ensure that requests came from a Shopify authenticated user. + * See the [ID Token documentation](https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens) from more information. + * + * @see https://shopify.dev/docs/api/checkout-ui-extensions/latest/apis/session-token + * @see https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens + */ + idToken?: () => Promise; + + /** + * The references and APIs to the UI extension that helped bootstrap the iframe. + */ + extension?: Extension; + + /** + * Information about the current visitor. + * + * @ignore async via our RPC endpoints to ensure a secure handshake between + * host and client is established. + */ + visitor?: () => Promise; +} + +interface Config { + /** + * The locale of the shop that’s embedding the app. + */ + locale?: string; +} + +interface Extension { + /** + * The unique handle name of the UI extension as defined by the developer. + * + * Learn more about [extension configuration](https://shopify.dev/docs/api/checkout-ui-extensions/latest/configuration#how-it-works). + */ + handle?: string; + + /** + * A MessagePort instance for communicating directly to and from the UI + * Extension that created the iframe. It will need to be started to begin + * receiving messages. + * + * Learn more about [MessagePort on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort). + */ + port?: MessagePort; + + /** + * Set an iframe’s size. Depending on the context, the host page may decide + * to apply or ignore the new sizes. For example, if the iframe is meant to + * fill its parent container the host would ignore the request. Conversely, + * if the parent container allows the iframe to fill it the host would + * apply the new size. + * + * Alias to `window.resizeTo()`, available here for feature discovery by the + * embedding app. + * + * Learn more about [resizeTo() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo). + */ + resizeTo?: Window['resizeTo']; +} + +interface Visitor { + /** + * The unique token of a given user across all surfaces in a shop, present + * if a user has opted-in to tracking. + * + * @ignore this maps to the _shopify_y cookie which Trekkie refers to as a + * uniqToken. + */ + id?: string; +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.doc.ts b/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.doc.ts new file mode 100644 index 000000000..a0aa658bb --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.doc.ts @@ -0,0 +1,215 @@ +import type {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'; + +const data: ReferenceEntityTemplateSchema = { + name: 'Chat', + description: 'Use Chat to create live chat applications.', + thumbnail: 'chat-thumbnail.png', + requires: + 'configuration of the [preloads](/docs/api/checkout-ui-extensions/latest/configuration#preloads) value in the extensions configuration file.', + isVisualComponent: true, + type: 'component', + definitions: [ + { + title: 'ChatProps', + description: '', + type: 'ChatProps', + }, + { + title: 'App Bridge for checkout', + description: ` +The App Bridge script for Checkout provides APIs that enables a secure communication channel between the Shopify Checkout and the embedded application within the Chat iframe. It also offers convenient methods to perform common actions like resizing the iframe from within the application. + +After App Bridge is set up in your app, you have access to the \`shopify\` global variable. This variable exposes the following App Bridge functionalities and configuration information: + `, + type: 'AppBridge', + }, + ], + category: 'Components', + subCategory: 'Overlays', + defaultExample: { + image: 'chat-component-minimized.png', + codeblock: { + title: 'Basic Chat', + tabs: [ + { + title: 'React', + code: '../../../../../../ui-extensions-react/src/surfaces/checkout/components/Chat/examples/basic-chat.example.tsx', + language: 'tsx', + }, + { + title: 'JS', + code: './examples/basic-chat.example.ts', + language: 'js', + }, + ], + }, + }, + subSections: [ + { + type: 'Generic', + anchorLink: 'about-app-bridge', + title: 'Getting started with App Bridge for checkout', + sectionContent: ` +You must add App Bridge to your hosted chat application by including the script tag pointing to the \`app-bridge-checkout.js\` as the first script in the \`\` section as seen in the example. The script loads directly from Shopify and keeps itself up-to-date. + `, + codeblock: { + title: 'Hosted chat application', + tabs: [ + { + code: './examples/include-app-bridge.example.html', + language: 'html', + }, + ], + }, + }, + { + type: 'Generic', + anchorLink: 'global-variable', + title: 'App Bridge’s global variable', + sectionContent: ` +After App Bridge is set up in your app, you have access to the \`shopify\` global variable. This variable exposes various App Bridge functionalities, such as resizing the parent iframe or retrieving shop's details. + +The [reference](#app%20bridge%20for%20checkout) above list all the available methods and properties. + +Alternatively, to explore all the functionality available on the \`shopify\` global variable: + +* Open the Chrome developer console while in checkout. +* Switch the frame context to your app's iframe. +* Enter \`shopify\` in the console. +`, + codeblock: { + title: 'shopify', + tabs: [ + { + title: 'config', + code: './examples/app-bridge-shopify-config.example.js', + language: 'js', + }, + ], + }, + }, + { + type: 'Generic', + anchorLink: 'src-and-query-parameters', + title: 'Chat source and query parameters', + sectionContent: ` +The \`src\` of the iframe rendered by Chat is provided by the \`preloads\` \`chat\` key in the extension configuration file. Shopify automatically appends query parameters to the URL which allows developers to verify the authenticity of the request and the identity of the merchant. We guarantee these tokens are valid and signed by Shopify. + +#### id_token +The ID token providing a set of claims as a signed [JSON Web Token (JWT)](https://openid.net/specs/openid-connect-core-1_0.html#IDToken%5C) with a TTL of 5 minutes. It can be used can be used to retrieve merchants information on the backend as well as ensure that requests came from a Shopify authenticated source. See the [ID Token documentation](https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens) from more information. + +#### locale +The locale of the shop that’s embedding the app, i.e. \`en-CA\`. This information is also available in the \`shopify\` global variable under \`config\`. + +#### handle +The unique handle name of the UI extension as defined by the developer. This information is also available in the \`shopify\` global variable under \`extension\`. +`, + codeblock: { + title: 'Chat source', + tabs: [ + { + title: 'shopify.extension.toml', + code: './examples/shopify-extension-toml.example.toml', + language: 'toml', + }, + ], + }, + }, + { + type: 'Generic', + anchorLink: 'chat-dimensions', + title: 'Chat dimensions', + sectionContent: ` +To provide developers with the most flexibility when it comes to responsive changes, the iframe rendered in the page by \`Chat\` takes the full width and height of the browser window. Only a specific part of the iframe is visible, the rest is clipped. + +The \`inlineSize\` and \`blockSize\` values set on Chat or changed through the App Bridge \`resizeTo()\` method dictates the bounding box of the visible part. That box is fixed and positioned in the bottom right corner of the iframe. + +With this in place, your application can now rely on the window’s dimension to change styles or apply specific behaviors to different window sizes. This allow developers to style their app as if as if the widget would be outside an iframe. For example, CSS media queries can now work within the iframe. +`, + codeblock: { + title: 'Hosted chat application', + tabs: [ + { + title: 'style.css', + code: './examples/chat-media-query.example.css', + language: 'css', + }, + ], + }, + }, + { + type: 'Generic', + anchorLink: 'app-bridge-css-api', + title: 'App Bridge’s CSS API', + sectionContent: ` +Since the Chat iframe is clipped and fills the whole window as seen in the previous section, using percentage based sizes for its UI elements will most likely resolves in clipped content. As mentioned in the UX guidelines, Chat is constraint to specific [maximum sizes on large and small screens](/docs/apps/build/checkout/chat/ux-for-chat#build-within-the-chat-component-dimensions) set by Shopify. Setting a 100% width on an element will not be constraint to the visible size of the iframe, but to the whole window. + +To remediate this issue, through App Bridge we offer a set of [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) will all the maximum dimensions defined in our UX guidelines. You can use these custom properties wether in Javascript or in the CSS of you application to set protections against overflowing contain while using percentage based sizes. Doing this, will also reduce regressions if Shopify ever changes the maximum dimensions. +`, + codeblock: { + title: 'App Bridge CSS API', + tabs: [ + { + title: 'Custom properties', + code: './examples/app-bridge-css.example.css', + language: 'css', + }, + { + title: 'style.css', + code: './examples/chat-custom-properties-css.example.css', + language: 'css', + }, + ], + }, + }, + ], + examples: { + description: '', + examples: [ + { + description: + 'A very common action in your application will be to request a resize of the iframe. This is done through the App Bridge `resizeTo()` method. The following example resizes the iframe following the click of an activator button to show a dialog window.', + codeblock: { + title: 'Resize the Chat iframe from the hosted application', + tabs: [ + { + title: 'UI Extension', + code: './examples/app-bridge-resize.example.tsx', + language: 'tsx', + }, + { + title: 'Hosted chat application', + code: './examples/app-bridge-resize.example.html', + language: 'html', + }, + ], + }, + }, + { + description: ` +Information can be passed between the hosted application and the UI extension through App Bridge. [Extensions API](/docs/api/checkout-ui-extensions/unstable#extension-apis) are available in the UI extension and can be shared through that method. + `, + codeblock: { + title: + 'Communicate information between the hosted application and the UI extension', + tabs: [ + { + title: 'UI Extension', + code: './examples/app-bridge-communication.example.tsx', + language: 'tsx', + }, + { + title: 'Hosted chat application', + code: './examples/app-bridge-communication.example.js', + language: 'html', + }, + ], + }, + }, + ], + }, + + related: [], +}; + +export default data; diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.ts b/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.ts index b7d895186..d99ddf59e 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/Chat.ts @@ -3,23 +3,17 @@ import {createRemoteComponent} from '@remote-ui/core'; import type {IdProps} from '../shared'; export interface ChatProps extends IdProps { - /** - * The URL to embed within the Chat component iframe. - */ - src?: string; - /** * Adjust the inline size. * * Checkout imposes sizing restrictions for the component, therefore the size set * may not be the actual size rendered. * - * - `number`: size in pixels. - * - `` `${number}%` ``: size in percentages of the available space. + * `number`: size in pixels. * - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size + * Learn more about [inline size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size). */ - inlineSize?: number | `${number}%`; + inlineSize?: number; /** * Adjust the block size. @@ -27,12 +21,11 @@ export interface ChatProps extends IdProps { * Checkout imposes sizing restrictions for the component, therefore the size set * may not be the actual size rendered. * - * - `number`: size in pixels. - * - `` `${number}%` ``: size in percentages of the available space. + * `number`: size in pixels. * - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/block-size + * Learn more about [block size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size). */ - blockSize?: number | `${number}%`; + blockSize?: number; /** * A label that describes the purpose or contents of the component. When set, @@ -57,29 +50,28 @@ interface MessageEvent { /** * The data sent by the message emitter (the embedded page). * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data + * Learn more about [MessageEvent data on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data). */ data?: any; /** * A string representing the origin of the message emitter (the embedded page). * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/origin + * Learn more about [MessageEvent origin on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/origin). */ origin: string; } -interface ReadyEvent { +export interface ReadyEvent { /** * A function to send messages to the embedded page. * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage + * Learn more about [postMessage on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage). */ - // eslint-disable-next-line no-warning-comments - postMessage: (message: any /* TODO , transfer?: Transferable[] */) => void; + postMessage: (message: any) => void; } /** - * Use Chat to embed another HTML page within the page. + * Use Chat to create live chat applications. */ export const Chat = createRemoteComponent<'Chat', ChatProps>('Chat'); diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.js b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.js new file mode 100644 index 000000000..e3fd44d88 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.js @@ -0,0 +1,15 @@ +// Create a variable to store the buyer's first name. +// We'll be able to use this to personalize the chat experience. +let buyerFirstName; + +// In the hosted application Javascript, listen for messages from the UI extension. +shopify.extension.port.onMessage = async (event) => { + // if the message's data has a ping action, respond with a pong + if (event.data.action === 'ping') { + buyerFirstName = event.data.buyer.firstName; + + await shopify.extension.messagePort.postMessage({ + action: 'pong', + }); + } +}; diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.tsx b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.tsx new file mode 100644 index 000000000..ad3cc0353 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-communication.example.tsx @@ -0,0 +1,58 @@ +import { + reactExtension, + useShippingAddress, + Chat, +} from '@shopify/ui-extensions-react/checkout'; +import {retain} from '@remote-ui/rpc'; +import type {ReadyEvent} from '@shopify/ui-extensions-react/checkout'; + +export default reactExtension('purchase.checkout.chat.render', () => ( + +)); + +function Extension() { + /** + * Use the `useShippingAddress` hook to access the first name of the buyer. + */ + const {firstName} = useShippingAddress(); + + /** + * Define a variable to store the `postMessage` function + * so we can re-use outside of the onReady callback later if needed. + */ + let postMessage; + + return ( + { + /** + * Save the `postMessage` function to the variable defined earlier. + */ + postMessage = postMessageParam; + retain(postMessage); + + /** + * When the communication channel is ready, send a message to the hosted application + * using the `postMessage` provided as parameter. + */ + postMessage({ + action: 'ping', + buyer: { + firstName, + }, + }); + }} + onMessage={(event: Event) => { + /** + * Listen for messages from the hosted application. + * If the action is `pong`, the communication channel is successful. + */ + if (event.data.action === 'pong') { + console.log('Messaging channel successful'); + } + }} + /> + ); +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-css.example.css b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-css.example.css new file mode 100644 index 000000000..3a1d2c306 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-css.example.css @@ -0,0 +1,16 @@ +:root { + --shopify-checkout-chat-minimized-max-inline-size: 224px; + --shopify-checkout-chat-minimized-max-block-size: 72px; + --shopify-checkout-chat-maximized-max-inline-size: 415px; + --shopify-checkout-chat-maximized-max-block-size: 700px; + + @media screen and (max-width: 569px) { + --shopify-checkout-chat-maximized-max-inline-size: 100dvi; + --shopify-checkout-chat-maximized-max-block-size: 93dvb; + + @supports not (inline-size: 100dvi) { + --shopify-checkout-chat-maximized-max-inline-size: 100vi; + --shopify-checkout-chat-maximized-max-block-size: 93vb; + } + } +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.html b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.html new file mode 100644 index 000000000..37ddd2db2 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.html @@ -0,0 +1,48 @@ + + + + + + + + + How can we help you today? + + + + + + + diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.tsx b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.tsx new file mode 100644 index 000000000..55fe8b5d5 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-resize.example.tsx @@ -0,0 +1,9 @@ +import {reactExtension, Chat} from '@shopify/ui-extensions-react/checkout'; + +export default reactExtension('purchase.checkout.chat.render', () => ( + +)); + +function Extension() { + return ; +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-shopify-config.example.js b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-shopify-config.example.js new file mode 100644 index 000000000..54096e025 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/app-bridge-shopify-config.example.js @@ -0,0 +1,2 @@ +shopify.config.locale; +// => 'en-CA' diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/basic-chat.example.ts b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/basic-chat.example.ts new file mode 100644 index 000000000..a93bb95e0 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/basic-chat.example.ts @@ -0,0 +1,13 @@ +import {extension, Chat} from '@shopify/ui-extensions/checkout'; + +// This component requires the configuration of the `extensions.targeting.preloads.chat` in the extensions configuration file. +// Its value will be used as the `src` attribute of the Chat component. + +export default extension('purchase.checkout.chat.render', (root) => { + const chat = root.createComponent(Chat, { + inlineSize: 100, + blockSize: 50, + }); + + root.appendChild(chat); +}); diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-custom-properties-css.example.css b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-custom-properties-css.example.css new file mode 100644 index 000000000..dfde429f2 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-custom-properties-css.example.css @@ -0,0 +1,11 @@ +.activator { + inline-size: 100%; + max-inline-size: var(--shopify-checkout-chat-minimized-max-inline-size); +} + +.dialog { + inline-size: min( + 100%, + var(--shopify-checkout-chat-maximized-max-inline-size) + ); +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-media-query.example.css b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-media-query.example.css new file mode 100644 index 000000000..f9bca2d39 --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/chat-media-query.example.css @@ -0,0 +1,9 @@ +.dialog { + border-radius: 1em; + inline-size: 200px; + + @media screen and (max-width: 569px) { + border-radius: 0; + inline-size: 100%; + } +} diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/include-app-bridge.example.html b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/include-app-bridge.example.html new file mode 100644 index 000000000..b8429429f --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/include-app-bridge.example.html @@ -0,0 +1,3 @@ + + + diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/shopify-extension-toml.example.toml b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/shopify-extension-toml.example.toml new file mode 100644 index 000000000..7760a9a1c --- /dev/null +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/examples/shopify-extension-toml.example.toml @@ -0,0 +1,5 @@ +[[extensions.targeting]] +target = "purchase.checkout.chat.render" + + [extensions.targeting.preloads] + chat = "https://my-chat-application.com" diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Icon/Icon.ts b/packages/ui-extensions/src/surfaces/checkout/components/Icon/Icon.ts index 793ee72ab..fee7058d5 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Icon/Icon.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Icon/Icon.ts @@ -61,6 +61,7 @@ export type IconSource = | 'question' | 'questionFill' | 'reorder' + | 'reset' | 'return' | 'savings' | 'settings' diff --git a/packages/ui-extensions/src/surfaces/checkout/components/shared.ts b/packages/ui-extensions/src/surfaces/checkout/components/shared.ts index 7343aa1fb..82a7c6ea3 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/shared.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/shared.ts @@ -349,7 +349,7 @@ export interface SpacingProps { * * - [`base`, `none`] means blockStart and blockEnd paddings are `base`, inlineStart and inlineEnd paddings are `none` * - * - [`base`, `none`, `loose`, `tight`] means blockStart padding is `base`, inlineEnd padding is `none`, blockEnd padding is `loose` and blockStart padding is `tight` + * - [`base`, `none`, `large200`, `small200`] means blockStart padding is `base`, inlineEnd padding is `none`, blockEnd padding is `large200` and blockStart padding is `small200` */ padding?: MaybeResponsiveConditionalStyle>; } @@ -503,11 +503,28 @@ export type Size = export type Spacing = | 'none' - | 'extraTight' - | 'tight' + | 'small500' + | 'small400' + | 'small300' + | 'small200' + | 'small100' | 'base' - | 'loose' - | 'extraLoose'; + | 'large100' + | 'large200' + | 'large300' + | 'large400' + | 'large500' + | SpacingDeprecated; + +/** @deprecated These values are deprecated and will eventually be removed. + * Use the new values. + * + * `extraTight`: `small400` + * `tight`: `small200` + * `loose`: `large200` + * `extraLoose`: `large500` + */ +export type SpacingDeprecated = 'extraTight' | 'tight' | 'loose' | 'extraLoose'; export type Alignment = 'start' | 'center' | 'end'; export type InlineAlignment = 'start' | 'center' | 'end'; diff --git a/packages/ui-extensions/src/surfaces/checkout/extension.ts b/packages/ui-extensions/src/surfaces/checkout/extension.ts index debbc493e..df68e1907 100644 --- a/packages/ui-extensions/src/surfaces/checkout/extension.ts +++ b/packages/ui-extensions/src/surfaces/checkout/extension.ts @@ -2,7 +2,12 @@ import {createExtensionRegistrationFunction} from '../../utilities/registration' import type {ExtensionTargets} from './targets'; -export * from '../../extension'; +export type { + RenderExtension, + RenderExtensionConnection, + RenderExtensionWithRemoteRoot, + RunnableExtension, +} from '../../extension'; export const extension = createExtensionRegistrationFunction(); diff --git a/packages/ui-extensions/src/surfaces/checkout/style/examples/defaultstyle.example.tsx b/packages/ui-extensions/src/surfaces/checkout/style/examples/defaultstyle.example.tsx index 44a69db35..3f462557c 100644 --- a/packages/ui-extensions/src/surfaces/checkout/style/examples/defaultstyle.example.tsx +++ b/packages/ui-extensions/src/surfaces/checkout/style/examples/defaultstyle.example.tsx @@ -6,4 +6,4 @@ > Content Content -; + diff --git a/packages/ui-extensions/src/surfaces/checkout/style/examples/hiding.example.tsx b/packages/ui-extensions/src/surfaces/checkout/style/examples/hiding.example.tsx index bd7ecda50..78e0af35c 100644 --- a/packages/ui-extensions/src/surfaces/checkout/style/examples/hiding.example.tsx +++ b/packages/ui-extensions/src/surfaces/checkout/style/examples/hiding.example.tsx @@ -5,4 +5,4 @@ )} > Content -; + diff --git a/packages/ui-extensions/src/surfaces/checkout/style/examples/simplecondition.example.tsx b/packages/ui-extensions/src/surfaces/checkout/style/examples/simplecondition.example.tsx index 8109d4d65..f20d3439e 100644 --- a/packages/ui-extensions/src/surfaces/checkout/style/examples/simplecondition.example.tsx +++ b/packages/ui-extensions/src/surfaces/checkout/style/examples/simplecondition.example.tsx @@ -6,4 +6,4 @@ )} > Content -; + diff --git a/packages/ui-extensions/src/surfaces/checkout/targets.ts b/packages/ui-extensions/src/surfaces/checkout/targets.ts index 5ec0b737d..efaf9c785 100644 --- a/packages/ui-extensions/src/surfaces/checkout/targets.ts +++ b/packages/ui-extensions/src/surfaces/checkout/targets.ts @@ -279,100 +279,6 @@ export interface RenderExtensionTargets { StandardApi<'Checkout::ThankYou::CustomerInformation::RenderAfter'>, AnyComponent >; - /** - * A [block extension target](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#block-extension-targets) that renders exclusively on the **Order status** page. - * Unlike static extension targets, block extension targets render where the merchant - * sets them using the [checkout editor](https://shopify.dev/apps/checkout/test-ui-extensions#test-the-extension-in-the-checkout-editor). - * - * The [supported locations](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations) for block extension targets can be previewed during development - * by [using a URL parameter](https://shopify.dev/docs/apps/checkout/best-practices/testing-ui-extensions#block-extension-targets). - * - * @deprecated Use `customer-account.order-status.block.render` from `@shopify/ui-extension/customer-account` instead. - */ - 'customer-account.order-status.block.render': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'customer-account.order-status.block.render'>, - AnyComponent - >; - /** - * A [block extension target](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#block-extension-targets) that renders exclusively on the **Order status** page. - * Unlike static extension targets, block extension targets render where the merchant - * sets them using the [checkout editor](https://shopify.dev/apps/checkout/test-ui-extensions#test-the-extension-in-the-checkout-editor). - * - * The [supported locations](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations) for block extension targets can be previewed during development - * by [using a URL parameter](https://shopify.dev/docs/apps/checkout/best-practices/testing-ui-extensions#block-extension-targets). - * - * @deprecated Use `customer-account.order-status.block.render` from `@shopify/ui-extension/customer-account` instead. - */ - 'Checkout::OrderStatus::Dynamic::Render': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'Checkout::OrderStatus::Dynamic::Render'>, - AnyComponent - >; - /** - * A static extension target that renders on every line item, inside the details - * under the line item properties element on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.cart-line-item.render-after` from `@shopify/ui-extension/customer-account` instead. - */ - 'customer-account.order-status.cart-line-item.render-after': RenderExtension< - CartLineItemApi & - OrderStatusApi & - CustomerAccountStandardApi<'customer-account.order-status.cart-line-item.render-after'>, - AnyComponent - >; - /** - * A static extension target that renders on every line item, inside the details - * under the line item properties element on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.cart-line-item.render-after` instead. - */ - 'Checkout::OrderStatus::CartLineDetails::RenderAfter': RenderExtension< - CartLineItemApi & - OrderStatusApi & - CustomerAccountStandardApi<'Checkout::OrderStatus::CartLineDetails::RenderAfter'>, - AnyComponent - >; - /** - * A static extension target that is rendered after all line items on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.cart-line-list.render-after` from `@shopify/ui-extension/customer-account` instead. - */ - 'customer-account.order-status.cart-line-list.render-after': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'customer-account.order-status.cart-line-list.render-after'>, - AnyComponent - >; - /** - * A static extension target that is rendered after all line items on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.cart-line-list.render-after` from `@shopify/ui-extension/customer-account` instead. - */ - 'Checkout::OrderStatus::CartLines::RenderAfter': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'Checkout::OrderStatus::CartLines::RenderAfter'>, - AnyComponent - >; - /** - * A static extension target that is rendered after a purchase below the customer information on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.customer-information.render-after` from `@shopify/ui-extension/customer-account` instead. - */ - 'customer-account.order-status.customer-information.render-after': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'customer-account.order-status.customer-information.render-after'>, - AnyComponent - >; - /** - * A static extension target that is rendered after a purchase below the customer information on the **Order status** page. - * - * @deprecated Use `customer-account.order-status.customer-information.render-after` from `@shopify/ui-extension/customer-account` instead. - */ - 'Checkout::OrderStatus::CustomerInformation::RenderAfter': RenderExtension< - OrderStatusApi & - CustomerAccountStandardApi<'Checkout::OrderStatus::CustomerInformation::RenderAfter'>, - AnyComponent - >; /** * A static extension target that renders the gift card entry form fields after * the buyer ticks a box to use a gift card. This does not replace the @@ -710,7 +616,7 @@ export interface RenderExtensionTargets { AnyComponent >; /** - * A static extension target that is rendered on top of the Checkout page as an overlay. + * A static extension target that is rendered on top of the checkout page as an overlay. * It is positioned in the bottom right corner of the screen. */ 'purchase.checkout.chat.render': RenderExtension< @@ -734,11 +640,11 @@ export interface RenderExtensionTargets { AnyComponent >; /** - * A static extension target that is rendered on top of the **Thank you** page as an overlay. + * A static extension target that is rendered on top of the **Thank you page** as an overlay. * It is positioned in the bottom right corner of the screen. */ 'purchase.thank-you.chat.render': RenderExtension< - CheckoutApi & StandardApi<'purchase.checkout.chat.render'>, + OrderConfirmationApi & StandardApi<'purchase.thank-you.chat.render'>, AllowedComponents<'Chat'> >; } @@ -861,42 +767,3 @@ export type RunnableExtensionTarget = keyof RunnableExtensionTargets; export type RunnableExtensions = { [Target in RunnableExtensionTarget]: RunnableExtensionTargets[Target]; }; - -/** - * The part of the standard API implemented for customer-account targets. Must - * match the types defined in the `surfaces/customer-account` section of this package. - */ -export interface CustomerAccountStandardApi< - Target extends keyof ExtensionTargets, -> extends Pick< - StandardApi, - | 'analytics' - | 'appliedGiftCards' - | 'appMetafields' - | 'attributes' - | 'buyerIdentity' - | 'checkoutSettings' - | 'checkoutToken' - | 'cost' - | 'discountCodes' - | 'discountAllocations' - | 'extension' - | 'extensionPoint' - | 'i18n' - | 'instructions' - | 'lines' - | 'localization' - | 'metafields' - | 'note' - | 'query' - | 'sessionToken' - | 'settings' - | 'shippingAddress' - | 'billingAddress' - | 'shop' - | 'storage' - | 'ui' - | 'version' - | 'customerPrivacy' - | 'applyTrackingConsentChange' - > {} From 92f69f2d7f908eb49f4d020a622e11659875ff5a Mon Sep 17 00:00:00 2001 From: Jean-Frederic Fortier Date: Wed, 6 Nov 2024 19:13:19 +0000 Subject: [PATCH 06/15] Remove changes unrelated to Chat --- packages/ui-extensions-react/README.md | 2 +- .../surfaces/checkout/hooks/buyer-journey.ts | 20 ++- .../checkout/hooks/cart-line-target.ts | 2 + .../checkout/hooks/delivery-groups.ts | 7 + .../checkout/hooks/payment-options.ts | 22 ++- .../src/surfaces/checkout/hooks/target.ts | 5 +- .../hooks/tests/buyer-journey.test.ts | 42 ++++++ packages/ui-extensions/README.md | 2 +- .../docs/surfaces/checkout/build-docs.sh | 6 +- .../reference/examples/query-fetch.example.ts | 18 ++- .../examples/query-fetch.example.tsx | 19 ++- .../checkout/reference/helper.docs.ts | 6 - .../checkout/staticPages/configuration.doc.ts | 14 +- packages/ui-extensions/src/extension.ts | 8 +- packages/ui-extensions/src/index.ts | 9 +- .../checkout/components/Badge/Badge.ts | 2 +- .../checkout/components/Chat/AppBridge.ts | 6 + .../surfaces/checkout/components/shared.ts | 27 +--- .../src/surfaces/checkout/extension.ts | 7 +- .../src/surfaces/checkout/targets.ts | 133 ++++++++++++++++++ 20 files changed, 274 insertions(+), 83 deletions(-) diff --git a/packages/ui-extensions-react/README.md b/packages/ui-extensions-react/README.md index f0b4a0433..efd3a97b5 100644 --- a/packages/ui-extensions-react/README.md +++ b/packages/ui-extensions-react/README.md @@ -6,7 +6,7 @@ This package contains the public type definitions and utilities needed to create Currently, this package only contains the extension APIs for the [`checkout` surface](./src/surfaces/checkout), but other Shopify surfaces will be added here soon. -All extensions, regardless of where they appear in Shopify, make use the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. +All extensions, regardless of where they appear in Shopify, make use of the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. A checkout extension using React would be written as follows: diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts index b7dca165d..4ad30a1a2 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/buyer-journey.ts @@ -19,7 +19,14 @@ export function useBuyerJourney< >(): BuyerJourney { const api = useApi(); - return api.buyerJourney; + if ('buyerJourney' in api) { + return api.buyerJourney; + } + + throw new ExtensionHasNoMethodError( + 'applyAttributeChange', + api.extension.target, + ); } /** @@ -31,7 +38,12 @@ export function useBuyerJourneyCompleted< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): boolean { const api = useApi(); - return useSubscription(api.buyerJourney.completed); + + if ('buyerJourney' in api) { + return useSubscription(api.buyerJourney.completed); + } + + throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target); } /** @@ -48,6 +60,10 @@ export function useBuyerJourneyIntercept< >(interceptor: Interceptor): void { const api = useApi(); + if (!('buyerJourney' in api)) { + throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target); + } + const interceptorRef = useRef(interceptor); interceptorRef.current = interceptor; diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts index ae4fae955..7100fde56 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/cart-line-target.ts @@ -11,12 +11,14 @@ import {useSubscription} from './subscription'; * - `purchase.cart-line-item.line-components.render` * - `purchase.checkout.cart-line-item.render-after` * - `purchase.thank-you.cart-line-item.render-after` + * - 'customer-account.order-status.cart-line-item.render-after' */ export function useCartLineTarget(): CartLine { const api = useApi< | 'purchase.cart-line-item.line-components.render' | 'purchase.checkout.cart-line-item.render-after' | 'purchase.thank-you.cart-line-item.render-after' + | 'customer-account.order-status.cart-line-item.render-after' >(); if (!api.target) { throw new ExtensionHasNoTargetError( diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts index cede53520..f7465b5b6 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/delivery-groups.ts @@ -3,6 +3,8 @@ import type { RenderExtensionTarget, } from '@shopify/ui-extensions/checkout'; +import {ExtensionHasNoMethodError} from '../errors'; + import {useApi} from './api'; import {useSubscription} from './subscription'; @@ -14,5 +16,10 @@ export function useDeliveryGroups< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): DeliveryGroup[] { const api = useApi(); + + if (!('deliveryGroups' in api)) { + throw new ExtensionHasNoMethodError('deliveryGroups', api.extension.target); + } + return useSubscription(api.deliveryGroups); } diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts index b50763e13..bea0176b4 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/payment-options.ts @@ -4,6 +4,8 @@ import type { SelectedPaymentOption, } from '@shopify/ui-extensions/checkout'; +import {ExtensionHasNoMethodError} from '../errors'; + import {useApi} from './api'; import {useSubscription} from './subscription'; @@ -14,7 +16,15 @@ export function useAvailablePaymentOptions< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): PaymentOption[] { const api = useApi(); - return useSubscription(api.availablePaymentOptions); + + if ('availablePaymentOptions' in api) { + return useSubscription(api.availablePaymentOptions); + } + + throw new ExtensionHasNoMethodError( + 'availablePaymentOptions', + api.extension.target, + ); } /** @@ -24,5 +34,13 @@ export function useSelectedPaymentOptions< Target extends RenderExtensionTarget = RenderExtensionTarget, >(): SelectedPaymentOption[] { const api = useApi(); - return useSubscription(api.selectedPaymentOptions); + + if ('selectedPaymentOptions' in api) { + return useSubscription(api.selectedPaymentOptions); + } + + throw new ExtensionHasNoMethodError( + 'selectedPaymentOptions', + api.extension.target, + ); } diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts index 6f7f1d579..c6995fcfe 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/target.ts @@ -15,8 +15,8 @@ class ExtensionHasNoTargetError extends Error { /** * Returns the cart line the extension is attached to. This hook can only be used by extensions in the - * `purchase.cart-line-item.line-components.render`, `purchase.checkout.cart-line-item.render-after`, and - * `purchase.thank-you.cart-line-item.render-after` + * `purchase.cart-line-item.line-components.render`, `purchase.checkout.cart-line-item.render-after`, + * `purchase.thank-you.cart-line-item.render-after`, and `customer-account.order-status.cart-line-item.render-after` * extension targets. Until version `2023-04`, this hook returned a `PresentmentCartLine` object. * * > Caution: Deprecated as of version `2023-10`, use `useCartLineTarget()` instead. @@ -28,6 +28,7 @@ export function useTarget(): CartLine { | 'purchase.cart-line-item.line-components.render' | 'purchase.checkout.cart-line-item.render-after' | 'purchase.thank-you.cart-line-item.render-after' + | 'customer-account.order-status.cart-line-item.render-after' >(); if (!api.target) { throw new ExtensionHasNoTargetError(api.extension.target); diff --git a/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts b/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts index aeb4f70e7..6907b18a9 100644 --- a/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts +++ b/packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/buyer-journey.test.ts @@ -151,6 +151,18 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourney()', () => { + it('raises an exception when buyerJourney api is not available', () => { + expect(() => { + mount.hook(() => useBuyerJourney(), { + extensionApi: { + extension: { + target: 'purchase.checkout.header.render-after', + }, + }, + }); + }).toThrow(ExtensionHasNoMethodError); + }); + it('returns the buyer journey when the api is available', () => { const hook = mount.hook(() => useBuyerJourney(), { extensionApi: { @@ -166,6 +178,18 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourneyCompleted()', () => { + it('raises an exception when buyerJourney api is not available', () => { + expect(() => { + mount.hook(() => useBuyerJourneyCompleted(), { + extensionApi: { + extension: { + target: 'purchase.checkout.header.render-after', + }, + }, + }); + }).toThrow(ExtensionHasNoMethodError); + }); + it.each([true, false])( 'returns the buyer journey completed value: %s', (completed) => { @@ -186,6 +210,24 @@ describe('buyerJourney Hooks', () => { }); describe('useBuyerJourneyIntercept()', () => { + it('raises an exception when buyerJourney api is not available', () => { + expect(() => { + mount.hook( + () => + useBuyerJourneyIntercept(() => ({ + behavior: 'allow', + })), + { + extensionApi: { + extension: { + target: 'purchase.checkout.header.render-after', + }, + }, + }, + ); + }).toThrow(ExtensionHasNoMethodError); + }); + it('calls the interceptor function', () => { const mockIntercept = jest.fn(() => Promise.resolve({behavior: 'allow'} as const), diff --git a/packages/ui-extensions/README.md b/packages/ui-extensions/README.md index 6bbd66fe7..e84b5e73f 100644 --- a/packages/ui-extensions/README.md +++ b/packages/ui-extensions/README.md @@ -6,7 +6,7 @@ This package contains the public type definitions and utilities needed to create Currently, this package only contains the extension APIs for the [`checkout`](./src/surfaces/checkout) and [`admin`](./src/surfaces/admin) surfaces, but other Shopify surfaces will be added here soon. -All extensions, regardless of where they appear in Shopify, make use the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. +All extensions, regardless of where they appear in Shopify, make use of the same [underlying technology](../../documentation/how-extensions-work.md), and most of the same “core” components (e.g., `BlockStack`, `Button`, `TextField`, etc) and capabilities (e.g., direct API access, session tokens). Separating APIs by surface makes it easier for a developer to see what is available to them in each context, and gives us a flexible system for introducing components and APIs available in only some areas of Shopify. A checkout extension using “vanilla” JavaScript would be written as follows: diff --git a/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh b/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh index 59e246a1c..d65549413 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh +++ b/packages/ui-extensions/docs/surfaces/checkout/build-docs.sh @@ -22,15 +22,15 @@ run_sed() { if [ -z $API_VERSION ] then API_VERSION="unstable" - echo "Building docs for 'unstable' checkout UI extensions API. You can add a calver version argument (e.g. 'pnpm docs:checkout 2023-07') to generate the docs for a stable version." + echo "Building docs for 'unstable' checkout UI extensions API. You can add a calver version argument (e.g. 'yarn docs:checkout 2023-07') to generate the docs for a stable version." else echo "Building docs for '$API_VERSION' checkout UI extensions API." echo "When generating docs for a stable version, 'unstable' docs are not regenerated. This avoids overwriting other unstable changes that are not included in this version." echo "If you need to update the 'unstable' version, run this command again without the '$API_VERSION' parameter." fi -COMPILE_DOCS="pnpm tsc --project $DOCS_PATH/tsconfig.docs.json --types react --moduleResolution node --target esNext --module CommonJS && pnpm generate-docs --overridePath ./$DOCS_PATH/typeOverride.json --input ./$DOCS_PATH/reference ./$SRC_PATH --typesInput ./$SRC_PATH ../ui-extensions-react/$SRC_PATH --output ./$DOCS_PATH/generated" -COMPILE_STATIC_PAGES="pnpm tsc $DOCS_PATH/staticPages/*.doc.ts --types react --moduleResolution node --target esNext --module CommonJS && pnpm generate-docs --isLandingPage --input ./$DOCS_PATH/staticPages --output ./$DOCS_PATH/generated" +COMPILE_DOCS="yarn tsc --project $DOCS_PATH/tsconfig.docs.json --types react --moduleResolution node --target esNext --module CommonJS && yarn generate-docs --overridePath ./$DOCS_PATH/typeOverride.json --input ./$DOCS_PATH/reference ./$SRC_PATH --typesInput ./$SRC_PATH ../ui-extensions-react/$SRC_PATH --output ./$DOCS_PATH/generated" +COMPILE_STATIC_PAGES="yarn tsc $DOCS_PATH/staticPages/*.doc.ts --types react --moduleResolution node --target esNext --module CommonJS && yarn generate-docs --isLandingPage --input ./$DOCS_PATH/staticPages --output ./$DOCS_PATH/generated" if echo "$PWD" | grep -q '\checkout-web'; then diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts index d7cf051b0..f132cdaa1 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.ts @@ -6,7 +6,8 @@ import { export default extension( 'purchase.checkout.block.render', - (root) => { + (root, {shop}) => { + const apiVersion = 'unstable'; const getProductsQuery = { query: `query ($first: Int!) { products(first: $first) { @@ -19,13 +20,16 @@ export default extension( variables: {first: 5}, }; - fetch('shopify:storefront/api/graphql.json', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + fetch( + `${shop.storefrontUrl}api/${apiVersion}/graphql.json`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(getProductsQuery), }, - body: JSON.stringify(getProductsQuery), - }) + ) .then((response) => response.json()) .then(({data}) => { const listItems = diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx index 95649e813..0a8dc709a 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/examples/query-fetch.example.tsx @@ -28,17 +28,22 @@ function Extension() { variables: {first: 5}, }; - fetch('shopify:storefront/api/graphql.json', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + const apiVersion = 'unstable'; + + fetch( + `${shop.storefrontUrl}api/${apiVersion}/graphql.json`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(getProductsQuery), }, - body: JSON.stringify(getProductsQuery), - }) + ) .then((response) => response.json()) .then(({data, errors}) => setData(data)) .catch(console.error); - }); + }, [shop]); return ( diff --git a/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts b/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts index 2de039224..5ca1e8e86 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/reference/helper.docs.ts @@ -339,12 +339,6 @@ Ensure your extension can use this API by [enabling the \`api_access\` capabilit description: ` You can access the [Storefront GraphQL API](/docs/api/storefront) using global \`fetch()\`. Ensure your extension can access the Storefront API via the [\`api_access\` capability](/docs/api/checkout-ui-extensions/configuration#api-access). - -The \`shopify:storefront\` protocol will automatically infer your Storefront URL and API version declared in your extension config. - -By omitting the API version (recommended), Shopify will use your API version configured in \`shopify.extension.toml\`. To change the API version, simply add it to the URL like \`shopify:storefront/api/2024-04/graphql.json\`. - -See [Storefront GraphQL API endpoints](/docs/api/storefront#endpoints) for more information. `, codeblock: { title: 'Accessing the Storefront API with fetch()', diff --git a/packages/ui-extensions/docs/surfaces/checkout/staticPages/configuration.doc.ts b/packages/ui-extensions/docs/surfaces/checkout/staticPages/configuration.doc.ts index 2aecd9591..70873a4c0 100644 --- a/packages/ui-extensions/docs/surfaces/checkout/staticPages/configuration.doc.ts +++ b/packages/ui-extensions/docs/surfaces/checkout/staticPages/configuration.doc.ts @@ -155,7 +155,7 @@ Defines the [capabilities](/docs/api/checkout-ui-extensions/apis/standardapi#pro { name: 'API access examples', subtitle: 'See', - url: '/docs/api/checkout-ui-extensions/apis/storefront-api#examples', + url: '/docs/api/checkout-ui-extensions/apis/standardapi#example-storefront-api-access', type: 'blocks', }, ], @@ -170,7 +170,7 @@ Defines the [capabilities](/docs/api/checkout-ui-extensions/apis/standardapi#pro }, { title: 'Methods for accessing the Storefront API', - sectionContent: `Enabling the \`api_access\` capability allows you to use the Standard API [\`query\`](/docs/api/checkout-ui-extensions/apis/storefront-api) method and the global \`fetch\` to retrieve data from the [Storefront API](/api/storefront) without manually managing token aquisition and refresh. + sectionContent: `Enabling the \`api_access\` capability allows you to use the Standard API [\`query\`](/docs/api/checkout-ui-extensions/apis/standardapi#properties-propertydetail-query) method and the global \`fetch\` to retrieve data from the [Storefront API](/api/storefront) without manually managing token aquisition and refresh. \`query\` lets you request a single GraphQL response from the Storefront API. @@ -194,12 +194,6 @@ Your extensions will have the following unauthenticated access scopes to the Sto - unauthenticated_read_metaobjects `, }, - { - title: 'Protocol Links', - sectionContent: ` -Protocol links are an easy way for Shopify to infer the type of request you are trying to make. If you would like to make a request to the [Storefront GraphQL API](/docs/api/storefront), you can use our [Storefront Protocol](/docs/api/checkout-ui-extensions/unstable/apis/storefront-api#examples) to infer your Storefront URL and API version. - `, - }, ], }, { @@ -475,13 +469,9 @@ You retrieve these metafields in your extension by reading [\`appMetafields\`](/ title: 'Preloads definition', sectionContent: ` For specific targets, you must provide the URL of assets or pages loaded by UI components within its extension. This allows Shopify to preload them as early as possible and ensure a performant experience for buyers. - Currently, the only supported component is \`chat\`. - The URL for the iframe used in this extension target. The URL can be absolute or relative. Relative URLs are resolved against the app URL. - For example, - * if the app URL is \`https://example.com\` and \`chat = "/my-chat-application"\`, the resolved URL will be \`https://example.com/my-chat-application\`. * if \`chat = "https://my-chat-application.com"\`, the resolved URL will be \`https://my-chat-application.com\`. `, diff --git a/packages/ui-extensions/src/extension.ts b/packages/ui-extensions/src/extension.ts index f4d1251a8..6047d1e38 100644 --- a/packages/ui-extensions/src/extension.ts +++ b/packages/ui-extensions/src/extension.ts @@ -37,10 +37,10 @@ export interface RenderExtensionWithRemoteRoot< any > = RemoteComponentType, > { - ( - root: RemoteRoot, - api: Api, - ): void | Promise; + (root: RemoteRoot, api: Api): + | void + | Promise + | Promise<() => void>; } export interface RunnableExtension { diff --git a/packages/ui-extensions/src/index.ts b/packages/ui-extensions/src/index.ts index c5d0da7b3..bcf51eb95 100644 --- a/packages/ui-extensions/src/index.ts +++ b/packages/ui-extensions/src/index.ts @@ -1,7 +1,2 @@ -export type {I18n, I18nTranslate} from './api'; -export type { - RenderExtension, - RenderExtensionConnection, - RenderExtensionWithRemoteRoot, - RunnableExtension, -} from './extension'; +export * from './api'; +export * from './extension'; diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts b/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts index b76e5f229..a2bd251c4 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Badge/Badge.ts @@ -3,7 +3,7 @@ import {createRemoteComponent} from '@remote-ui/core'; import type {Size, VisibilityProps} from '../shared'; import type {IconSource} from '../Icon/Icon'; -type Tone = 'default' | 'accent' | 'critical' | 'subdued'; +type Tone = 'default' | 'critical' | 'subdued'; export interface BadgeProps extends VisibilityProps { /** diff --git a/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts b/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts index 5e54e0c1d..5eed16501 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/Chat/AppBridge.ts @@ -1,3 +1,7 @@ +export {}; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore interface AppBridge { /** * The static configuration values that will not change during runtime. @@ -74,6 +78,8 @@ interface Extension { * * Learn more about [resizeTo() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo). */ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore resizeTo?: Window['resizeTo']; } diff --git a/packages/ui-extensions/src/surfaces/checkout/components/shared.ts b/packages/ui-extensions/src/surfaces/checkout/components/shared.ts index 82a7c6ea3..7343aa1fb 100644 --- a/packages/ui-extensions/src/surfaces/checkout/components/shared.ts +++ b/packages/ui-extensions/src/surfaces/checkout/components/shared.ts @@ -349,7 +349,7 @@ export interface SpacingProps { * * - [`base`, `none`] means blockStart and blockEnd paddings are `base`, inlineStart and inlineEnd paddings are `none` * - * - [`base`, `none`, `large200`, `small200`] means blockStart padding is `base`, inlineEnd padding is `none`, blockEnd padding is `large200` and blockStart padding is `small200` + * - [`base`, `none`, `loose`, `tight`] means blockStart padding is `base`, inlineEnd padding is `none`, blockEnd padding is `loose` and blockStart padding is `tight` */ padding?: MaybeResponsiveConditionalStyle>; } @@ -503,28 +503,11 @@ export type Size = export type Spacing = | 'none' - | 'small500' - | 'small400' - | 'small300' - | 'small200' - | 'small100' + | 'extraTight' + | 'tight' | 'base' - | 'large100' - | 'large200' - | 'large300' - | 'large400' - | 'large500' - | SpacingDeprecated; - -/** @deprecated These values are deprecated and will eventually be removed. - * Use the new values. - * - * `extraTight`: `small400` - * `tight`: `small200` - * `loose`: `large200` - * `extraLoose`: `large500` - */ -export type SpacingDeprecated = 'extraTight' | 'tight' | 'loose' | 'extraLoose'; + | 'loose' + | 'extraLoose'; export type Alignment = 'start' | 'center' | 'end'; export type InlineAlignment = 'start' | 'center' | 'end'; diff --git a/packages/ui-extensions/src/surfaces/checkout/extension.ts b/packages/ui-extensions/src/surfaces/checkout/extension.ts index df68e1907..debbc493e 100644 --- a/packages/ui-extensions/src/surfaces/checkout/extension.ts +++ b/packages/ui-extensions/src/surfaces/checkout/extension.ts @@ -2,12 +2,7 @@ import {createExtensionRegistrationFunction} from '../../utilities/registration' import type {ExtensionTargets} from './targets'; -export type { - RenderExtension, - RenderExtensionConnection, - RenderExtensionWithRemoteRoot, - RunnableExtension, -} from '../../extension'; +export * from '../../extension'; export const extension = createExtensionRegistrationFunction(); diff --git a/packages/ui-extensions/src/surfaces/checkout/targets.ts b/packages/ui-extensions/src/surfaces/checkout/targets.ts index efaf9c785..079d8bea2 100644 --- a/packages/ui-extensions/src/surfaces/checkout/targets.ts +++ b/packages/ui-extensions/src/surfaces/checkout/targets.ts @@ -279,6 +279,100 @@ export interface RenderExtensionTargets { StandardApi<'Checkout::ThankYou::CustomerInformation::RenderAfter'>, AnyComponent >; + /** + * A [block extension target](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#block-extension-targets) that renders exclusively on the **Order status** page. + * Unlike static extension targets, block extension targets render where the merchant + * sets them using the [checkout editor](https://shopify.dev/apps/checkout/test-ui-extensions#test-the-extension-in-the-checkout-editor). + * + * The [supported locations](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations) for block extension targets can be previewed during development + * by [using a URL parameter](https://shopify.dev/docs/apps/checkout/best-practices/testing-ui-extensions#block-extension-targets). + * + * @deprecated Use `customer-account.order-status.block.render` from `@shopify/ui-extension/customer-account` instead. + */ + 'customer-account.order-status.block.render': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'customer-account.order-status.block.render'>, + AnyComponent + >; + /** + * A [block extension target](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#block-extension-targets) that renders exclusively on the **Order status** page. + * Unlike static extension targets, block extension targets render where the merchant + * sets them using the [checkout editor](https://shopify.dev/apps/checkout/test-ui-extensions#test-the-extension-in-the-checkout-editor). + * + * The [supported locations](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations) for block extension targets can be previewed during development + * by [using a URL parameter](https://shopify.dev/docs/apps/checkout/best-practices/testing-ui-extensions#block-extension-targets). + * + * @deprecated Use `customer-account.order-status.block.render` from `@shopify/ui-extension/customer-account` instead. + */ + 'Checkout::OrderStatus::Dynamic::Render': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'Checkout::OrderStatus::Dynamic::Render'>, + AnyComponent + >; + /** + * A static extension target that renders on every line item, inside the details + * under the line item properties element on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.cart-line-item.render-after` from `@shopify/ui-extension/customer-account` instead. + */ + 'customer-account.order-status.cart-line-item.render-after': RenderExtension< + CartLineItemApi & + OrderStatusApi & + CustomerAccountStandardApi<'customer-account.order-status.cart-line-item.render-after'>, + AnyComponent + >; + /** + * A static extension target that renders on every line item, inside the details + * under the line item properties element on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.cart-line-item.render-after` instead. + */ + 'Checkout::OrderStatus::CartLineDetails::RenderAfter': RenderExtension< + CartLineItemApi & + OrderStatusApi & + CustomerAccountStandardApi<'Checkout::OrderStatus::CartLineDetails::RenderAfter'>, + AnyComponent + >; + /** + * A static extension target that is rendered after all line items on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.cart-line-list.render-after` from `@shopify/ui-extension/customer-account` instead. + */ + 'customer-account.order-status.cart-line-list.render-after': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'customer-account.order-status.cart-line-list.render-after'>, + AnyComponent + >; + /** + * A static extension target that is rendered after all line items on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.cart-line-list.render-after` from `@shopify/ui-extension/customer-account` instead. + */ + 'Checkout::OrderStatus::CartLines::RenderAfter': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'Checkout::OrderStatus::CartLines::RenderAfter'>, + AnyComponent + >; + /** + * A static extension target that is rendered after a purchase below the customer information on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.customer-information.render-after` from `@shopify/ui-extension/customer-account` instead. + */ + 'customer-account.order-status.customer-information.render-after': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'customer-account.order-status.customer-information.render-after'>, + AnyComponent + >; + /** + * A static extension target that is rendered after a purchase below the customer information on the **Order status** page. + * + * @deprecated Use `customer-account.order-status.customer-information.render-after` from `@shopify/ui-extension/customer-account` instead. + */ + 'Checkout::OrderStatus::CustomerInformation::RenderAfter': RenderExtension< + OrderStatusApi & + CustomerAccountStandardApi<'Checkout::OrderStatus::CustomerInformation::RenderAfter'>, + AnyComponent + >; /** * A static extension target that renders the gift card entry form fields after * the buyer ticks a box to use a gift card. This does not replace the @@ -767,3 +861,42 @@ export type RunnableExtensionTarget = keyof RunnableExtensionTargets; export type RunnableExtensions = { [Target in RunnableExtensionTarget]: RunnableExtensionTargets[Target]; }; + +/** + * The part of the standard API implemented for customer-account targets. Must + * match the types defined in the `surfaces/customer-account` section of this package. + */ +export interface CustomerAccountStandardApi< + Target extends keyof ExtensionTargets, +> extends Pick< + StandardApi, + | 'analytics' + | 'appliedGiftCards' + | 'appMetafields' + | 'attributes' + | 'buyerIdentity' + | 'checkoutSettings' + | 'checkoutToken' + | 'cost' + | 'discountCodes' + | 'discountAllocations' + | 'extension' + | 'extensionPoint' + | 'i18n' + | 'instructions' + | 'lines' + | 'localization' + | 'metafields' + | 'note' + | 'query' + | 'sessionToken' + | 'settings' + | 'shippingAddress' + | 'billingAddress' + | 'shop' + | 'storage' + | 'ui' + | 'version' + | 'customerPrivacy' + | 'applyTrackingConsentChange' + > {} From aacea261a1d7e5d1709b632a58323d5afee63a65 Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Sat, 2 Nov 2024 01:25:07 +0000 Subject: [PATCH 07/15] Add POS UI ext Print API tutorial Update print api doc comment about app backend Add print images --- .../reference/apis/print-api.doc.ts | 42 ++- .../reference/components/PrintPreview.doc.ts | 26 +- .../examples/print-api/print-full-url.tsx | 2 + .../examples/print-api/print-relative.tsx | 3 + .../examples/print-preview/default.example.ts | 6 +- .../print-preview/default.example.tsx | 4 +- .../reference/helpers/generateCodeBlock.ts | 17 + .../screenshots/print-preview-default.png | Bin 0 -> 54192 bytes .../screenshots/print-preview-thumbnail.png | Bin 0 -> 16382 bytes .../examples/print-example/print-modal.tsx | 156 +++++++++ .../examples/print-example/print-tile.tsx | 24 ++ .../print-example/remix-route-example.js | 155 +++++++++ .../print-example/shopify.extension.toml | 16 + .../pages/example-print-extension.doc.ts | 310 ++++++++++++++++++ 14 files changed, 749 insertions(+), 12 deletions(-) create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-full-url.tsx create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-relative.tsx create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/screenshots/print-preview-default.png create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/screenshots/print-preview-thumbnail.png create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/staticPages/examples/print-example/print-modal.tsx create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/staticPages/examples/print-example/print-tile.tsx create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/staticPages/examples/print-example/remix-route-example.js create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/staticPages/examples/print-example/shopify.extension.toml create mode 100644 packages/ui-extensions/docs/surfaces/point-of-sale/staticPages/pages/example-print-extension.doc.ts diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/print-api.doc.ts b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/print-api.doc.ts index 1ccdc4c47..232a48c47 100644 --- a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/print-api.doc.ts +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/apis/print-api.doc.ts @@ -1,20 +1,31 @@ import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'; -import {generateCodeBlock} from '../helpers/generateCodeBlock'; +import { + generateCodeBlock, + generateTSXCodeBlock, +} from '../helpers/generateCodeBlock'; const generateCodeBlockForPrintApi = (title: string, fileName: string) => generateCodeBlock(title, 'print-api', fileName); const data: ReferenceEntityTemplateSchema = { name: 'Print API', - description: ` -The Print API provides access to printing functionality. -`, + description: `The Print API enables document printing functionality in your point of sale extension. Use this API to trigger the native print dialog for your documents. + +The \`print()\` method accepts either: +- A relative path that will be appended to your app's [application_url](/docs/apps/build/cli-for-apps/app-configuration#application_url) +- A full URL to your app's backend that will be used to return the document to print + +Supported document types: +- HTML documents (recommended for best printing experience) +- Text files +- Image files (PNG, JPEG, etc.) +- PDF files (Note: On Android devices, PDFs will be downloaded and must be printed using an external application)`, isVisualComponent: false, type: 'APIs', definitions: [ { title: 'PrintApi', - description: '', + description: 'Interface for handling print operations', type: 'PrintApiContent', }, ], @@ -22,9 +33,14 @@ The Print API provides access to printing functionality. related: [ { name: 'PrintPreview Component', - subtitle: 'See how to use the Print API with a PrintPreview.', + subtitle: 'Preview documents before printing', url: '/api/pos-ui-extensions/components/printpreview', }, + { + name: 'Build a Print Extension', + subtitle: 'Learn how to implement printing', + url: '/docs/api/pos-ui-extensions/examples/print-extension', + }, ], examples: { description: 'Examples of using the Print API', @@ -35,6 +51,20 @@ The Print API provides access to printing functionality. 'print', ), }, + { + codeblock: generateTSXCodeBlock( + 'Print with relative path', + 'print-api', + 'print-relative', + ), + }, + { + codeblock: generateTSXCodeBlock( + 'Print with full URL', + 'print-api', + 'print-full-url', + ), + }, ], }, }; diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/components/PrintPreview.doc.ts b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/components/PrintPreview.doc.ts index 9004de694..d9d327a86 100644 --- a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/components/PrintPreview.doc.ts +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/components/PrintPreview.doc.ts @@ -6,13 +6,24 @@ const generateCodeBlockForPrintPreview = (title: string, fileName: string) => const data: ReferenceEntityTemplateSchema = { name: 'PrintPreview', - description: 'Renders a `PrintPreview`.', + description: `A component that displays a preview of a printable document. Use this component to let users review documents before printing. + +The \`src\` prop accepts either: +- A relative path that will be appended to your app's [application_url](/docs/apps/build/cli-for-apps/app-configuration#application_url) +- A full URL to your document endpoint + +Supported document types: +- HTML documents (recommended for best preview experience) +- Text files +- Image files (PNG, JPEG, etc.) +- PDF files (Note: On Android devices, PDFs will be downloaded and must be printed using an external application)`, isVisualComponent: true, type: 'component', + thumbnail: 'print-preview-thumbnail.png', definitions: [ { title: 'PrintPreview', - description: '', + description: 'Renders a preview of a printable document', type: 'PrintPreviewProps', }, ], @@ -20,13 +31,20 @@ const data: ReferenceEntityTemplateSchema = { related: [ { name: 'Print API', - subtitle: 'See how to use the Print API.', + subtitle: 'Handle print operations', url: '/api/pos-ui-extensions/apis/print-api', }, + { + name: 'Build a Print Extension', + subtitle: 'Learn how to implement printing', + url: '/docs/api/pos-ui-extensions/examples/print-extension', + }, ], defaultExample: { + image: 'print-preview-default.png', + description: 'Basic usage with relative and full URLs:', codeblock: generateCodeBlockForPrintPreview( - 'Render a PrintPreview and a button for printing', + 'Basic PrintPreview', 'default.example', ), }, diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-full-url.tsx b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-full-url.tsx new file mode 100644 index 000000000..a1470f9d9 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-full-url.tsx @@ -0,0 +1,2 @@ +// Using a full URL directly +await print.print('https://my-print-service.com/api/print/document'); diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-relative.tsx b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-relative.tsx new file mode 100644 index 000000000..faafccf17 --- /dev/null +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-api/print-relative.tsx @@ -0,0 +1,3 @@ +// If your application_url is "https://my-app.com" +// This will resolve to "https://my-app.com/api/print/document" +await print.print('/api/print/document'); diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.ts b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.ts index 68cb21cff..af55a52f9 100644 --- a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.ts +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.ts @@ -20,7 +20,10 @@ export default extension( Button, { title: 'Print', - onPress: () => api.print.print(), + onPress: () => + api.print.print( + '/documents/test-print', + ), }, ); @@ -32,6 +35,7 @@ export default extension( ); homeScreen.append(printPreview); + homeScreen.append(printButton); root.append(homeScreen); }, diff --git a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.tsx b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.tsx index d27427368..c2980f548 100644 --- a/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.tsx +++ b/packages/ui-extensions/docs/surfaces/point-of-sale/reference/examples/print-preview/default.example.tsx @@ -15,7 +15,9 @@ const Modal = () => {