+ {showExtensionFirst ? (
+ // Extension first, then mobile
+
+ {/* Extension Section */}
+
+
{t('USE_EXTENSION')}
+
{t('ONE_CLICK_CONNECT')}
+
+
+
+
+
+
+ {/* Mobile Section */}
+
+
{t('USE_MOBILE')}
+
{t('SCAN_TO_CONNECT')}
+
+
+
{ if (el) this.qrCodeContainer = el; }} />
+
+
+
+ ) : (
+ // Mobile first, then extension
+
+ {/* Mobile Section */}
+
+
{t('USE_MOBILE')}
+
{t('SCAN_TO_CONNECT')}
+
+
+
{ if (el) this.qrCodeContainer = el; }} />
+
+
+
+
+
+ {/* Extension Section */}
+
+
{t('USE_EXTENSION')}
+
{t('INSTALL_MODAL.INSTALL_META_MASK_EXTENSION_TEXT')}
+
+
+
+
+ )}
+
+
+
+
+
+ )
+ }
+}
+
diff --git a/packages/sdk-multichain-ui/src/components/style.css b/packages/sdk-multichain-ui/src/components/style.css
new file mode 100644
index 000000000..8e740ea7f
--- /dev/null
+++ b/packages/sdk-multichain-ui/src/components/style.css
@@ -0,0 +1,191 @@
+/* Euclid Circular B Font Faces */
+@font-face {
+ font-family: 'Euclid Circular B';
+ src: url('../assets/fonts/Euclid Circular B Regular.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+.flexContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: row;
+}
+
+.flexItem11 {
+ flex: 11;
+ justify-content: center;
+ align-items: center;
+}
+
+.flexItem1 {
+ flex: 1;
+ justify-content: center;
+ align-items: center;
+}
+
+.button {
+ margin-top: 41.5px;
+ margin-bottom: 20px;
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ padding: 12px 20px;
+ background:#0376C9;
+ border-radius: 32px;
+ color: white;
+ border: 0;
+ font-size: 14px;
+ cursor: pointer;
+}
+
+.backdrop {
+ visibility: visible;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ width: 100%;
+ z-index: 99998;
+ background: rgba(0, 0, 0, 0.87);
+ opacity: 0.3;
+}
+
+.modal {
+ visibility: visible;
+ position: fixed;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 99999;
+ background: white;
+ padding: 20px;
+ border-radius: 8px;
+ top: 50%;
+ max-width: 360px;
+ width: 460px;
+ min-width: 300px;
+ box-shadow: rgba(0, 0, 0, 0.2) 0px 11px 15px -7px, rgba(0, 0, 0, 0.14) 0px 24px 38px 3px, rgba(0, 0, 0, 0.12) 0px 9px 46px 8px;
+ -webkit-font-smoothing: antialiased;
+}
+
+.sectionDivider {
+ height:1px;
+ background-color:#B7BBC866;
+ margin-top:17px;
+ margin-bottom:10px;
+}
+
+.closeButtonContainer {
+ position: absolute;
+ right: 15px;
+ top: 15px;
+ padding: 10px;
+ user-select: none;
+}
+
+.buttonText {
+ margin-left:10px;
+}
+
+.closeButton {
+ color: #BBC0C5;
+ cursor: pointer;
+ user-select: none;
+}
+
+
+
+.right {
+ display: flex;
+ align-items: center;
+ justify-content: right;
+}
+
+#sdk-mm-qrcode {
+ margin-top:10px;
+ margin-bottom:10px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border: none !important;
+ outline: none !important;
+ box-shadow: none !important;
+}
+
+#sdk-mm-qrcode svg {
+ width: 100% !important;
+ height: auto !important;
+ border: none !important;
+ outline: none !important;
+ box-shadow: none !important;
+ stroke: none !important;
+ stroke-width: 0 !important;
+ background: transparent !important;
+}
+
+
+* {
+ font-family: 'Euclid Circular B', sans-serif;
+}
+
+.modalTitle {
+ font-size: 16px;
+ font-weight: 700;
+ letter-spacing: 0px;
+ line-height: 24px;
+ color: #141618;
+ margin-top: 4px;
+ text-align: center;
+ user-select: none;
+}
+
+.sectionTitle {
+ text-align: center;
+ font-size: 14px;
+ font-weight: 500;
+ margin-bottom:0px;
+ margin-top: 20px;
+ font-weight: bold;
+}
+
+.sectionDescription {
+ text-align: center;
+ font-size: 14px;
+ font-weight: 400;
+ margin-top: 5px;
+ color:#6A737D;
+}
+
+.extensionButton {
+ padding:15px 20px;
+ margin-top:15px;
+ margin-bottom:0px;
+}
+
+.qrContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+}
+
+.qrCode {
+ margin: 0 auto;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.version-title {
+
+ text-align: center;
+ font-size: 10px;
+ font-weight: 400;
+ margin-top: 5px;
+ color:#6A737D;
+}
diff --git a/packages/sdk-multichain-ui/src/components/widget-wrapper/resetStyles.css b/packages/sdk-multichain-ui/src/components/widget-wrapper/resetStyles.css
new file mode 100644
index 000000000..d6b304293
--- /dev/null
+++ b/packages/sdk-multichain-ui/src/components/widget-wrapper/resetStyles.css
@@ -0,0 +1,125 @@
+/* globalStyles.css */
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+ display: block;
+}
+
+body {
+ line-height: 1;
+}
+
+ol,
+ul {
+ list-style: none;
+}
+
+blockquote,
+q {
+ quotes: none;
+}
+
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
diff --git a/packages/sdk-multichain-ui/src/components/widget-wrapper/widget-wrapper.tsx b/packages/sdk-multichain-ui/src/components/widget-wrapper/widget-wrapper.tsx
new file mode 100644
index 000000000..53c1802c4
--- /dev/null
+++ b/packages/sdk-multichain-ui/src/components/widget-wrapper/widget-wrapper.tsx
@@ -0,0 +1,18 @@
+import { h, ChildNode } from '@stencil/core';
+import './resetStyles.css';
+
+const widgetWrapperStyle = {
+ fontFamily: '"Euclid Circular B", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
+};
+
+export const WidgetWrapper = ({
+ className,
+}: {
+ className: string;
+}, children: ChildNode) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/sdk-multichain-ui/src/index.html b/packages/sdk-multichain-ui/src/index.html
new file mode 100644
index 000000000..50f63614f
--- /dev/null
+++ b/packages/sdk-multichain-ui/src/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
SDK Install Modal Web
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/sdk-multichain-ui/src/index.ts b/packages/sdk-multichain-ui/src/index.ts
new file mode 100644
index 000000000..fbae333af
--- /dev/null
+++ b/packages/sdk-multichain-ui/src/index.ts
@@ -0,0 +1,12 @@
+/**
+ * @fileoverview entry point for your component library
+ *
+ * This is the entry point for your component library. Use this file to export utilities,
+ * constants or data structure that accompany your components.
+ *
+ * DO NOT use this file to export your components. Instead, use the recommended approaches
+ * to consume components of this package as outlined in the `README.md`.
+ */
+
+export type { Components, MmInstallModalCustomEvent, JSX } from './components'
+
diff --git a/packages/sdk-multichain-ui/stencil.config.ts b/packages/sdk-multichain-ui/stencil.config.ts
new file mode 100644
index 000000000..94344913f
--- /dev/null
+++ b/packages/sdk-multichain-ui/stencil.config.ts
@@ -0,0 +1,51 @@
+import { Config } from '@stencil/core';
+import { visualizer } from 'rollup-plugin-visualizer';
+
+export const config: Config = {
+ namespace: 'sdk-install-modal-web',
+ validatePrimaryPackageOutputTarget: true,
+ outputTargets: [
+ {
+ type: 'dist',
+ isPrimaryPackageOutputTarget: true,
+ copy: [
+ {
+ src: 'assets',
+ dest: 'assets'
+ }
+ ]
+ },
+ {
+ type: 'www',
+ serviceWorker: null,
+ baseUrl: 'http://localhost:4444/',
+ copy: [
+ {
+ src: 'assets',
+ dest: 'assets'
+ }
+ ]
+ }
+ ],
+ enableCache: true,
+ buildEs5: false,
+ // Add hash for file names for better caching
+ hashFileNames: true,
+ excludeUnusedDependencies: true,
+ testing: {
+ browserHeadless: "new",
+ },
+ rollupPlugins: {
+ after: [
+ process.env.NODE_ENV === 'development' ? visualizer() : null
+ ].filter(Boolean),
+ },
+ // Add treeshaking for better optimization
+ extras: {
+ enableImportInjection: true,
+ scriptDataOpts: false,
+ appendChildSlotFix: false,
+ cloneNodeFix: false,
+ slotChildNodesFix: false,
+ }
+};
diff --git a/packages/sdk-multichain-ui/tsconfig.json b/packages/sdk-multichain-ui/tsconfig.json
new file mode 100644
index 000000000..c450a3960
--- /dev/null
+++ b/packages/sdk-multichain-ui/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ // "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "baseUrl": "./",
+ "strict": true,
+ "strictPropertyInitialization": false,
+ "target": "es2017",
+ "lib": ["es6", "dom", "es2016", "es2017"],
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "experimentalDecorators": true,
+ "forceConsistentCasingInFileNames": true,
+ "moduleResolution": "Node",
+ "jsx": "react",
+ "composite": true,
+ "skipLibCheck": true,
+ "jsxFactory": "h",
+ "module": "esnext",
+ "noUnusedLocals": true,
+ "noUnusedParameters": true
+ },
+ "include": ["./src"],
+ "exclude": ["node_modules", "dist", "loader"]
+}
diff --git a/yarn.lock b/yarn.lock
index 9ff0635fa..dcbb43939 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11579,6 +11579,40 @@ __metadata:
languageName: unknown
linkType: soft
+"@metamask/sdk-multichain-ui@workspace:packages/sdk-multichain-ui":
+ version: 0.0.0-use.local
+ resolution: "@metamask/sdk-multichain-ui@workspace:packages/sdk-multichain-ui"
+ dependencies:
+ "@lavamoat/allow-scripts": ^2.3.1
+ "@metamask/auto-changelog": 3.1.0
+ "@paulmillr/qr": ^0.2.1
+ "@size-limit/preset-big-lib": ^11.0.2
+ "@stencil/core": ^4.22.2
+ "@types/i18n": ^0.13.12
+ "@types/jest": ^29.5.14
+ "@types/node": ^22.9.0
+ "@types/prettier": ^2
+ "@typescript-eslint/eslint-plugin": ^5.56.0
+ "@typescript-eslint/parser": ^5.56.0
+ eslint: ^8.36.0
+ eslint-config-prettier: ^8.3.0
+ eslint-plugin-import: ^2.23.4
+ eslint-plugin-jest: ^24.4.0
+ eslint-plugin-jsdoc: ^44.2.4
+ eslint-plugin-node: ^11.1.0
+ eslint-plugin-prettier: ^3.4.0
+ eslint-plugin-react: ^7.32.2
+ jest: ^29.6.4
+ prettier: ^2.8.8
+ puppeteer: ^23.8.0
+ qr-code-styling: ^1.9.2
+ rimraf: ^5.0.0
+ rollup-plugin-visualizer: ^5.12.0
+ size-limit: ^11.1.6
+ typescript: ^5.6.3
+ languageName: unknown
+ linkType: soft
+
"@metamask/sdk-react-native@workspace:packages/sdk-react-native":
version: 0.0.0-use.local
resolution: "@metamask/sdk-react-native@workspace:packages/sdk-react-native"
@@ -45299,6 +45333,15 @@ __metadata:
languageName: node
linkType: hard
+"qr-code-styling@npm:^1.9.2":
+ version: 1.9.2
+ resolution: "qr-code-styling@npm:1.9.2"
+ dependencies:
+ qrcode-generator: ^1.4.4
+ checksum: bc8fa04821efd485e12c3c32485964abfe4ba3173e397f96a870c69626b7b377d660cfbef33ea9e5fd23867eae3073dc2ea88ba2476df6206346481f69052acc
+ languageName: node
+ linkType: hard
+
"qrcode-generator@npm:^1.4.3":
version: 1.4.4
resolution: "qrcode-generator@npm:1.4.4"
@@ -45306,6 +45349,13 @@ __metadata:
languageName: node
linkType: hard
+"qrcode-generator@npm:^1.4.4":
+ version: 1.5.2
+ resolution: "qrcode-generator@npm:1.5.2"
+ checksum: aec3891afddf88054ebdeb3698f24ca30e60a5f3816e3a0812adb50d1efcf571a31909cafdc2c1275f404a0484b1109be917d458ad7f0da058dcdf6f92b95cce
+ languageName: node
+ linkType: hard
+
"qrcode-terminal-nooctal@npm:^0.12.1":
version: 0.12.1
resolution: "qrcode-terminal-nooctal@npm:0.12.1"