@cartridge/controller 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$deps.log +18 -18
- package/.turbo/turbo-build.log +16 -16
- package/dist/iframe/base.d.ts +0 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1854 -811
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/{provider-s-80NdXp.js → provider-DCZ6z1Gs.js} +38 -24
- package/dist/provider-DCZ6z1Gs.js.map +1 -0
- package/dist/session.js +2 -2
- package/dist/stats.html +1 -1
- package/dist/toast/components/close-button.d.ts +1 -0
- package/dist/toast/components/progress-bar.d.ts +6 -0
- package/dist/toast/index.d.ts +57 -0
- package/dist/toast/styles.d.ts +1 -0
- package/dist/toast/types.d.ts +39 -0
- package/dist/toast/utils/progress-bar.d.ts +9 -0
- package/dist/toast/utils.d.ts +8 -0
- package/dist/toast/variants/achievement.d.ts +3 -0
- package/dist/toast/variants/error.d.ts +3 -0
- package/dist/toast/variants/index.d.ts +6 -0
- package/dist/toast/variants/marketplace.d.ts +3 -0
- package/dist/toast/variants/network-switch.d.ts +3 -0
- package/dist/toast/variants/quest.d.ts +3 -0
- package/dist/toast/variants/transaction.d.ts +3 -0
- package/dist/types.d.ts +3 -3
- package/dist/utils.d.ts +1 -0
- package/dist/wallets/index.d.ts +1 -0
- package/dist/wallets/phantom-evm/index.d.ts +7 -0
- package/dist/wallets/types.d.ts +2 -2
- package/package.json +2 -3
- package/src/iframe/base.ts +2 -20
- package/src/index.ts +1 -0
- package/src/toast/components/close-button.ts +82 -0
- package/src/toast/components/progress-bar.ts +60 -0
- package/src/toast/index.ts +263 -0
- package/src/toast/styles.ts +142 -0
- package/src/toast/types.ts +67 -0
- package/src/toast/utils/progress-bar.ts +23 -0
- package/src/toast/utils.ts +65 -0
- package/src/toast/variants/achievement.ts +244 -0
- package/src/toast/variants/error.ts +107 -0
- package/src/toast/variants/index.ts +6 -0
- package/src/toast/variants/marketplace.ts +145 -0
- package/src/toast/variants/network-switch.ts +72 -0
- package/src/toast/variants/quest.ts +164 -0
- package/src/toast/variants/transaction.ts +256 -0
- package/src/types.ts +1 -0
- package/src/utils.ts +15 -0
- package/src/wallets/bridge.ts +4 -0
- package/src/wallets/index.ts +1 -0
- package/src/wallets/phantom-evm/index.ts +8 -0
- package/src/wallets/types.ts +5 -1
- package/dist/provider-s-80NdXp.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CloseButton: (translucent?: boolean) => HTMLDivElement;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ToastOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Show a toast notification
|
|
4
|
+
*
|
|
5
|
+
* The toast will always appear on the parent page, even if called from within an iframe.
|
|
6
|
+
* This ensures toasts are visible above all content, including the keychain iframe.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Toast options with variant-specific properties
|
|
9
|
+
* @returns A function to manually dismiss the toast
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { toast } from "@cartridge/controller";
|
|
14
|
+
*
|
|
15
|
+
* // Error toast
|
|
16
|
+
* toast({
|
|
17
|
+
* variant: "error",
|
|
18
|
+
* message: "Transaction failed",
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Transaction toast
|
|
22
|
+
* toast({
|
|
23
|
+
* variant: "transaction",
|
|
24
|
+
* hash: "0x1234...",
|
|
25
|
+
* status: "success",
|
|
26
|
+
* amount: "100",
|
|
27
|
+
* token: "ETH"
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Network switch toast
|
|
31
|
+
* toast({
|
|
32
|
+
* variant: "network-switch",
|
|
33
|
+
* networkName: "Mainnet",
|
|
34
|
+
* networkIcon: <url to icon image>
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* // Achievement toast
|
|
38
|
+
* toast({
|
|
39
|
+
* variant: "achievement",
|
|
40
|
+
* itemName: "First Achievement",
|
|
41
|
+
* itemImage: "https://example.com/trophy.png"
|
|
42
|
+
* action: "purchased" | "sold",
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Marketplace toast
|
|
46
|
+
* toast({
|
|
47
|
+
* variant: "marketplace",
|
|
48
|
+
* itemName: "Cool NFT #123",
|
|
49
|
+
* action: "purchased",
|
|
50
|
+
* price: "0.5",
|
|
51
|
+
* currency: "ETH",
|
|
52
|
+
* image: "https://example.com/nft.png"
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function toast(options: ToastOptions): () => void;
|
|
57
|
+
export * from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function injectStyles(targetDoc: Document): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ToastPosition = "top-left" | "top-right" | "top-center" | "bottom-left" | "bottom-right" | "bottom-center";
|
|
2
|
+
export interface BaseToastOptions {
|
|
3
|
+
duration?: number;
|
|
4
|
+
position?: ToastPosition;
|
|
5
|
+
}
|
|
6
|
+
export interface ErrorToastOptions extends BaseToastOptions {
|
|
7
|
+
variant: "error";
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TransactionToastOptions extends BaseToastOptions {
|
|
11
|
+
variant: "transaction";
|
|
12
|
+
status: "confirming" | "confirmed";
|
|
13
|
+
isExpanded?: boolean;
|
|
14
|
+
label?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface NetworkSwitchToastOptions extends BaseToastOptions {
|
|
17
|
+
variant: "network-switch";
|
|
18
|
+
networkName: string;
|
|
19
|
+
networkIcon?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AchievementToastOptions extends BaseToastOptions {
|
|
22
|
+
variant: "achievement";
|
|
23
|
+
title: string;
|
|
24
|
+
subtitle?: string;
|
|
25
|
+
xpAmount: number;
|
|
26
|
+
isDraft?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface QuestToastOptions extends BaseToastOptions {
|
|
29
|
+
variant: "quest";
|
|
30
|
+
title: string;
|
|
31
|
+
subtitle: string;
|
|
32
|
+
}
|
|
33
|
+
export interface MarketplaceToastOptions extends BaseToastOptions {
|
|
34
|
+
variant: "marketplace";
|
|
35
|
+
itemName: string;
|
|
36
|
+
itemImage: string;
|
|
37
|
+
action: "purchased" | "sold";
|
|
38
|
+
}
|
|
39
|
+
export type ToastOptions = ErrorToastOptions | TransactionToastOptions | NetworkSwitchToastOptions | AchievementToastOptions | QuestToastOptions | MarketplaceToastOptions;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add a progress bar to a toast element
|
|
3
|
+
*
|
|
4
|
+
* @param toast - The toast element to add the progress bar to
|
|
5
|
+
* @param duration - Duration in milliseconds
|
|
6
|
+
* @param onComplete - Callback when progress completes
|
|
7
|
+
* @param borderRadius - Optional border radius in pixels (default: 8px)
|
|
8
|
+
*/
|
|
9
|
+
export declare function addProgressBarToToast(toast: HTMLElement, duration: number, onComplete: () => void, borderRadius?: number): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const TOAST_CONTAINER_ID = "cartridge-toast-container";
|
|
2
|
+
export declare const DEFAULT_DURATION = 3000;
|
|
3
|
+
export declare const DEFAULT_POSITION = "bottom-right";
|
|
4
|
+
export declare const TOAST_MESSAGE_TYPE = "cartridge-toast-show";
|
|
5
|
+
export declare function isInIframe(): boolean;
|
|
6
|
+
export declare function getTargetDocument(): Document | null;
|
|
7
|
+
export declare function getToastContainer(targetDoc: Document, position: string): HTMLElement;
|
|
8
|
+
export declare function removeToast(toast: HTMLElement): void;
|
package/dist/types.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export type KeychainSession = {
|
|
|
15
15
|
};
|
|
16
16
|
export declare const EMBEDDED_WALLETS: readonly ["google", "webauthn", "discord", "walletconnect", "password"];
|
|
17
17
|
export type EmbeddedWallet = (typeof EMBEDDED_WALLETS)[number];
|
|
18
|
-
export declare const ALL_AUTH_OPTIONS: readonly ["google", "webauthn", "discord", "walletconnect", "password", "metamask", "rabby", "argent", "braavos", "phantom", "base"];
|
|
18
|
+
export declare const ALL_AUTH_OPTIONS: readonly ["google", "webauthn", "discord", "walletconnect", "password", "metamask", "rabby", "phantom-evm", "argent", "braavos", "phantom", "base"];
|
|
19
19
|
export type AuthOption = (typeof ALL_AUTH_OPTIONS)[number];
|
|
20
|
-
export declare const IMPLEMENTED_AUTH_OPTIONS: ("metamask" | "rabby" | "google" | "webauthn" | "discord" | "walletconnect" | "password")[];
|
|
20
|
+
export declare const IMPLEMENTED_AUTH_OPTIONS: ("metamask" | "rabby" | "phantom-evm" | "google" | "webauthn" | "discord" | "walletconnect" | "password")[];
|
|
21
21
|
export type AuthOptions = (typeof IMPLEMENTED_AUTH_OPTIONS)[number][];
|
|
22
22
|
export declare enum ResponseCodes {
|
|
23
23
|
SUCCESS = "SUCCESS",
|
|
@@ -155,7 +155,7 @@ export type KeychainOptions = IFrameOptions & {
|
|
|
155
155
|
/** When true, defer iframe mounting until connect() is called. Reduces initial load and resource fetching. */
|
|
156
156
|
lazyload?: boolean;
|
|
157
157
|
};
|
|
158
|
-
export type ProfileContextTypeVariant = "inventory" | "trophies" | "achievements" | "leaderboard" | "activity";
|
|
158
|
+
export type ProfileContextTypeVariant = "inventory" | "trophies" | "achievements" | "quests" | "leaderboard" | "activity";
|
|
159
159
|
export type Token = "eth" | "strk" | "lords" | "usdc" | "usdt";
|
|
160
160
|
export type Tokens = {
|
|
161
161
|
erc20?: Token[];
|
package/dist/utils.d.ts
CHANGED
|
@@ -14,3 +14,4 @@ export declare function toArray<T>(val: T | T[]): T[];
|
|
|
14
14
|
export declare function humanizeString(str: string): string;
|
|
15
15
|
export declare function parseChainId(url: URL): ChainId;
|
|
16
16
|
export declare function isMobile(): boolean;
|
|
17
|
+
export declare function sanitizeImageSrc(src: string): string;
|
package/dist/wallets/index.d.ts
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ExternalWalletType } from '../types';
|
|
2
|
+
import { EthereumWalletBase } from '../ethereum-base';
|
|
3
|
+
export declare class PhantomEVMWallet extends EthereumWalletBase {
|
|
4
|
+
readonly type: ExternalWalletType;
|
|
5
|
+
readonly rdns = "app.phantom";
|
|
6
|
+
readonly displayName = "Phantom";
|
|
7
|
+
}
|
package/dist/wallets/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const AUTH_EXTERNAL_WALLETS: readonly ["metamask", "rabby"];
|
|
1
|
+
export declare const AUTH_EXTERNAL_WALLETS: readonly ["metamask", "rabby", "phantom-evm"];
|
|
2
2
|
export type AuthExternalWallet = (typeof AUTH_EXTERNAL_WALLETS)[number];
|
|
3
3
|
export declare const EXTRA_EXTERNAL_WALLETS: readonly ["argent", "braavos", "phantom", "base"];
|
|
4
4
|
export type ExtraExternalWallet = (typeof EXTRA_EXTERNAL_WALLETS)[number];
|
|
5
|
-
export declare const EXTERNAL_WALLETS: readonly ["metamask", "rabby", "argent", "braavos", "phantom", "base"];
|
|
5
|
+
export declare const EXTERNAL_WALLETS: readonly ["metamask", "rabby", "phantom-evm", "argent", "braavos", "phantom", "base"];
|
|
6
6
|
export type ExternalWalletType = (typeof EXTERNAL_WALLETS)[number];
|
|
7
7
|
export type ExternalPlatform = "starknet" | "ethereum" | "solana" | "base" | "arbitrum" | "optimism";
|
|
8
8
|
export interface ExternalWallet {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartridge/controller",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "Cartridge Controller",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"vite-plugin-node-polyfills": "^0.23.0",
|
|
51
51
|
"vite-plugin-top-level-await": "^1.4.4",
|
|
52
52
|
"vite-plugin-wasm": "^3.4.1",
|
|
53
|
-
"@cartridge/tsconfig": "0.11.
|
|
53
|
+
"@cartridge/tsconfig": "0.11.3"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build:deps": "pnpm build",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"build:browser": "vite build",
|
|
59
59
|
"build:node": "tsup --config tsup.node.config.ts",
|
|
60
60
|
"build": "pnpm build:browser && pnpm build:node",
|
|
61
|
-
"build:compat": "pnpm build:browser && pnpm build:node",
|
|
62
61
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
63
62
|
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
64
63
|
"test": "jest",
|
package/src/iframe/base.ts
CHANGED
|
@@ -14,7 +14,6 @@ export class IFrame<CallSender extends {}> implements Modal {
|
|
|
14
14
|
private iframe?: HTMLIFrameElement;
|
|
15
15
|
private container?: HTMLDivElement;
|
|
16
16
|
private onClose?: () => void;
|
|
17
|
-
private child?: AsyncMethodReturns<CallSender>;
|
|
18
17
|
private closeTimeout?: NodeJS.Timeout;
|
|
19
18
|
|
|
20
19
|
constructor({
|
|
@@ -55,7 +54,7 @@ export class IFrame<CallSender extends {}> implements Modal {
|
|
|
55
54
|
iframe.sandbox.add("allow-scripts");
|
|
56
55
|
iframe.sandbox.add("allow-same-origin");
|
|
57
56
|
iframe.allow =
|
|
58
|
-
"publickey-credentials-create *; publickey-credentials-get *; clipboard-write";
|
|
57
|
+
"publickey-credentials-create *; publickey-credentials-get *; clipboard-write; local-network-access *; payment *";
|
|
59
58
|
iframe.style.scrollbarWidth = "none";
|
|
60
59
|
iframe.style.setProperty("-ms-overflow-style", "none");
|
|
61
60
|
iframe.style.setProperty("-webkit-scrollbar", "none");
|
|
@@ -118,20 +117,6 @@ export class IFrame<CallSender extends {}> implements Modal {
|
|
|
118
117
|
{ passive: false },
|
|
119
118
|
);
|
|
120
119
|
|
|
121
|
-
// Add click event listener to close iframe when clicking outside
|
|
122
|
-
container.addEventListener("click", (e) => {
|
|
123
|
-
if (e.target === container) {
|
|
124
|
-
// Attempting to reset(clear context) for keychain iframe (identified by ID)
|
|
125
|
-
if (id === "controller-keychain" && this.child) {
|
|
126
|
-
// Type assertion for keychain child only
|
|
127
|
-
(this.child as any)
|
|
128
|
-
.reset?.()
|
|
129
|
-
.catch((e: any) => console.error("Error resetting context:", e));
|
|
130
|
-
}
|
|
131
|
-
this.close();
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
120
|
this.iframe = iframe;
|
|
136
121
|
this.container = container;
|
|
137
122
|
|
|
@@ -142,10 +127,7 @@ export class IFrame<CallSender extends {}> implements Modal {
|
|
|
142
127
|
reload: (_origin: string) => () => window.location.reload(),
|
|
143
128
|
...methods,
|
|
144
129
|
},
|
|
145
|
-
}).promise.then(
|
|
146
|
-
this.child = child;
|
|
147
|
-
onConnect(child);
|
|
148
|
-
});
|
|
130
|
+
}).promise.then(onConnect);
|
|
149
131
|
|
|
150
132
|
this.resize();
|
|
151
133
|
window.addEventListener("resize", () => this.resize());
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export const CloseButton = (translucent = false): HTMLDivElement => {
|
|
2
|
+
const container = document.createElement("div");
|
|
3
|
+
container.id = "close-button";
|
|
4
|
+
container.style.display = "flex";
|
|
5
|
+
container.style.alignItems = "center";
|
|
6
|
+
container.style.justifyContent = "center";
|
|
7
|
+
|
|
8
|
+
const button = document.createElement("button");
|
|
9
|
+
button.className = translucent
|
|
10
|
+
? "cartridge-close-button translucent"
|
|
11
|
+
: "cartridge-close-button";
|
|
12
|
+
|
|
13
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
14
|
+
svg.setAttribute("width", "20");
|
|
15
|
+
svg.setAttribute("height", "20");
|
|
16
|
+
svg.setAttribute("viewBox", "0 0 20 20");
|
|
17
|
+
svg.setAttribute("fill", "none");
|
|
18
|
+
svg.style.pointerEvents = "none"; // Ensure clicks pass through to button
|
|
19
|
+
|
|
20
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
21
|
+
path.setAttribute(
|
|
22
|
+
"d",
|
|
23
|
+
"M15.5465 14.343C15.8881 14.6837 15.8881 15.2364 15.5465 15.5772C15.2049 15.9179 14.6506 15.9178 14.309 15.5772L10.0006 11.2484L5.66162 15.5757C5.32001 15.9164 4.76575 15.9164 4.4241 15.5757C4.08245 15.235 4.08249 14.6822 4.4241 14.3415L8.76455 10.0157L4.4229 5.65573C4.08128 5.31504 4.08128 4.76227 4.4229 4.42155C4.76451 4.08082 5.31877 4.08086 5.66042 4.42155L10.0006 8.78299L14.3396 4.45573C14.6812 4.11504 15.2355 4.11504 15.5771 4.45573C15.9188 4.79642 15.9187 5.34918 15.5771 5.68991L11.2367 10.0157L15.5465 14.343Z",
|
|
24
|
+
);
|
|
25
|
+
path.setAttribute("class", "cartridge-close-icon");
|
|
26
|
+
|
|
27
|
+
svg.appendChild(path);
|
|
28
|
+
button.appendChild(svg);
|
|
29
|
+
|
|
30
|
+
// Inline critical button styles
|
|
31
|
+
button.style.display = "flex";
|
|
32
|
+
button.style.alignItems = "center";
|
|
33
|
+
button.style.justifyContent = "center";
|
|
34
|
+
button.style.border = "none";
|
|
35
|
+
button.style.background = "transparent";
|
|
36
|
+
button.style.cursor = "pointer";
|
|
37
|
+
button.style.borderRadius = "4px";
|
|
38
|
+
button.style.padding = "10px";
|
|
39
|
+
button.style.gap = "4px";
|
|
40
|
+
button.style.transition = "background-color 0.2s ease";
|
|
41
|
+
|
|
42
|
+
// Add styles dynamically to the correct document
|
|
43
|
+
const targetDoc = container.ownerDocument;
|
|
44
|
+
if (!targetDoc.getElementById("cartridge-close-button-style")) {
|
|
45
|
+
const style = targetDoc.createElement("style");
|
|
46
|
+
style.id = "cartridge-close-button-style";
|
|
47
|
+
style.textContent = `
|
|
48
|
+
.cartridge-close-button .cartridge-close-icon {
|
|
49
|
+
fill: rgba(0, 0, 0, 0.48);
|
|
50
|
+
transition: fill 0.2s ease;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.cartridge-close-button:not(.translucent):hover {
|
|
54
|
+
background-color: #181c19;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.cartridge-close-button:not(.translucent):hover .cartridge-close-icon {
|
|
58
|
+
fill: rgba(255, 255, 255, 0.72);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.cartridge-close-button.translucent .cartridge-close-icon {
|
|
62
|
+
fill: rgba(0, 0, 0, 0.48);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.cartridge-close-button.translucent:hover {
|
|
66
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.cartridge-close-button.translucent:hover .cartridge-close-icon {
|
|
70
|
+
fill: rgba(0, 0, 0, 0.72);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.cartridge-close-button:active {
|
|
74
|
+
transform: scale(0.95);
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
targetDoc.head.appendChild(style);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
container.appendChild(button);
|
|
81
|
+
return container;
|
|
82
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface ProgressBarOptions {
|
|
2
|
+
duration: number; // in milliseconds (0 or Infinity for static full bar)
|
|
3
|
+
onComplete?: () => void;
|
|
4
|
+
borderRadius?: number; // Optional border radius in pixels (default: 8px)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const ProgressBar = (options: ProgressBarOptions): HTMLDivElement => {
|
|
8
|
+
const borderRadius = options.borderRadius ?? 8;
|
|
9
|
+
const isInfiniteDuration =
|
|
10
|
+
!isFinite(options.duration) || options.duration <= 0;
|
|
11
|
+
|
|
12
|
+
const container = document.createElement("div");
|
|
13
|
+
container.className = "cartridge-toast-progress-bar";
|
|
14
|
+
container.style.position = "absolute";
|
|
15
|
+
container.style.bottom = "0";
|
|
16
|
+
container.style.left = "0";
|
|
17
|
+
container.style.right = "0";
|
|
18
|
+
container.style.height = "4px";
|
|
19
|
+
container.style.overflow = "hidden";
|
|
20
|
+
container.style.borderBottomLeftRadius = `${borderRadius}px`;
|
|
21
|
+
container.style.borderBottomRightRadius = `${borderRadius}px`;
|
|
22
|
+
container.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
|
|
23
|
+
|
|
24
|
+
const inside = document.createElement("div");
|
|
25
|
+
inside.className = "cartridge-toast-progress-bar-fill";
|
|
26
|
+
inside.style.position = "absolute";
|
|
27
|
+
inside.style.bottom = "0";
|
|
28
|
+
inside.style.left = "0";
|
|
29
|
+
inside.style.height = "100%";
|
|
30
|
+
inside.style.backgroundColor = "rgba(255, 255, 255, 0.8)";
|
|
31
|
+
inside.style.borderBottomLeftRadius = `${borderRadius}px`;
|
|
32
|
+
|
|
33
|
+
if (isInfiniteDuration) {
|
|
34
|
+
// For infinite duration, show full bar immediately without animation
|
|
35
|
+
inside.style.width = "100%";
|
|
36
|
+
inside.style.transition = "none";
|
|
37
|
+
} else {
|
|
38
|
+
// For finite duration, animate the progress bar
|
|
39
|
+
inside.style.width = "0%";
|
|
40
|
+
inside.style.transition = `width ${options.duration}ms linear`;
|
|
41
|
+
|
|
42
|
+
// Start animation after a brief delay to ensure styles are applied
|
|
43
|
+
requestAnimationFrame(() => {
|
|
44
|
+
requestAnimationFrame(() => {
|
|
45
|
+
inside.style.width = "100%";
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Call onComplete when animation finishes
|
|
50
|
+
if (options.onComplete) {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
options.onComplete?.();
|
|
53
|
+
}, options.duration);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
container.appendChild(inside);
|
|
58
|
+
|
|
59
|
+
return container;
|
|
60
|
+
};
|