diff --git a/.changeset/early-eggs-slide.md b/.changeset/early-eggs-slide.md new file mode 100644 index 00000000..47085bc0 --- /dev/null +++ b/.changeset/early-eggs-slide.md @@ -0,0 +1,5 @@ +--- +"with-vite-bundled": minor +--- + +feat: add new example with vanilla js + bundled widget diff --git a/README.md b/README.md index 5b628c7f..aae46c6d 100644 --- a/README.md +++ b/README.md @@ -20,28 +20,6 @@ yarn add @stakekit/widget pnpm add @stakekit/widget ``` -If you are going to use StakeKit Widget as a React component, you'll need to install some additional peer dependencies: - -```bash -npm install wagmi@2 viem@2 - -yarn add wagmi@2 viem@2 - -pnpm add wagmi@2 viem@2 -``` - -If you're using Next.js, add this to your webpack configuration in `next.config.js`: - -```js -const nextConfig = { - webpack: (config) => { - config.externals.push("pino-pretty", "lokijs", "encoding"); - - return config; - }, -}; -``` - ## Usage To use StakeKit Widget, first you'll need API key from StakeKit. @@ -163,66 +141,85 @@ const App = () => { ```ts { - color: { - white: string; - black: string; - transparent: string; - primary: string; - accent: string; - disabled: string; - text: string; - textMuted: string; - textDanger: string; - background: string; - backgroundMuted: string; - tokenSelectBackground: string; - tokenSelectHoverBackground: string; - tokenSelect: string; - skeletonLoaderBase: string; - skeletonLoaderHighlight: string; - tabBorder: string; - stakeSectionBackground: string; - dropdownBackground: string; - selectValidatorMultiSelectedBackground: string; - selectValidatorMultiDefaultBackground: string; - warningBoxBackground: string; - positionsSectionBackgroundColor: string; - positionsSectionBorderColor: string; - positionsSectionDividerColor: string; - positionsClaimRewardsBackground: string; - positionsActionRequiredBackground: string; - modalOverlayBackground: string; - modalBodyBackground: string; - tooltipBackground: string; - primaryButtonColor: string; - primaryButtonBackground: string; - primaryButtonOutline: string; - primaryButtonHoverColor: string; - primaryButtonHoverBackground: string; - primaryButtonHoverOutline: string; - primaryButtonActiveColor: string; - primaryButtonActiveBackground: string; - primaryButtonActiveOutline: string; - secondaryButtonColor: string; - secondaryButtonBackground: string; - secondaryButtonOutline: string; - secondaryButtonHoverColor: string; - secondaryButtonHoverBackground: string; - secondaryButtonHoverOutline: string; - secondaryButtonActiveColor: string; - secondaryButtonActiveBackground: string; - secondaryButtonActiveOutline: string; - disabledButtonColor: string; - disabledButtonBackground: string; - disabledButtonOutline: string; - disabledButtonHoverColor: string; - disabledButtonHoverBackground: string; - disabledButtonHoverOutline: string; - disabledButtonActiveColor: string; - disabledButtonActiveBackground: string; - disabledButtonActiveOutline: string; - } & { - connectKit: { + color: { + white: string; + black: string; + transparent: string; + primary: string; + accent: string; + disabled: string; + text: string; + textMuted: string; + textDanger: string; + background: string; + backgroundMuted: string; + tokenSelectBackground: string; + tokenSelectHoverBackground: string; + tokenSelect: string; + skeletonLoaderBase: string; + skeletonLoaderHighlight: string; + tabBorder: string; + stakeSectionBackground: string; + dropdownBackground: string; + selectValidatorMultiSelectedBackground: string; + selectValidatorMultiDefaultBackground: string; + warningBoxBackground: string; + positionsSectionBackgroundColor: string; + positionsSectionBorderColor: string; + positionsSectionDividerColor: string; + positionsClaimRewardsBackground: string; + positionsActionRequiredBackground: string; + positionsPendingBackground: string; + modalOverlayBackground: string; + modalBodyBackground: string; + tooltipBackground: string; + primaryButtonColor: string; + primaryButtonBackground: string; + primaryButtonOutline: string; + primaryButtonHoverColor: string; + primaryButtonHoverBackground: string; + primaryButtonHoverOutline: string; + primaryButtonActiveColor: string; + primaryButtonActiveBackground: string; + primaryButtonActiveOutline: string; + secondaryButtonColor: string; + secondaryButtonBackground: string; + secondaryButtonOutline: string; + secondaryButtonHoverColor: string; + secondaryButtonHoverBackground: string; + secondaryButtonHoverOutline: string; + secondaryButtonActiveColor: string; + secondaryButtonActiveBackground: string; + secondaryButtonActiveOutline: string; + smallButtonColor: string; + smallButtonBackground: string; + smallButtonOutline: string; + smallButtonHoverColor: string; + smallButtonHoverBackground: string; + smallButtonHoverOutline: string; + smallButtonActiveColor: string; + smallButtonActiveBackground: string; + smallButtonActiveOutline: string; + smallLightButtonColor: string; + smallLightButtonBackground: string; + smallLightButtonOutline: string; + smallLightButtonHoverColor: string; + smallLightButtonHoverBackground: string; + smallLightButtonHoverOutline: string; + smallLightButtonActiveColor: string; + smallLightButtonActiveBackground: string; + smallLightButtonActiveOutline: string; + disabledButtonColor: string; + disabledButtonBackground: string; + disabledButtonOutline: string; + disabledButtonHoverColor: string; + disabledButtonHoverBackground: string; + disabledButtonHoverOutline: string; + disabledButtonActiveColor: string; + disabledButtonActiveBackground: string; + disabledButtonActiveOutline: string; + } & { + connectKit: { accentColor: string; accentColorForeground: string; actionButtonBorder: string; @@ -254,188 +251,236 @@ const App = () => { selectedOptionBorder: string; standby: string; }; - }; - fontSize: { - xs: string; - sm: string; - md: string; - lg: string; - lgx: string; - xl: string; - "2xl": string; - "3xl": string; - "4xl": string; - "5xl": string; - "6xl": string; - }; - letterSpacing: { - tighter: string; - tight: string; - normal: string; - wide: string; - wider: string; - widest: string; - }; - lineHeight: { - none: string; - shorter: string; - short: string; - base: string; - tall: string; - taller: string; - xs: string; - sm: string; - md: string; - lg: string; - xl: string; - "2xl": string; - "3xl": string; - "4xl": string; - "5xl": string; - "6xl": string; - }; - fontWeight: { - normal: string; - medium: string; - semibold: string; - bold: string; - extrabold: string; - modalHeading: string; - tokenSelect: string; - primaryButton: string; - secondaryButton: string; - }; - borderRadius: { - baseContract: { - none: string; - sm: string; - base: string; - md: string; - lg: string; - xl: string; - "2xl": string; - "3xl": string; - full: string; - half: string; - widgetBorderRadius: string; - primaryButton: string; - secondaryButton: string; - }; - connectKit: { + }; + fontSize: { + xs: string; + sm: string; + md: string; + lg: string; + lgx: string; + xl: string; + "2xl": string; + "3xl": string; + "4xl": string; + "5xl": string; + "6xl": string; + }; + letterSpacing: { + tighter: string; + tight: string; + normal: string; + wide: string; + wider: string; + widest: string; + }; + lineHeight: { + none: string; + shorter: string; + short: string; + base: string; + tall: string; + taller: string; + xs: string; + sm: string; + md: string; + lg: string; + xl: string; + "2xl": string; + "3xl": string; + "4xl": string; + "5xl": string; + "6xl": string; + }; + fontWeight: { + normal: string; + medium: string; + semibold: string; + bold: string; + extrabold: string; + modalHeading: string; + tokenSelect: string; + primaryButton: string; + secondaryButton: string; + }; + borderRadius: { + baseContract: { + none: string; + sm: string; + base: string; + md: string; + lg: string; + xl: string; + "2xl": string; + "3xl": string; + full: string; + half: string; + widgetBorderRadius: string; + primaryButton: string; + secondaryButton: string; + smallButton: string; + }; + connectKit: { actionButton: string; connectButton: string; menuButton: string; modal: string; modalMobile: string; }; - }; - space: { - full: string; - unset: string; - auto: string; - "0": string; - "1": string; - "2": string; - "3": string; - "4": string; - "5": string; - "6": string; - "7": string; - "8": string; - "9": string; - "10": string; - "12": string; - "14": string; - "16": string; - "20": string; - "24": string; - "28": string; - "32": string; - "36": string; - "40": string; - "44": string; - "48": string; - px: string; - buttonMinHeight: string; - }; - heading: { - h1: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - h2: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - h3: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - h4: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - }; - text: { - large: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - medium: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - small: { - mobile: { - fontSize: string; - }; - tablet: { - fontSize: string; - }; - }; - }; - zIndices: { - hide: string; - auto: string; - base: string; - docked: string; - dropdown: string; - sticky: string; - banner: string; - overlay: string; - modal: string; - skipLink: string; - }; - font: { - body: string; - }; + }; + space: { + full: string; + unset: string; + auto: string; + "0": string; + "1": string; + "2": string; + "3": string; + "4": string; + "5": string; + "6": string; + "7": string; + "8": string; + "9": string; + "10": string; + "12": string; + "14": string; + "16": string; + "20": string; + "24": string; + "28": string; + "32": string; + "36": string; + "40": string; + "44": string; + "48": string; + px: string; + buttonMinHeight: string; + }; + heading: { + h1: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + h2: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + h3: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + h4: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + }; + text: { + small: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + large: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + medium: { + mobile: { + fontSize: string; + }; + tablet: { + fontSize: string; + }; + }; + }; + zIndices: { + hide: string; + auto: string; + simple: string; + base: string; + docked: string; + dropdown: string; + sticky: string; + banner: string; + overlay: string; + modal: string; + skipLink: string; + }; + font: { + body: string; + }; } ``` +### Custom provider + +Optionally, you can pass externalProviders property to the widget which will be used to connect to the wallet. + +```ts +type SKExternalProviders = { + currentChain?: number; + currentAddress: string; + initToken?: `${TokenDto["network"]}-${TokenDto["address"]}`; + supportedChainIds?: number[]; + type: "generic"; + provider: EVMWallet; +}; + +type EVMWallet = { + signMessage: (message: string) => Promise; + switchChain: (chainId: string) => Promise; + getTransactionReceipt?(txHash: string): Promise<{ + transactionHash?: string; + }>; + sendTransaction(tx: EVMTx): Promise; +}; + +export declare enum TxType { + Legacy = "0x1", + EIP1559 = "0x2" +} + +export type EVMTx = { + data: Hex; + from: Hex; + to: Hex; + value: Hex | undefined; + nonce: Hex; + gas: Hex; + chainId: Hex; + type: Hex; +} & ({ + type: TxType.EIP1559; + maxFeePerGas: Hex | undefined; + maxPriorityFeePerGas: Hex | undefined; +} | { + type: TxType.Legacy; +}); +``` + ### Tracking StakeKit component provides `tracking` prop for analytics to track user actions and page views diff --git a/package.json b/package.json index a261025b..27afe739 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "knip": "^5.46.2", "turbo": "^2.4.4" }, - "packageManager": "pnpm@10.7.0", + "packageManager": "pnpm@10.7.1", "pnpm": { "overrides": { "@types/react": "19.0.10", diff --git a/packages/examples/with-vite-bundled/.env.example b/packages/examples/with-vite-bundled/.env.example new file mode 100644 index 00000000..c340407d --- /dev/null +++ b/packages/examples/with-vite-bundled/.env.example @@ -0,0 +1 @@ +VITE_API_KEY= \ No newline at end of file diff --git a/packages/examples/with-vite-bundled/.gitignore b/packages/examples/with-vite-bundled/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/examples/with-vite-bundled/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/examples/with-vite-bundled/index.html b/packages/examples/with-vite-bundled/index.html new file mode 100644 index 00000000..44a93350 --- /dev/null +++ b/packages/examples/with-vite-bundled/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + TS + + +
+ + + diff --git a/packages/examples/with-vite-bundled/package.json b/packages/examples/with-vite-bundled/package.json new file mode 100644 index 00000000..d8948ef2 --- /dev/null +++ b/packages/examples/with-vite-bundled/package.json @@ -0,0 +1,20 @@ +{ + "name": "with-vite-bundled", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "tsc && biome check .", + "format": "biome check --write ." + }, + "dependencies": { + "@stakekit/widget": "workspace:*" + }, + "devDependencies": { + "typescript": "~5.7.2", + "vite": "^6.2.0" + } +} diff --git a/packages/examples/with-vite-bundled/public/vite.svg b/packages/examples/with-vite-bundled/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/packages/examples/with-vite-bundled/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/examples/with-vite-bundled/src/main.ts b/packages/examples/with-vite-bundled/src/main.ts new file mode 100644 index 00000000..9d5d5c3f --- /dev/null +++ b/packages/examples/with-vite-bundled/src/main.ts @@ -0,0 +1,9 @@ +import "./style.css"; +import "@stakekit/widget/style.css"; +import { darkTheme, renderSKWidget } from "@stakekit/widget/bundle"; + +renderSKWidget({ + container: document.querySelector("#app")!, + apiKey: import.meta.env.VITE_API_KEY, + theme: darkTheme, +}); diff --git a/packages/examples/with-vite-bundled/src/style.css b/packages/examples/with-vite-bundled/src/style.css new file mode 100644 index 00000000..344949e5 --- /dev/null +++ b/packages/examples/with-vite-bundled/src/style.css @@ -0,0 +1,3 @@ +body { + background-color: #000; +} diff --git a/packages/examples/with-vite-bundled/src/typescript.svg b/packages/examples/with-vite-bundled/src/typescript.svg new file mode 100644 index 00000000..d91c910c --- /dev/null +++ b/packages/examples/with-vite-bundled/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/examples/with-vite-bundled/src/vite-env.d.ts b/packages/examples/with-vite-bundled/src/vite-env.d.ts new file mode 100644 index 00000000..03e82b4b --- /dev/null +++ b/packages/examples/with-vite-bundled/src/vite-env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_KEY: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/packages/examples/with-vite-bundled/tsconfig.json b/packages/examples/with-vite-bundled/tsconfig.json new file mode 100644 index 00000000..a4883f28 --- /dev/null +++ b/packages/examples/with-vite-bundled/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/packages/widget/src/providers/safe/safe-connector.ts b/packages/widget/src/providers/safe/safe-connector.ts index bbddd49f..256e3960 100644 --- a/packages/widget/src/providers/safe/safe-connector.ts +++ b/packages/widget/src/providers/safe/safe-connector.ts @@ -137,7 +137,7 @@ function safe( } export const safeConnector = (): WalletList[number] => ({ - groupName: "Ledger Live", + groupName: "Safe Wallet", wallets: [ () => ({ id: configMeta.id, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2abb7a8d..8be32905 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,19 @@ importers: specifier: ^6.2.3 version: 6.2.3(@types/node@22.13.13)(jiti@2.4.2) + packages/examples/with-vite-bundled: + dependencies: + '@stakekit/widget': + specifier: workspace:* + version: link:../../widget + devDependencies: + typescript: + specifier: ~5.7.2 + version: 5.7.3 + vite: + specifier: ^6.2.0 + version: 6.2.3(@types/node@22.13.13)(jiti@2.4.2) + packages/widget: dependencies: react-compiler-runtime: @@ -5528,6 +5541,11 @@ packages: typeforce@1.18.0: resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==} + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + typescript@5.8.2: resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} @@ -12889,6 +12907,8 @@ snapshots: typeforce@1.18.0: {} + typescript@5.7.3: {} + typescript@5.8.2: {} ua-parser-js@1.0.40: {}