@withone/connect 0.13.2 → 0.15.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.
- package/README.md +40 -14
- package/dist/button.d.ts +0 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/platforms.d.ts +1 -1
- package/dist/react.cjs.js +1 -1
- package/dist/react.esm.js +1 -1
- package/dist/server/index.cjs.js +152 -28
- package/dist/server/index.d.ts +14 -2
- package/dist/server/index.esm.js +151 -29
- package/dist/server/types.d.ts +42 -5
- package/dist/svelte.d.ts +1 -1
- package/dist/types.d.ts +19 -16
- package/dist/vue.cjs.js +1 -1
- package/dist/vue.d.ts +15 -24
- package/dist/vue.esm.js +1 -1
- package/package.json +1 -1
- package/skills/one-connect/SKILL.md +25 -12
- package/src/button.ts +11 -78
- package/src/flow.ts +1 -1
- package/src/index.ts +2 -0
- package/src/platforms.ts +1 -1
- package/src/react.ts +2 -3
- package/src/server/index.ts +212 -38
- package/src/server/types.ts +45 -5
- package/src/svelte.ts +1 -1
- package/src/types.ts +20 -16
- package/src/vue.ts +7 -5
package/dist/vue.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("vue"),t=require("@withone/connect");const n={type:Boolean,default:void 0},o=e.defineComponent({name:"OneConnectButton",props:{authorizeUrl:{type:String,required:!0},platforms:{type:Array,default:void 0},connected:n,disabled:n,variant:{type:String,default:void 0},size:{type:String,default:void 0},fullWidth:n,theme:{type:String,default:void 0},connectTheme:{type:String,default:void 0},
|
|
1
|
+
"use strict";var e=require("vue"),t=require("@withone/connect");const n={type:Boolean,default:void 0},o=e.defineComponent({name:"OneConnectButton",props:{authorizeUrl:{type:String,required:!0},logos:{type:Array,default:void 0},platforms:{type:Array,default:void 0},connected:n,disabled:n,variant:{type:String,default:void 0},size:{type:String,default:void 0},fullWidth:n,theme:{type:String,default:void 0},connectTheme:{type:String,default:void 0},label:{type:String,default:void 0},connectedLabel:{type:String,default:void 0},description:{type:String,default:void 0}},emits:{success:()=>!0,error:(e,t)=>"string"==typeof e&&"string"==typeof t,cancel:()=>!0},setup(n,{emit:o}){const r=e.ref(null);let i=null;const l=()=>({...n,onSuccess:()=>o("success"),onError:(e,t)=>o("error",e,t),onCancel:()=>o("cancel")});return e.onMounted(()=>{r.value&&(i=t.renderConnectButton(r.value,l()))}),e.watch(()=>({...n}),()=>{var e;return null===(e=i)||void 0===e?void 0:e.update(l())},{deep:!0}),e.onBeforeUnmount(()=>{var e;null===(e=i)||void 0===e||e.destroy(),i=null}),()=>{var t;return e.h("span",{ref:r,class:"one-connect","data-variant":null!==(t=n.variant)&&void 0!==t?t:"default","data-full-width":n.fullWidth?"":void 0})}}});exports.ConnectButton=o;
|
package/dist/vue.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { PropType } from "vue";
|
|
2
|
-
import { type
|
|
2
|
+
import { type ConnectButtonLogoInput, type ConnectButtonSize, type ConnectButtonTheme, type ConnectButtonVariant, type ConnectFailureCode, type OneConnectTheme } from "@withone/connect";
|
|
3
3
|
export declare const ConnectButton: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
4
|
authorizeUrl: {
|
|
5
5
|
type: StringConstructor;
|
|
6
6
|
required: true;
|
|
7
7
|
};
|
|
8
|
+
logos: {
|
|
9
|
+
type: PropType<ConnectButtonLogoInput[]>;
|
|
10
|
+
default: undefined;
|
|
11
|
+
};
|
|
12
|
+
/** @deprecated use logos */
|
|
8
13
|
platforms: {
|
|
9
|
-
type: PropType<
|
|
14
|
+
type: PropType<ConnectButtonLogoInput[]>;
|
|
10
15
|
default: undefined;
|
|
11
16
|
};
|
|
12
17
|
connected: {
|
|
@@ -37,15 +42,6 @@ export declare const ConnectButton: import("vue").DefineComponent<import("vue").
|
|
|
37
42
|
type: PropType<OneConnectTheme>;
|
|
38
43
|
default: undefined;
|
|
39
44
|
};
|
|
40
|
-
/** @deprecated use connectTheme */
|
|
41
|
-
appTheme: {
|
|
42
|
-
type: PropType<OneConnectTheme>;
|
|
43
|
-
default: undefined;
|
|
44
|
-
};
|
|
45
|
-
accentColor: {
|
|
46
|
-
type: StringConstructor;
|
|
47
|
-
default: undefined;
|
|
48
|
-
};
|
|
49
45
|
label: {
|
|
50
46
|
type: StringConstructor;
|
|
51
47
|
default: undefined;
|
|
@@ -69,8 +65,13 @@ export declare const ConnectButton: import("vue").DefineComponent<import("vue").
|
|
|
69
65
|
type: StringConstructor;
|
|
70
66
|
required: true;
|
|
71
67
|
};
|
|
68
|
+
logos: {
|
|
69
|
+
type: PropType<ConnectButtonLogoInput[]>;
|
|
70
|
+
default: undefined;
|
|
71
|
+
};
|
|
72
|
+
/** @deprecated use logos */
|
|
72
73
|
platforms: {
|
|
73
|
-
type: PropType<
|
|
74
|
+
type: PropType<ConnectButtonLogoInput[]>;
|
|
74
75
|
default: undefined;
|
|
75
76
|
};
|
|
76
77
|
connected: {
|
|
@@ -101,15 +102,6 @@ export declare const ConnectButton: import("vue").DefineComponent<import("vue").
|
|
|
101
102
|
type: PropType<OneConnectTheme>;
|
|
102
103
|
default: undefined;
|
|
103
104
|
};
|
|
104
|
-
/** @deprecated use connectTheme */
|
|
105
|
-
appTheme: {
|
|
106
|
-
type: PropType<OneConnectTheme>;
|
|
107
|
-
default: undefined;
|
|
108
|
-
};
|
|
109
|
-
accentColor: {
|
|
110
|
-
type: StringConstructor;
|
|
111
|
-
default: undefined;
|
|
112
|
-
};
|
|
113
105
|
label: {
|
|
114
106
|
type: StringConstructor;
|
|
115
107
|
default: undefined;
|
|
@@ -131,13 +123,12 @@ export declare const ConnectButton: import("vue").DefineComponent<import("vue").
|
|
|
131
123
|
label: string;
|
|
132
124
|
disabled: boolean;
|
|
133
125
|
connectTheme: OneConnectTheme;
|
|
134
|
-
|
|
135
|
-
platforms:
|
|
126
|
+
logos: ConnectButtonLogoInput[];
|
|
127
|
+
platforms: ConnectButtonLogoInput[];
|
|
136
128
|
variant: ConnectButtonVariant;
|
|
137
129
|
size: ConnectButtonSize;
|
|
138
130
|
theme: ConnectButtonTheme;
|
|
139
131
|
description: string;
|
|
140
132
|
fullWidth: boolean;
|
|
141
|
-
accentColor: string;
|
|
142
133
|
connectedLabel: string;
|
|
143
134
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineComponent as e,ref as t,onMounted as n,watch as o,onBeforeUnmount as r,h as
|
|
1
|
+
import{defineComponent as e,ref as t,onMounted as n,watch as o,onBeforeUnmount as r,h as l}from"vue";import{renderConnectButton as i}from"@withone/connect";const a={type:Boolean,default:void 0},d=e({name:"OneConnectButton",props:{authorizeUrl:{type:String,required:!0},logos:{type:Array,default:void 0},platforms:{type:Array,default:void 0},connected:a,disabled:a,variant:{type:String,default:void 0},size:{type:String,default:void 0},fullWidth:a,theme:{type:String,default:void 0},connectTheme:{type:String,default:void 0},label:{type:String,default:void 0},connectedLabel:{type:String,default:void 0},description:{type:String,default:void 0}},emits:{success:()=>!0,error:(e,t)=>"string"==typeof e&&"string"==typeof t,cancel:()=>!0},setup(e,{emit:a}){const d=t(null);let u=null;const c=()=>({...e,onSuccess:()=>a("success"),onError:(e,t)=>a("error",e,t),onCancel:()=>a("cancel")});return n(()=>{d.value&&(u=i(d.value,c()))}),o(()=>({...e}),()=>{var e;return null===(e=u)||void 0===e?void 0:e.update(c())},{deep:!0}),r(()=>{var e;null===(e=u)||void 0===e||e.destroy(),u=null}),()=>{var t;return l("span",{ref:d,class:"one-connect","data-variant":null!==(t=e.variant)&&void 0!==t?t:"default","data-full-width":e.fullWidth?"":void 0})}}});export{d as ConnectButton};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@withone/connect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "One Connect for your app: the button your users press, the two backend routes as one import, and a server client that calls One with the grant. Users keep their connections in One; your app holds only what they granted.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -110,40 +110,53 @@ import { ConnectButton } from "@withone/connect/react";
|
|
|
110
110
|
|
|
111
111
|
<ConnectButton
|
|
112
112
|
authorizeUrl="/api/one/authorize"
|
|
113
|
-
|
|
113
|
+
logos={["gmail", "stripe"]} // connector slugs, decoration only
|
|
114
114
|
connected={hasGrant} // from the server: await oneConnect.isConnected(userId)
|
|
115
115
|
onSuccess={() => { /* refetch app state */ }}
|
|
116
116
|
onError={(message) => { /* show message */ }}
|
|
117
117
|
/>
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
-
Optional props: `variant` ("default" | "accent" | "block"), `
|
|
121
|
-
|
|
122
|
-
`
|
|
120
|
+
Optional props: `variant` ("default" | "accent" | "block"), `size` ("sm" |
|
|
121
|
+
"md" | "lg"), `fullWidth`, `theme` ("light" | "dark" | "auto"), `label`,
|
|
122
|
+
`description`, `disabled`. The accent variant's colours come from the host's
|
|
123
|
+
`--one-connect-accent` and `--one-connect-accent-fg` CSS variables.
|
|
123
124
|
|
|
124
125
|
Vue: `@withone/connect/vue`, same props. Svelte: `use:connectButton` from
|
|
125
126
|
`@withone/connect/svelte`. Anything else: `import "@withone/connect"` and use
|
|
126
|
-
`<one-connect-button authorize-url="/api/one/authorize"
|
|
127
|
+
`<one-connect-button authorize-url="/api/one/authorize" logos="gmail, stripe">`.
|
|
127
128
|
A custom button in React: `useOneConnect({ authorizeUrl })` returns `{ open, status }`.
|
|
128
129
|
|
|
129
130
|
## 6 - Calling One with the grant
|
|
130
131
|
|
|
132
|
+
The same four steps the One CLI takes: find the action, read its knowledge,
|
|
133
|
+
run it. Always read the knowledge before running an action for the first
|
|
134
|
+
time; it names the required fields, the encoding and any header.
|
|
135
|
+
|
|
131
136
|
```ts
|
|
132
|
-
const connections = await oneConnect.listConnections(userId);
|
|
133
|
-
const
|
|
137
|
+
const connections = await oneConnect.listConnections(userId); // [{ key, platform, access }]
|
|
138
|
+
const [action] = await oneConnect.searchActions(userId, "stripe", "create an invoice"); // best first, 5 by default
|
|
139
|
+
const guide = await oneConnect.getActionKnowledge(userId, action._id); // { knowledge (Markdown), ioSchema, method, path, tags }
|
|
134
140
|
|
|
135
141
|
const reply = await oneConnect.runAction(userId, {
|
|
136
142
|
connectionKey: connection.key,
|
|
137
143
|
actionId: action._id,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
body: payload, // what the guide asks for
|
|
145
|
+
pathParams: { calendarId: "primary" }, // values for {{placeholders}} in the path
|
|
146
|
+
query: { limit: "10" },
|
|
147
|
+
encoding: "json", // or "form" / "multipart", as the guide says
|
|
148
|
+
headers: {}, // only when the guide names one
|
|
141
149
|
});
|
|
142
150
|
// { status, ok, blockedByGrant, data }
|
|
143
151
|
```
|
|
144
152
|
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
`runAction` takes the method and path from the action, fills the path's
|
|
154
|
+
placeholders, puts the connection key in the body of an action One serves
|
|
155
|
+
itself (tag `custom`), and encodes the body as asked. `listActions(userId,
|
|
156
|
+
platform)` lists a whole catalog when search is not enough.
|
|
157
|
+
|
|
158
|
+
Do not set any auth header. The package adds the connect key and the
|
|
159
|
+
user's id to every call it makes.
|
|
147
160
|
|
|
148
161
|
A `403` reply with `blockedByGrant: true` means the call is outside what
|
|
149
162
|
the user granted. Do not retry it.
|
package/src/button.ts
CHANGED
|
@@ -20,8 +20,10 @@ import type {
|
|
|
20
20
|
* custom properties set through the CSSOM, which such a policy allows.
|
|
21
21
|
*
|
|
22
22
|
* Theming hooks for the host page: `--one-connect-font`,
|
|
23
|
-
* `--one-connect-radius`,
|
|
24
|
-
*
|
|
23
|
+
* `--one-connect-radius`, `--one-connect-accent` and
|
|
24
|
+
* `--one-connect-accent-fg` (the accent variant's fill and text), and
|
|
25
|
+
* `::part(button)` / `::part(label)` on the host (`one-connect-button`,
|
|
26
|
+
* or `.one-connect` for the wrappers).
|
|
25
27
|
*/
|
|
26
28
|
|
|
27
29
|
const MAX_VISIBLE_CHIPS = 3;
|
|
@@ -129,57 +131,6 @@ function adoptStyles(root: ShadowRoot): void {
|
|
|
129
131
|
root.appendChild(style);
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
/* ── Accent contrast ──────────────────────────────────────────────── */
|
|
133
|
-
|
|
134
|
-
function parseRgb(color: string): [number, number, number] | null {
|
|
135
|
-
const value = color.trim().toLowerCase();
|
|
136
|
-
const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(value);
|
|
137
|
-
if (hex) {
|
|
138
|
-
const digits = hex[1].length === 3 ? hex[1].replace(/./g, "$&$&") : hex[1];
|
|
139
|
-
return [0, 2, 4].map((i) => parseInt(digits.slice(i, i + 2), 16)) as [
|
|
140
|
-
number,
|
|
141
|
-
number,
|
|
142
|
-
number,
|
|
143
|
-
];
|
|
144
|
-
}
|
|
145
|
-
const rgb = /^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/.exec(value);
|
|
146
|
-
return rgb ? [Number(rgb[1]), Number(rgb[2]), Number(rgb[3])] : null;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Any CSS colour to sRGB, through a canvas when it is not already hex
|
|
150
|
-
* or rgb() ("navy", "hsl(…)"). Null when the browser cannot say. */
|
|
151
|
-
function toRgb(color: string): [number, number, number] | null {
|
|
152
|
-
const direct = parseRgb(color);
|
|
153
|
-
if (direct) return direct;
|
|
154
|
-
try {
|
|
155
|
-
const context = document.createElement("canvas").getContext("2d");
|
|
156
|
-
if (!context) return null;
|
|
157
|
-
context.fillStyle = "#000";
|
|
158
|
-
context.fillStyle = color;
|
|
159
|
-
return parseRgb(String(context.fillStyle));
|
|
160
|
-
} catch {
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const luminance = ([r, g, b]: [number, number, number]): number => {
|
|
166
|
-
const channel = (c: number) => {
|
|
167
|
-
const s = c / 255;
|
|
168
|
-
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
169
|
-
};
|
|
170
|
-
return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
/** Black or white, whichever has the higher WCAG contrast on `color`. */
|
|
174
|
-
export function readableTextOn(color: string): string {
|
|
175
|
-
const rgb = toRgb(color);
|
|
176
|
-
if (!rgb) return CARBON;
|
|
177
|
-
const l = luminance(rgb);
|
|
178
|
-
const onWhite = 1.05 / (l + 0.05);
|
|
179
|
-
const onCarbon = (l + 0.05) / (luminance([10, 12, 11]) + 0.05);
|
|
180
|
-
return onWhite > onCarbon ? WHITE : CARBON;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
134
|
/* ── Rendering ────────────────────────────────────────────────────── */
|
|
184
135
|
|
|
185
136
|
const el = <K extends keyof HTMLElementTagNameMap>(
|
|
@@ -200,7 +151,7 @@ const icon = (svg: string, className = "icon"): HTMLSpanElement => {
|
|
|
200
151
|
};
|
|
201
152
|
|
|
202
153
|
function buildStack(props: ConnectButtonProps): HTMLElement | null {
|
|
203
|
-
const platforms = normalizePlatforms(props.platforms);
|
|
154
|
+
const platforms = normalizePlatforms(props.logos ?? props.platforms);
|
|
204
155
|
if (platforms.length === 0) return null;
|
|
205
156
|
const stack = el("span", "stack");
|
|
206
157
|
stack.setAttribute("aria-hidden", "true");
|
|
@@ -230,7 +181,7 @@ const flowOptions = (
|
|
|
230
181
|
handlers: Pick<OneConnectFlowOptions, "onSuccess" | "onError" | "onCancel">,
|
|
231
182
|
): OneConnectFlowOptions => ({
|
|
232
183
|
authorizeUrl: props.authorizeUrl,
|
|
233
|
-
connectTheme: props.connectTheme
|
|
184
|
+
connectTheme: props.connectTheme,
|
|
234
185
|
...handlers,
|
|
235
186
|
});
|
|
236
187
|
|
|
@@ -311,22 +262,6 @@ export function renderConnectButton(
|
|
|
311
262
|
? (props.connectedLabel ?? "Connected")
|
|
312
263
|
: (props.label ?? "Connect your apps");
|
|
313
264
|
|
|
314
|
-
// Colour props travel as custom properties on the button inside the
|
|
315
|
-
// shadow root, set through the CSSOM: allowed under a strict CSP, and
|
|
316
|
-
// never written to the host, whose attributes belong to whoever
|
|
317
|
-
// rendered it (a server-rendered page must hydrate unchanged).
|
|
318
|
-
if (variant === "accent") {
|
|
319
|
-
const accent = props.accentColor?.trim() || LIME;
|
|
320
|
-
button.style.setProperty("--one-connect-accent", accent);
|
|
321
|
-
button.style.setProperty(
|
|
322
|
-
"--one-connect-accent-fg",
|
|
323
|
-
readableTextOn(accent),
|
|
324
|
-
);
|
|
325
|
-
} else {
|
|
326
|
-
button.style.removeProperty("--one-connect-accent");
|
|
327
|
-
button.style.removeProperty("--one-connect-accent-fg");
|
|
328
|
-
}
|
|
329
|
-
|
|
330
265
|
button.dataset.variant = variant;
|
|
331
266
|
button.dataset.size = props.size ?? "md";
|
|
332
267
|
button.dataset.theme = props.theme ?? "light";
|
|
@@ -438,6 +373,7 @@ export function mountConnectButton(
|
|
|
438
373
|
|
|
439
374
|
const ATTRIBUTES = [
|
|
440
375
|
"authorize-url",
|
|
376
|
+
"logos",
|
|
441
377
|
"platforms",
|
|
442
378
|
"connected",
|
|
443
379
|
"disabled",
|
|
@@ -446,8 +382,6 @@ const ATTRIBUTES = [
|
|
|
446
382
|
"full-width",
|
|
447
383
|
"theme",
|
|
448
384
|
"connect-theme",
|
|
449
|
-
"app-theme",
|
|
450
|
-
"accent-color",
|
|
451
385
|
"label",
|
|
452
386
|
"connected-label",
|
|
453
387
|
"description",
|
|
@@ -510,17 +444,16 @@ export function registerConnectButton(): void {
|
|
|
510
444
|
private props(authorizeUrl: string): ConnectButtonProps {
|
|
511
445
|
return {
|
|
512
446
|
authorizeUrl,
|
|
513
|
-
|
|
447
|
+
logos: parsePlatformsAttribute(
|
|
448
|
+
this.getAttribute("logos") ?? this.getAttribute("platforms"),
|
|
449
|
+
),
|
|
514
450
|
connected: flag(this, "connected"),
|
|
515
451
|
disabled: flag(this, "disabled"),
|
|
516
452
|
variant: attributeAs(this, "variant", ["default", "accent", "block"]),
|
|
517
453
|
size: attributeAs(this, "size", ["sm", "md", "lg"]),
|
|
518
454
|
fullWidth: flag(this, "full-width"),
|
|
519
455
|
theme: attributeAs(this, "theme", ["light", "dark", "auto"]),
|
|
520
|
-
connectTheme:
|
|
521
|
-
attributeAs(this, "connect-theme", ["light", "dark"]) ??
|
|
522
|
-
attributeAs(this, "app-theme", ["light", "dark"]),
|
|
523
|
-
accentColor: this.getAttribute("accent-color") ?? undefined,
|
|
456
|
+
connectTheme: attributeAs(this, "connect-theme", ["light", "dark"]),
|
|
524
457
|
label: this.getAttribute("label") ?? undefined,
|
|
525
458
|
connectedLabel: this.getAttribute("connected-label") ?? undefined,
|
|
526
459
|
description: this.getAttribute("description") ?? undefined,
|
package/src/flow.ts
CHANGED
|
@@ -92,7 +92,7 @@ function bindPageshow(): void {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
const authorizeUrlFor = (options: OneConnectFlowOptions): string => {
|
|
95
|
-
const theme = options.connectTheme
|
|
95
|
+
const theme = options.connectTheme;
|
|
96
96
|
try {
|
|
97
97
|
const url = new URL(options.authorizeUrl, window.location.origin);
|
|
98
98
|
if (theme) url.hash = `${THEME_PARAM}=${theme}`;
|
package/src/index.ts
CHANGED
package/src/platforms.ts
CHANGED
|
@@ -94,7 +94,7 @@ export function normalizePlatforms(
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* The `
|
|
97
|
+
* The `logos` attribute on <one-connect-button>: a comma list of
|
|
98
98
|
* slugs ("stripe, notion") or, for overrides, a JSON array of
|
|
99
99
|
* {slug, name, imageUrl} objects.
|
|
100
100
|
*/
|
package/src/react.ts
CHANGED
|
@@ -30,15 +30,14 @@ export interface ConnectButtonProps extends ConnectButtonCoreProps {
|
|
|
30
30
|
const visualKey = (props: ConnectButtonCoreProps): string =>
|
|
31
31
|
JSON.stringify([
|
|
32
32
|
props.authorizeUrl,
|
|
33
|
-
props.platforms ?? [],
|
|
33
|
+
props.logos ?? props.platforms ?? [],
|
|
34
34
|
props.connected,
|
|
35
35
|
props.disabled,
|
|
36
36
|
props.variant,
|
|
37
37
|
props.size,
|
|
38
38
|
props.fullWidth,
|
|
39
39
|
props.theme,
|
|
40
|
-
props.connectTheme
|
|
41
|
-
props.accentColor,
|
|
40
|
+
props.connectTheme,
|
|
42
41
|
props.label,
|
|
43
42
|
props.connectedLabel,
|
|
44
43
|
props.description,
|