Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-drexler committed Nov 21, 2024
1 parent 318b8ed commit fe20446
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 61 deletions.
6 changes: 6 additions & 0 deletions .changeset/shiny-owls-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/ui-extensions-react': minor
'@shopify/ui-extensions': minor
---

wip
3 changes: 3 additions & 0 deletions packages/ui-extensions-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
"dependencies": {
"@remote-ui/async-subscription": "^2.1.12",
"@remote-ui/react": "^5.0.2",
"@remote-dom/react": "^1.2.1",
"react-dom": "^18.3.1",
"@types/react": ">=18.2.67"
},
"peerDependencies": {
Expand All @@ -81,6 +83,7 @@
"@faker-js/faker": "^8.4.1",
"@quilted/react-testing": "^0.5.31",
"@shopify/ui-extensions": "0.0.0-unstable",
"@types/react-dom": "^18.3.0",
"react": "^18.0.0",
"react-reconciler": "0.29.0",
"react-test-renderer": "^18.2.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import {Button as BaseButton} from '@shopify/ui-extensions/checkout';
import {createRemoteReactComponent} from '@remote-ui/react';
import type {ReactPropsFromRemoteComponentType} from '@remote-ui/react';
import {createRemoteComponent} from '@remote-dom/react';

// @ts-ignore
export type ButtonProps = ReactPropsFromRemoteComponentType<typeof BaseButton>;

export const Button = createRemoteReactComponent(BaseButton, {
fragmentProps: ['overlay'],
export const Button = createRemoteComponent('ui-button', BaseButton, {
eventProps: {
onPress: {event: 'press'},
},
slots: ['overlay'],
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {Link as BaseLink} from '@shopify/ui-extensions/checkout';
import {createRemoteReactComponent} from '@remote-ui/react';
import type {ReactPropsFromRemoteComponentType} from '@remote-ui/react';
import {createRemoteComponent} from '@remote-dom/react';

export type LinkProps = ReactPropsFromRemoteComponentType<typeof BaseLink>;

export const Link = createRemoteReactComponent(BaseLink, {
fragmentProps: ['overlay'],
});
export const Link = createRemoteComponent('ui-link', BaseLink);
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {Modal as BaseModal} from '@shopify/ui-extensions/checkout';
import {createRemoteReactComponent} from '@remote-ui/react';
import type {ReactPropsFromRemoteComponentType} from '@remote-ui/react';
import {createRemoteComponent} from '@remote-dom/react';

// @ts-ignore
export type ModalProps = ReactPropsFromRemoteComponentType<typeof BaseModal>;

export const Modal = createRemoteReactComponent(BaseModal, {
fragmentProps: ['primaryAction', 'secondaryActions'],
});
export const Modal = createRemoteComponent('ui-modal', BaseModal);
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {View as BaseView} from '@shopify/ui-extensions/checkout';
import {createRemoteReactComponent} from '@remote-ui/react';
//@ts-ignore
import {createRemoteComponent} from '@remote-dom/react';
import type {ReactPropsFromRemoteComponentType} from '@remote-ui/react';

export type ViewProps = ReactPropsFromRemoteComponentType<typeof BaseView>;

export const View = createRemoteReactComponent(BaseView);
export const View = createRemoteComponent('ui-view', BaseView);
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export * from './PolicyModal';
export * from './ResourceItem';
export * from './ImageGroup';
export * from './shared-checkout-components';

export default {};
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export {
Tooltip,
type TooltipProps,
View,
type ViewProps,
ToggleButton,
type ToggleButtonProps,
ToggleButtonGroup,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@remote-dom/react/polyfill';
import type {ReactElement, PropsWithChildren} from 'react';
import {Component} from 'react';
import {render as remoteRender} from '@remote-ui/react';
import {extension} from '@shopify/ui-extensions/customer-account';
import type {
ExtensionTargets,
Expand All @@ -10,6 +10,8 @@ import type {

import {ExtensionApiContext} from './context';

import {createRoot} from 'react-dom/client';

/**
* Registers your React-based UI Extension to run for the selected extension target.
* Additionally, this function will automatically provide the extension API as React
Expand All @@ -26,6 +28,7 @@ import {ExtensionApiContext} from './context';
* which allows you to perform initial asynchronous work like fetching data from your
* own backend.
*/

export function reactExtension<Target extends RenderExtensionTarget>(
target: Target,
render: (
Expand All @@ -41,24 +44,12 @@ export function reactExtension<Target extends RenderExtensionTarget>(
async (root, api) => {
const element = await render(api as ApiForRenderExtension<Target>);

await new Promise<void>((resolve, reject) => {
try {
remoteRender(
<ExtensionApiContext.Provider value={api}>
<ErrorBoundary>{element}</ErrorBoundary>
</ExtensionApiContext.Provider>,
root,
() => {
resolve();
},
);
} catch (error) {
// Workaround for https://github.com/Shopify/ui-extensions/issues/325
// eslint-disable-next-line no-console
console.error(error);
reject(error);
}
});
createRoot(root).render(
<ExtensionApiContext.Provider value={api}>
<ErrorBoundary>{element}</ErrorBoundary>
</ExtensionApiContext.Provider>,
);
return;
},
) as any;
}
Expand All @@ -85,6 +76,7 @@ export function render<Target extends RenderExtensionTarget>(
target: Target,
render: (api: ApiForRenderExtension<Target>) => ReactElement<any>,
): ExtensionTargets[Target] {
//@ts-ignore
return reactExtension(target, render);
}

Expand Down
3 changes: 2 additions & 1 deletion packages/ui-extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"sideEffects": false,
"dependencies": {
"@remote-ui/async-subscription": "^2.1.12",
"@remote-ui/core": "^2.2.4"
"@remote-ui/core": "^2.2.4",
"@remote-dom/core": "^1.5.1"
},
"devDependencies": {
"@shopify/generate-docs": "0.16.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {createRemoteComponent} from '@remote-ui/core';
import {createRemoteElement} from '@remote-dom/core/elements';

import type {
Appearance,
Expand Down Expand Up @@ -85,7 +85,11 @@ export interface ButtonProps
onPress?(): void;
}

/**
* Buttons are used for actions, such as “Add”, “Continue”, “Pay now”, or “Save”.
*/
export const Button = createRemoteComponent<'Button', ButtonProps>('Button');
export const Button = createRemoteElement<{}>({
properties: {to: String, foo: String},
events: {press: {bubbles: true}},
slots: ['overlay'],
});

// @ts-ignore
customElements.define('ui-button', Button);
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {createRemoteComponent} from '@remote-ui/core';

import type {
Appearance,
OverlayActivatorProps,
DisclosureActivatorProps,
} from '../shared';
import {createRemoteElement} from '@remote-dom/core/elements';

export interface LinkProps
extends OverlayActivatorProps,
Expand Down Expand Up @@ -48,7 +47,9 @@ export interface LinkProps
onPress?(): void;
}

/**
* Link makes text interactive so customers can perform an action, such as navigating to another location.
*/
export const Link = createRemoteComponent<'Link', LinkProps>('Link');
export const Link = createRemoteElement<{}>({
properties: {to: String},
});

// @ts-ignore
customElements.define('ui-link', Link);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {createRemoteElement} from '@remote-dom/core/elements';
import type {RemoteFragment} from '@remote-ui/core';
import {createRemoteComponent} from '@remote-ui/core';

export interface ModalProps {
/**
Expand Down Expand Up @@ -57,4 +57,11 @@ export interface ModalProps {
*
* The library automatically applies the [WAI-ARIA Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) to both the activator and the modal content.
*/
export const Modal = createRemoteComponent<'Modal', ModalProps>('Modal');
// export const Modal = createRemoteComponent<'Modal', ModalProps>('Modal');

export const Modal = createRemoteElement<{}>({
properties: {id: String},
});

// @ts-ignore
customElements.define('ui-modal', Modal);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {createRemoteComponent} from '@remote-ui/core';
import {createRemoteElement} from '@remote-dom/core/elements';

import type {MaybeResponsiveConditionalStyle} from '../../style/types';
import type {
Expand Down Expand Up @@ -234,4 +234,9 @@ export interface ViewProps
* “natural” size, so this component can be useful in layout components (like `Grid`,
* `BlockStack`, `InlineStack`) that would otherwise stretch their children to fit.
*/
export const View = createRemoteComponent<'View', ViewProps>('View');
export const View = createRemoteElement<{}>({
properties: {padding: String, border: String},
});

// @ts-ignore
customElements.define('ui-view', View);
41 changes: 29 additions & 12 deletions packages/ui-extensions/src/utilities/registration.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import {createRemoteRoot} from '@remote-ui/core';
import '@remote-dom/core/polyfill';

import type {
RenderExtensionConnection,
RenderExtension,
RenderExtensionWithRemoteRoot,
} from '../extension';

import {
// @ts-ignore
BatchingRemoteConnection,
RemoteFragmentElement,
// @ts-ignore
RemoteMutationObserver,
RemoteRootElement,
} from '@remote-dom/core/elements';

console.log('### RemoteRootElement', RemoteRootElement);
// @ts-ignore
customElements.define('remote-root', RemoteRootElement);
// @ts-ignore
customElements.define('remote-fragment', RemoteFragmentElement);

export interface ExtensionRegistrationFunction<ExtensionTargets> {
<Target extends keyof ExtensionTargets>(
target: Target,
Expand Down Expand Up @@ -46,35 +61,37 @@ export function createExtensionRegistrationFunction<
return (implementation as any)(...args);
}

const [{channel, components}, api] = args as [
RenderExtensionConnection,
any,
];
const [{channel}, api] = args as [RenderExtensionConnection, any];

// @ts-ignore
const root = document.createElement('remote-root');
root.connect(channel);

const root = createRemoteRoot(channel, {
components,
strict: true,
});
// try {
// const observer = new RemoteMutationObserver(channel);
// observer.observe(root);
// } catch {
// }

let renderResult = (implementation as any)(root, api);

console.log('### renderResult test', renderResult);

if (
typeof renderResult === 'object' &&
renderResult != null &&
'then' in renderResult
) {
renderResult = await renderResult;
console.log('### renderResult promise', renderResult);
}

root.mount();

return renderResult;
}

(globalThis as any).shopify?.extend(target, extension);

return extension as any;
};

return extensionWrapper;
}
Loading

0 comments on commit fe20446

Please sign in to comment.