@appkits-ai/ui 0.1.0

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.
Files changed (82) hide show
  1. package/README.md +51 -0
  2. package/dist/components/badge.d.ts +17 -0
  3. package/dist/components/badge.d.ts.map +1 -0
  4. package/dist/components/badge.js +25 -0
  5. package/dist/components/button.d.ts +18 -0
  6. package/dist/components/button.d.ts.map +1 -0
  7. package/dist/components/button.js +36 -0
  8. package/dist/components/card.d.ts +35 -0
  9. package/dist/components/card.d.ts.map +1 -0
  10. package/dist/components/card.js +45 -0
  11. package/dist/components/checkbox.d.ts +7 -0
  12. package/dist/components/checkbox.d.ts.map +1 -0
  13. package/dist/components/checkbox.js +20 -0
  14. package/dist/components/context-menu.d.ts +71 -0
  15. package/dist/components/context-menu.d.ts.map +1 -0
  16. package/dist/components/context-menu.js +100 -0
  17. package/dist/components/dialog.d.ts +46 -0
  18. package/dist/components/dialog.d.ts.map +1 -0
  19. package/dist/components/dialog.js +70 -0
  20. package/dist/components/input.d.ts +11 -0
  21. package/dist/components/input.d.ts.map +1 -0
  22. package/dist/components/input.js +9 -0
  23. package/dist/components/label.d.ts +8 -0
  24. package/dist/components/label.d.ts.map +1 -0
  25. package/dist/components/label.js +15 -0
  26. package/dist/components/notifications.d.ts +5 -0
  27. package/dist/components/notifications.d.ts.map +1 -0
  28. package/dist/components/notifications.js +22 -0
  29. package/dist/components/scroll-area.d.ts +12 -0
  30. package/dist/components/scroll-area.d.ts.map +1 -0
  31. package/dist/components/scroll-area.js +23 -0
  32. package/dist/components/select.d.ts +46 -0
  33. package/dist/components/select.d.ts.map +1 -0
  34. package/dist/components/select.js +72 -0
  35. package/dist/components/switch.d.ts +8 -0
  36. package/dist/components/switch.d.ts.map +1 -0
  37. package/dist/components/switch.js +15 -0
  38. package/dist/components/tabs.d.ts +20 -0
  39. package/dist/components/tabs.d.ts.map +1 -0
  40. package/dist/components/tabs.js +33 -0
  41. package/dist/components/theme-provider.d.ts +8 -0
  42. package/dist/components/theme-provider.d.ts.map +1 -0
  43. package/dist/components/theme-provider.js +14 -0
  44. package/dist/components/tooltip.d.ts +8 -0
  45. package/dist/components/tooltip.d.ts.map +1 -0
  46. package/dist/components/tooltip.js +15 -0
  47. package/dist/components/transfer-status-panel.d.ts +34 -0
  48. package/dist/components/transfer-status-panel.d.ts.map +1 -0
  49. package/dist/components/transfer-status-panel.js +41 -0
  50. package/dist/components/upload-conflict-dialog.d.ts +16 -0
  51. package/dist/components/upload-conflict-dialog.d.ts.map +1 -0
  52. package/dist/components/upload-conflict-dialog.js +24 -0
  53. package/dist/components/upload-drop-overlay.d.ts +15 -0
  54. package/dist/components/upload-drop-overlay.d.ts.map +1 -0
  55. package/dist/components/upload-drop-overlay.js +30 -0
  56. package/dist/hooks/index.d.ts +6 -0
  57. package/dist/hooks/index.d.ts.map +1 -0
  58. package/dist/hooks/index.js +5 -0
  59. package/dist/hooks/use-chain-settings.d.ts +43 -0
  60. package/dist/hooks/use-chain-settings.d.ts.map +1 -0
  61. package/dist/hooks/use-chain-settings.js +313 -0
  62. package/dist/hooks/use-global-dialog.d.ts +28 -0
  63. package/dist/hooks/use-global-dialog.d.ts.map +1 -0
  64. package/dist/hooks/use-global-dialog.js +80 -0
  65. package/dist/hooks/use-sub-app-context-menu.d.ts +5 -0
  66. package/dist/hooks/use-sub-app-context-menu.d.ts.map +1 -0
  67. package/dist/hooks/use-sub-app-context-menu.js +37 -0
  68. package/dist/hooks/use-theme-sync.d.ts +5 -0
  69. package/dist/hooks/use-theme-sync.d.ts.map +1 -0
  70. package/dist/hooks/use-theme-sync.js +36 -0
  71. package/dist/index.d.ts +26 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +25 -0
  74. package/dist/lib/notify.d.ts +21 -0
  75. package/dist/lib/notify.d.ts.map +1 -0
  76. package/dist/lib/notify.js +81 -0
  77. package/dist/lib/utils.d.ts +10 -0
  78. package/dist/lib/utils.d.ts.map +1 -0
  79. package/dist/lib/utils.js +12 -0
  80. package/package.json +79 -0
  81. package/postcss.config.mjs +6 -0
  82. package/src/styles/globals.css +182 -0
@@ -0,0 +1,43 @@
1
+ import { type StateStorage } from "zustand/middleware";
2
+ export type ChainCategory = "evm" | "solana" | "sui" | "ton";
3
+ export interface NetworkConfig {
4
+ id: string;
5
+ name: string;
6
+ chainId: number | string;
7
+ rpcUrl: string;
8
+ defaultRpcUrl: string;
9
+ enabled: boolean;
10
+ currency: string;
11
+ explorerUrl?: string;
12
+ category: ChainCategory;
13
+ }
14
+ interface ChainSettingsStore {
15
+ networks: NetworkConfig[];
16
+ updateNetwork: (id: string, updates: Partial<NetworkConfig>) => void;
17
+ resetNetwork: (id: string) => void;
18
+ resetAll: () => void;
19
+ getNetwork: (chainId: number | string) => NetworkConfig | undefined;
20
+ }
21
+ /**
22
+ * Creates the IndexedDB-backed storage used by Zustand persist.
23
+ */
24
+ export declare function createChainSettingsIndexedDbStorage(): StateStorage;
25
+ export declare const useChainSettingsStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ChainSettingsStore>, "setState" | "persist"> & {
26
+ setState(partial: ChainSettingsStore | Partial<ChainSettingsStore> | ((state: ChainSettingsStore) => ChainSettingsStore | Partial<ChainSettingsStore>), replace?: false | undefined): unknown;
27
+ setState(state: ChainSettingsStore | ((state: ChainSettingsStore) => ChainSettingsStore), replace: true): unknown;
28
+ persist: {
29
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ChainSettingsStore, unknown, unknown>>) => void;
30
+ clearStorage: () => void;
31
+ rehydrate: () => Promise<void> | void;
32
+ hasHydrated: () => boolean;
33
+ onHydrate: (fn: (state: ChainSettingsStore) => void) => () => void;
34
+ onFinishHydration: (fn: (state: ChainSettingsStore) => void) => () => void;
35
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<ChainSettingsStore, unknown, unknown>>;
36
+ };
37
+ }>;
38
+ /**
39
+ * Provides the useChainSettings hook behavior.
40
+ */
41
+ export declare const useChainSettings: () => ChainSettingsStore;
42
+ export {};
43
+ //# sourceMappingURL=use-chain-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chain-settings.d.ts","sourceRoot":"","sources":["../../src/hooks/use-chain-settings.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AA8B5B,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAG1B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACrE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;CACrE;AAoJD;;GAEG;AACH,wBAAgB,mCAAmC,IAAI,YAAY,CAkBlE;AAyGD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAiCjC,CAAC;AAUF;;GAEG;AACH,eAAO,MAAM,gBAAgB,0BAgC5B,CAAC"}
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Defines the use-chain-settings React hook for shared UI behavior.
3
+ * @module ui-package
4
+ */
5
+ import { create } from "zustand";
6
+ import { persist, createJSONStorage, } from "zustand/middleware";
7
+ import { mainnet, sepolia, arbitrum, optimism, polygon, bsc, base, linea, scroll, zksync, avalanche, arbitrumSepolia, baseSepolia, } from "viem/chains";
8
+ // Define a safe fallback for unichain if not exported by default viem version in this workspace
9
+ // ... (Lines 6-15 omitted for brevity, keeping as is in file)
10
+ const unichain = {
11
+ id: 1301,
12
+ name: "Unichain",
13
+ network: "unichain",
14
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
15
+ rpcUrls: {
16
+ default: { http: ["https://rpc.unichain.org"] },
17
+ public: { http: ["https://rpc.unichain.org"] },
18
+ },
19
+ };
20
+ const CHAIN_SETTINGS_DB_NAME = "appkits-chain-settings";
21
+ const CHAIN_SETTINGS_DB_VERSION = 1;
22
+ const CHAIN_SETTINGS_STORE = "settings";
23
+ const CHAIN_SETTINGS_INDEXEDDB_TIMEOUT_MS = 1000;
24
+ const CHAIN_SETTINGS_CACHE_KEY = "appkits-chain-settings";
25
+ const memoryStateStorage = new Map();
26
+ /**
27
+ * Returns the browser IndexedDB factory for chain settings cache.
28
+ */
29
+ function chainSettingsIndexedDb() {
30
+ return typeof indexedDB === "undefined" ? null : indexedDB;
31
+ }
32
+ /**
33
+ * Opens the IndexedDB store for chain settings startup cache.
34
+ */
35
+ async function openChainSettingsDb() {
36
+ const factory = chainSettingsIndexedDb();
37
+ if (!factory)
38
+ return null;
39
+ return new Promise((resolve, reject) => {
40
+ const request = factory.open(CHAIN_SETTINGS_DB_NAME, CHAIN_SETTINGS_DB_VERSION);
41
+ const timer = globalThis.setTimeout(() => reject(new Error("chain_settings_cache_open_timeout")), CHAIN_SETTINGS_INDEXEDDB_TIMEOUT_MS);
42
+ /**
43
+ * Clears the IndexedDB open timeout.
44
+ */
45
+ const finish = () => globalThis.clearTimeout(timer);
46
+ request.onupgradeneeded = () => {
47
+ const db = request.result;
48
+ if (!db.objectStoreNames.contains(CHAIN_SETTINGS_STORE)) {
49
+ db.createObjectStore(CHAIN_SETTINGS_STORE, { keyPath: "key" });
50
+ }
51
+ };
52
+ request.onsuccess = () => {
53
+ finish();
54
+ const db = request.result;
55
+ db.onversionchange = () => db.close();
56
+ resolve(db);
57
+ };
58
+ request.onblocked = () => {
59
+ finish();
60
+ reject(new Error("chain_settings_cache_open_blocked"));
61
+ };
62
+ request.onerror = () => {
63
+ finish();
64
+ reject(request.error || new Error("chain_settings_cache_open_failed"));
65
+ };
66
+ });
67
+ }
68
+ /**
69
+ * Resolves an IndexedDB request result.
70
+ */
71
+ async function indexedDbRequestResult(request) {
72
+ return new Promise((resolve, reject) => {
73
+ request.onsuccess = () => resolve(request.result);
74
+ request.onerror = () => reject(request.error || new Error("indexeddb_request_failed"));
75
+ });
76
+ }
77
+ /**
78
+ * Waits for an IndexedDB transaction to commit.
79
+ */
80
+ async function waitForIndexedDbTransaction(transaction) {
81
+ return new Promise((resolve, reject) => {
82
+ transaction.oncomplete = () => resolve();
83
+ transaction.onerror = () => reject(transaction.error || new Error("indexeddb_transaction_failed"));
84
+ transaction.onabort = () => reject(transaction.error || new Error("indexeddb_transaction_aborted"));
85
+ });
86
+ }
87
+ /**
88
+ * Loads one chain settings cache value from IndexedDB.
89
+ */
90
+ async function loadChainSettingsCache(key) {
91
+ const db = await openChainSettingsDb();
92
+ if (!db)
93
+ return null;
94
+ try {
95
+ const transaction = db.transaction(CHAIN_SETTINGS_STORE, "readonly");
96
+ const record = await indexedDbRequestResult(transaction
97
+ .objectStore(CHAIN_SETTINGS_STORE)
98
+ .get(key));
99
+ return record?.value ?? null;
100
+ }
101
+ finally {
102
+ db.close();
103
+ }
104
+ }
105
+ /**
106
+ * Saves one chain settings cache value into IndexedDB.
107
+ */
108
+ async function saveChainSettingsCache(key, value) {
109
+ const db = await openChainSettingsDb();
110
+ if (!db)
111
+ return;
112
+ try {
113
+ const transaction = db.transaction(CHAIN_SETTINGS_STORE, "readwrite");
114
+ transaction.objectStore(CHAIN_SETTINGS_STORE).put({
115
+ key,
116
+ value,
117
+ updatedAt: new Date().toISOString(),
118
+ });
119
+ await waitForIndexedDbTransaction(transaction);
120
+ }
121
+ finally {
122
+ db.close();
123
+ }
124
+ }
125
+ /**
126
+ * Deletes one chain settings cache value from IndexedDB.
127
+ */
128
+ async function deleteChainSettingsCache(key) {
129
+ const db = await openChainSettingsDb();
130
+ if (!db)
131
+ return;
132
+ try {
133
+ const transaction = db.transaction(CHAIN_SETTINGS_STORE, "readwrite");
134
+ transaction.objectStore(CHAIN_SETTINGS_STORE).delete(key);
135
+ await waitForIndexedDbTransaction(transaction);
136
+ }
137
+ finally {
138
+ db.close();
139
+ }
140
+ }
141
+ /**
142
+ * Creates the IndexedDB-backed storage used by Zustand persist.
143
+ */
144
+ export function createChainSettingsIndexedDbStorage() {
145
+ return {
146
+ getItem: async (name) => {
147
+ const key = name || CHAIN_SETTINGS_CACHE_KEY;
148
+ const cached = await loadChainSettingsCache(key);
149
+ return cached ?? memoryStateStorage.get(key) ?? null;
150
+ },
151
+ setItem: async (name, value) => {
152
+ const key = name || CHAIN_SETTINGS_CACHE_KEY;
153
+ memoryStateStorage.set(key, value);
154
+ await saveChainSettingsCache(key, value);
155
+ },
156
+ removeItem: async (name) => {
157
+ const key = name || CHAIN_SETTINGS_CACHE_KEY;
158
+ memoryStateStorage.delete(key);
159
+ await deleteChainSettingsCache(key);
160
+ },
161
+ };
162
+ }
163
+ // Better Public RPCs
164
+ const PUBLIC_RPCS = {
165
+ "1": "https://ethereum-rpc.publicnode.com",
166
+ "56": "https://bsc-rpc.publicnode.com",
167
+ "8453": "https://base-rpc.publicnode.com",
168
+ "42161": "https://arbitrum-one-rpc.publicnode.com",
169
+ "10": "https://optimism-rpc.publicnode.com",
170
+ "137": "https://polygon-bor-rpc.publicnode.com",
171
+ "11155111": "https://ethereum-sepolia-rpc.publicnode.com",
172
+ };
173
+ // Initial Configuration
174
+ const CHAINS_DATA = [
175
+ // EVM
176
+ { chain: mainnet, id: "mainnet", enabled: true, category: "evm" },
177
+ { chain: bsc, id: "bsc", enabled: true, category: "evm" },
178
+ { chain: base, id: "base", enabled: true, category: "evm" },
179
+ { chain: arbitrum, id: "arbitrum", enabled: true, category: "evm" },
180
+ { chain: optimism, id: "optimism", enabled: true, category: "evm" },
181
+ { chain: polygon, id: "polygon", enabled: true, category: "evm" },
182
+ {
183
+ chain: arbitrumSepolia,
184
+ id: "arbitrum-sepolia",
185
+ enabled: false,
186
+ category: "evm",
187
+ },
188
+ { chain: baseSepolia, id: "base-sepolia", enabled: false, category: "evm" },
189
+ { chain: linea, id: "linea", enabled: false, category: "evm" },
190
+ { chain: scroll, id: "scroll", enabled: false, category: "evm" },
191
+ { chain: zksync, id: "zksync", enabled: false, category: "evm" },
192
+ { chain: avalanche, id: "avalanche", enabled: false, category: "evm" },
193
+ { chain: unichain, id: "unichain", enabled: false, category: "evm" },
194
+ { chain: sepolia, id: "sepolia", enabled: true, category: "evm" },
195
+ // Non-EVM Placeholders
196
+ {
197
+ id: "solana-mainnet",
198
+ name: "Solana",
199
+ chainId: "solana-mainnet",
200
+ rpcUrl: "https://api.mainnet-beta.solana.com",
201
+ defaultRpcUrl: "https://api.mainnet-beta.solana.com",
202
+ enabled: true,
203
+ currency: "SOL",
204
+ category: "solana",
205
+ chain: null, // Special handling
206
+ },
207
+ {
208
+ id: "sui-mainnet",
209
+ name: "Sui",
210
+ chainId: "sui-mainnet",
211
+ rpcUrl: "https://fullnode.mainnet.sui.io:443",
212
+ defaultRpcUrl: "https://fullnode.mainnet.sui.io:443",
213
+ enabled: true,
214
+ currency: "SUI",
215
+ category: "sui",
216
+ chain: null,
217
+ },
218
+ {
219
+ id: "ton-mainnet",
220
+ name: "TON",
221
+ chainId: "ton-mainnet",
222
+ rpcUrl: "https://toncenter.com/api/v2/jsonRPC",
223
+ defaultRpcUrl: "https://toncenter.com/api/v2/jsonRPC",
224
+ enabled: true,
225
+ currency: "TON",
226
+ category: "ton",
227
+ chain: null,
228
+ },
229
+ ];
230
+ const INITIAL_NETWORKS = CHAINS_DATA.map((item) => {
231
+ if (item.chain) {
232
+ // EVM
233
+ const rpc = PUBLIC_RPCS[String(item.chain.id)] || item.chain.rpcUrls.default.http[0];
234
+ return {
235
+ id: item.id,
236
+ name: item.chain.name,
237
+ chainId: item.chain.id,
238
+ rpcUrl: rpc,
239
+ defaultRpcUrl: rpc,
240
+ enabled: item.enabled,
241
+ currency: item.chain.nativeCurrency.symbol,
242
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
243
+ explorerUrl: item.chain.blockExplorers?.default?.url,
244
+ category: "evm",
245
+ };
246
+ }
247
+ else {
248
+ // Non-EVM
249
+ return {
250
+ id: item.id,
251
+ name: item.name,
252
+ chainId: item.chainId,
253
+ rpcUrl: item.rpcUrl,
254
+ defaultRpcUrl: item.defaultRpcUrl,
255
+ enabled: item.enabled,
256
+ currency: item.currency,
257
+ category: item.category,
258
+ };
259
+ }
260
+ });
261
+ // Export the raw store for direct usage if needed (though the hook is preferred)
262
+ export const useChainSettingsStore = create()(persist((set, get) => {
263
+ return {
264
+ networks: INITIAL_NETWORKS,
265
+ updateNetwork: (id, updates) => set((state) => ({
266
+ networks: state.networks.map((n) => n.id === id ? { ...n, ...updates } : n),
267
+ })),
268
+ resetNetwork: (id) => set((state) => ({
269
+ networks: state.networks.map((n) => n.id === id ? { ...n, rpcUrl: n.defaultRpcUrl } : n),
270
+ })),
271
+ resetAll: () => set({ networks: INITIAL_NETWORKS }),
272
+ getNetwork: (chainId) => get().networks.find((n) => n.chainId === chainId),
273
+ };
274
+ }, {
275
+ name: "appkits-chain-settings",
276
+ storage: createJSONStorage(createChainSettingsIndexedDbStorage),
277
+ partialize: (state) => ({ networks: state.networks }),
278
+ skipHydration: true,
279
+ }));
280
+ // Auto-hydrate
281
+ if (typeof window !== "undefined") {
282
+ void useChainSettingsStore.persist.rehydrate();
283
+ }
284
+ // Export a hook that manages sync
285
+ import { useEffect } from "react";
286
+ /**
287
+ * Provides the useChainSettings hook behavior.
288
+ */
289
+ export const useChainSettings = () => {
290
+ const store = useChainSettingsStore();
291
+ useEffect(() => {
292
+ // Only run if we are in an iframe (child app)
293
+ if (typeof window !== "undefined" && window.parent !== window) {
294
+ // 1. Listen for updates from parent
295
+ /**
296
+ * Handles Message behavior.
297
+ */
298
+ const handleMessage = (event) => {
299
+ if (event.data?.type === "UPDATE_CHAIN_SETTINGS" &&
300
+ Array.isArray(event.data.payload)) {
301
+ // Update store directly without triggering a re-save loops if possible,
302
+ // but here we just update the state.
303
+ useChainSettingsStore.setState({ networks: event.data.payload });
304
+ }
305
+ };
306
+ window.addEventListener("message", handleMessage);
307
+ // 2. Request initial settings
308
+ window.parent.postMessage({ type: "REQUEST_CHAIN_SETTINGS" }, "*");
309
+ return () => window.removeEventListener("message", handleMessage);
310
+ }
311
+ }, []);
312
+ return store;
313
+ };
@@ -0,0 +1,28 @@
1
+ export interface DialogButton {
2
+ label: string;
3
+ action: string;
4
+ variant?: "default" | "secondary" | "destructive" | "outline";
5
+ }
6
+ export interface DialogStep {
7
+ id: string;
8
+ label: string;
9
+ status: "pending" | "loading" | "success" | "error";
10
+ }
11
+ export interface DialogParams {
12
+ type: "info" | "success" | "error" | "loading" | "signature";
13
+ title: string;
14
+ description?: string;
15
+ buttons?: DialogButton[];
16
+ steps?: DialogStep[];
17
+ appId?: string;
18
+ }
19
+ export interface UseGlobalDialogReturn {
20
+ openDialog: (params: Omit<DialogParams, "appId">) => Promise<string>;
21
+ updateDialog: (updates: Partial<DialogParams>) => void;
22
+ closeDialog: () => void;
23
+ }
24
+ /**
25
+ * Provides the useGlobalDialog hook behavior.
26
+ */
27
+ export declare function useGlobalDialog(): UseGlobalDialogReturn;
28
+ //# sourceMappingURL=use-global-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-global-dialog.d.ts","sourceRoot":"","sources":["../../src/hooks/use-global-dialog.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;CAC/D;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;CACrD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACvD,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,qBAAqB,CA4FvD"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Defines the use-global-dialog React hook for shared UI behavior.
3
+ * @module ui-package
4
+ */
5
+ import { useEffect, useCallback, useRef } from "react";
6
+ /**
7
+ * Provides the useGlobalDialog hook behavior.
8
+ */
9
+ export function useGlobalDialog() {
10
+ const activeRequestId = useRef(null);
11
+ const pendingPromise = useRef(null);
12
+ const openDialog = useCallback((params) => {
13
+ const id = Math.random().toString(36).substr(2, 9);
14
+ activeRequestId.current = id;
15
+ // Infer appId from URL or context?
16
+ // We can pass appId from the consuming app if it knows it.
17
+ // Or Desktop infers it.
18
+ // For now, let's assume Desktop can infer focused window if we don't pass it,
19
+ // OR we pass `window.name` or similar if sub-apps are aware of their ID.
20
+ // Actually WindowFrame sets valid appId via query param or simple assumption?
21
+ // Let's pass a known appId if possible, e.g. "token-factory".
22
+ // Actually, the GlobalDialogManager logic:
23
+ // `if (newParams.appId) focusWindow(newParams.appId)`
24
+ // Sub-apps might not know their own ID easily without it being injected.
25
+ // We will try to pass `window.name` which might be set by `WindowFrame`??
26
+ // WindowFrame uses `src={window.contentUrl}`. It doesn't set `name`.
27
+ // Workaround: We'll rely on the consuming app to pass its ID if it wants focus.
28
+ // Or simply `TokenFactory` knows it's "token-factory".
29
+ return new Promise((resolve, reject) => {
30
+ pendingPromise.current = { resolve, reject };
31
+ window.parent.postMessage({
32
+ type: "GLOBAL_DIALOG_REQUEST",
33
+ params: {
34
+ ...params,
35
+ id,
36
+ // appId will be merged in by the caller if they add it to params, or we can add it here if we knew it.
37
+ },
38
+ }, "*");
39
+ });
40
+ }, []);
41
+ const updateDialog = useCallback((updates) => {
42
+ if (!activeRequestId.current)
43
+ return;
44
+ window.parent.postMessage({
45
+ type: "GLOBAL_DIALOG_UPDATE",
46
+ updates: { ...updates, id: activeRequestId.current },
47
+ }, "*");
48
+ }, []);
49
+ const closeDialog = useCallback(() => {
50
+ window.parent.postMessage({
51
+ type: "GLOBAL_DIALOG_CLOSE",
52
+ }, "*");
53
+ if (pendingPromise.current) {
54
+ pendingPromise.current.resolve("close"); // or reject?
55
+ pendingPromise.current = null;
56
+ }
57
+ activeRequestId.current = null;
58
+ }, []);
59
+ useEffect(() => {
60
+ /**
61
+ * Handles Message behavior.
62
+ */
63
+ const handleMessage = (event) => {
64
+ if (event.data?.type === "GLOBAL_DIALOG_RESPONSE") {
65
+ if (event.data.id === activeRequestId.current) {
66
+ if (pendingPromise.current) {
67
+ pendingPromise.current.resolve(event.data.action);
68
+ pendingPromise.current = null;
69
+ }
70
+ if (event.data.action === "close" || event.data.action === "cancel") {
71
+ activeRequestId.current = null;
72
+ }
73
+ }
74
+ }
75
+ };
76
+ window.addEventListener("message", handleMessage);
77
+ return () => window.removeEventListener("message", handleMessage);
78
+ }, []);
79
+ return { openDialog, updateDialog, closeDialog };
80
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Provides the useSubAppContextMenu hook behavior.
3
+ */
4
+ export declare const useSubAppContextMenu: () => void;
5
+ //# sourceMappingURL=use-sub-app-context-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-sub-app-context-menu.d.ts","sourceRoot":"","sources":["../../src/hooks/use-sub-app-context-menu.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,eAAO,MAAM,oBAAoB,YA2BhC,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Defines the use-sub-app-context-menu React hook for shared UI behavior.
3
+ * @module ui-package
4
+ */
5
+ "use client";
6
+ import { useEffect } from "react";
7
+ import { contextMenu, isInsideAppKits } from "@appkits-ai/sdk/client";
8
+ /**
9
+ * Provides the useSubAppContextMenu hook behavior.
10
+ */
11
+ export const useSubAppContextMenu = () => {
12
+ useEffect(() => {
13
+ /**
14
+ * Handles ContextMenu behavior.
15
+ */
16
+ const handleContextMenu = (e) => {
17
+ e.preventDefault();
18
+ if (!isInsideAppKits())
19
+ return;
20
+ void contextMenu.open({ x: e.clientX, y: e.clientY });
21
+ };
22
+ /**
23
+ * Handles Click behavior.
24
+ */
25
+ const handleClick = () => {
26
+ if (!isInsideAppKits())
27
+ return;
28
+ void contextMenu.close();
29
+ };
30
+ window.addEventListener("contextmenu", handleContextMenu);
31
+ window.addEventListener("click", handleClick);
32
+ return () => {
33
+ window.removeEventListener("contextmenu", handleContextMenu);
34
+ window.removeEventListener("click", handleClick);
35
+ };
36
+ }, []);
37
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Provides the useThemeSync hook behavior.
3
+ */
4
+ export declare function useThemeSync(): void;
5
+ //# sourceMappingURL=use-theme-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-theme-sync.d.ts","sourceRoot":"","sources":["../../src/hooks/use-theme-sync.ts"],"names":[],"mappings":"AAcA;;GAEG;AACH,wBAAgB,YAAY,SA4B3B"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Defines the use-theme-sync React hook for shared UI behavior.
3
+ * @module ui-package
4
+ */
5
+ "use client";
6
+ import { useEffect } from "react";
7
+ import { useTheme } from "next-themes";
8
+ /**
9
+ * Provides the useThemeSync hook behavior.
10
+ */
11
+ export function useThemeSync() {
12
+ const { setTheme } = useTheme();
13
+ useEffect(() => {
14
+ /**
15
+ * Handles Message behavior.
16
+ */
17
+ const handleMessage = (event) => {
18
+ if (event.data && event.data.type === "THEME_CHANGE") {
19
+ const message = event.data;
20
+ setTheme(message.theme);
21
+ // Fallback: Force class on HTML element strictly
22
+ const html = document.documentElement;
23
+ html.classList.remove("light", "dark");
24
+ html.classList.add(message.theme);
25
+ }
26
+ };
27
+ window.addEventListener("message", handleMessage);
28
+ // Tell parent we are ready (optional, good for initial sync)
29
+ if (window.parent && window.parent !== window) {
30
+ window.parent.postMessage({ type: "APP_READY" }, "*");
31
+ }
32
+ return () => {
33
+ window.removeEventListener("message", handleMessage);
34
+ };
35
+ }, [setTheme]);
36
+ }
@@ -0,0 +1,26 @@
1
+ export * from "./components/badge.js";
2
+ export * from "./components/button.js";
3
+ export * from "./components/card.js";
4
+ export * from "./components/checkbox.js";
5
+ export * from "./components/context-menu.js";
6
+ export * from "./components/dialog.js";
7
+ export * from "./components/input.js";
8
+ export * from "./components/label.js";
9
+ export * from "./components/notifications.js";
10
+ export * from "./components/scroll-area.js";
11
+ export * from "./components/select.js";
12
+ export * from "./components/switch.js";
13
+ export * from "./components/tabs.js";
14
+ export * from "./components/theme-provider.js";
15
+ export * from "./components/tooltip.js";
16
+ export * from "./components/transfer-status-panel.js";
17
+ export * from "./components/upload-conflict-dialog.js";
18
+ export * from "./components/upload-drop-overlay.js";
19
+ export * from "./hooks/index.js";
20
+ export * from "./hooks/use-chain-settings.js";
21
+ export * from "./hooks/use-global-dialog.js";
22
+ export * from "./hooks/use-sub-app-context-menu.js";
23
+ export * from "./hooks/use-theme-sync.js";
24
+ export * from "./lib/notify.js";
25
+ export * from "./lib/utils.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AACpD,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ export * from "./components/badge.js";
2
+ export * from "./components/button.js";
3
+ export * from "./components/card.js";
4
+ export * from "./components/checkbox.js";
5
+ export * from "./components/context-menu.js";
6
+ export * from "./components/dialog.js";
7
+ export * from "./components/input.js";
8
+ export * from "./components/label.js";
9
+ export * from "./components/notifications.js";
10
+ export * from "./components/scroll-area.js";
11
+ export * from "./components/select.js";
12
+ export * from "./components/switch.js";
13
+ export * from "./components/tabs.js";
14
+ export * from "./components/theme-provider.js";
15
+ export * from "./components/tooltip.js";
16
+ export * from "./components/transfer-status-panel.js";
17
+ export * from "./components/upload-conflict-dialog.js";
18
+ export * from "./components/upload-drop-overlay.js";
19
+ export * from "./hooks/index.js";
20
+ export * from "./hooks/use-chain-settings.js";
21
+ export * from "./hooks/use-global-dialog.js";
22
+ export * from "./hooks/use-sub-app-context-menu.js";
23
+ export * from "./hooks/use-theme-sync.js";
24
+ export * from "./lib/notify.js";
25
+ export * from "./lib/utils.js";
@@ -0,0 +1,21 @@
1
+ export interface NotificationAction {
2
+ label: string;
3
+ url?: string;
4
+ onClick?: () => void;
5
+ }
6
+ export interface NotificationOptions {
7
+ action?: NotificationAction;
8
+ type?: "default" | "success" | "error" | "loading" | "info";
9
+ duration?: number;
10
+ icon?: React.ReactNode;
11
+ id?: string | number;
12
+ }
13
+ /**
14
+ * Implements notify behavior.
15
+ */
16
+ export declare function notify(title: string, body?: string, optionsOrAction?: NotificationOptions | NotificationAction): string | number;
17
+ /**
18
+ * Implements dismiss behavior.
19
+ */
20
+ export declare function dismiss(id: string | number): void;
21
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/lib/notify.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,EACb,eAAe,CAAC,EAAE,mBAAmB,GAAG,kBAAkB,mBAkE3D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,QAQ1C"}