@dexterai/connect 0.7.0 → 0.8.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/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
2
2
  import { S as SignInResult, P as PasskeyLoginTokens, C as ConnectVault, a as ConnectError, c as StoredWallet, b as PasskeySignalSupport } from './signals-CkBFwCNw.js';
3
- import { ReactElement } from 'react';
3
+ import { ReactElement, ReactNode } from 'react';
4
4
 
5
5
  type ConnectStatus = 'idle' | 'pending' | 'done' | 'error';
6
6
  interface UseSignInWithDexterConfig {
@@ -48,24 +48,49 @@ interface SignInWithDexterProps extends UseSignInWithDexterConfig {
48
48
  onError?: (error: ConnectError) => void;
49
49
  /** Button label when signed out. Default "Sign in with Dexter". */
50
50
  label?: string;
51
- /** Visual variant: 'primary' = filled ember (default), 'secondary' = outline. */
51
+ /** 'primary' = filled ember (default), 'secondary' = outline. */
52
52
  variant?: 'primary' | 'secondary';
53
+ /** Full-width button. */
54
+ block?: boolean;
53
55
  /** Extra className composed after the brand classes. Prefer overriding the
54
- * `--dx-*` CSS variables for theming over restyling from scratch. */
56
+ * `--dx-*` CSS variables for theming. */
55
57
  className?: string;
56
- /** Render the built-in connected chip (wallet + balance). Default true.
57
- * Set false to render nothing once connected (consumer renders its own UI). */
58
+ /** Render the built-in connected chip (wallet + balance). Default true. */
58
59
  showConnectedChip?: boolean;
59
60
  }
60
61
  /**
61
- * Turnkey "Sign in with Dexter" element. Signed out → the branded ember button
62
+ * Turnkey "Sign in with Dexter" element. Signed out → the branded DexterButton
62
63
  * (hover / focus / active / loading states, themeable via --dx-* CSS vars);
63
64
  * signed in → a compact chip with the Dexter Wallet address + USD available.
64
- * Wraps useSignInWithDexter; consumers who need the raw vault/passkey data
65
- * should use that hook directly. Brand voice: no emojis, "unlock" banned.
65
+ * Wraps useSignInWithDexter; for the wallet CREATE flow use <DexterButton>
66
+ * wired to your create action. Brand voice: no emojis, "unlock" banned.
66
67
  */
67
68
  declare function SignInWithDexter(props: SignInWithDexterProps): ReactElement | null;
68
69
 
70
+ /** The Dexter passkey mark — the brand glyph carried on the branded button. */
71
+ declare function DexterMark(): ReactElement;
72
+ interface DexterButtonProps {
73
+ /** Button content (e.g. "Sign in with Dexter", "Create your Dexter Wallet"). */
74
+ children?: ReactNode;
75
+ /** Loading state: shows the animated spinner + `loadingLabel`, disables click. */
76
+ loading?: boolean;
77
+ /** Label shown next to the spinner while loading. Default "Connecting…". */
78
+ loadingLabel?: string;
79
+ /** 'primary' = filled ember (default), 'secondary' = outline. */
80
+ variant?: 'primary' | 'secondary';
81
+ /** Full-width (fills its container). */
82
+ block?: boolean;
83
+ /** Render the Dexter mark before the children. Default true. */
84
+ withMark?: boolean;
85
+ onClick?: () => void;
86
+ disabled?: boolean;
87
+ /** Extra className composed after the brand classes. */
88
+ className?: string;
89
+ type?: 'button' | 'submit';
90
+ }
91
+ /** The branded Dexter button. Wire it to any action via `onClick`. */
92
+ declare function DexterButton(props: DexterButtonProps): ReactElement;
93
+
69
94
  interface UseDexterWallet {
70
95
  /** Active wallet handle, or null if this browser has no active wallet. */
71
96
  activeHandle: string | null;
@@ -96,4 +121,4 @@ interface UseDexterWallet {
96
121
  }
97
122
  declare function useDexterWallet(): UseDexterWallet;
98
123
 
99
- export { type ConnectStatus, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useSignInWithDexter };
124
+ export { type ConnectStatus, DexterButton, type DexterButtonProps, DexterMark, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useSignInWithDexter };
package/dist/react.js CHANGED
@@ -116,6 +116,9 @@ function useSignInWithDexter(config = {}) {
116
116
  }
117
117
 
118
118
  // src/SignInWithDexter.tsx
119
+ import { useEffect as useEffect3 } from "react";
120
+
121
+ // src/DexterButton.tsx
119
122
  import { useEffect as useEffect2 } from "react";
120
123
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
121
124
  var STYLE_ID = "dexter-connect-button-styles";
@@ -139,6 +142,7 @@ var BUTTON_CSS = `
139
142
  .dx-btn:disabled{ cursor:default; filter:saturate(.85) brightness(.98); }
140
143
  .dx-btn--secondary{ background:transparent; color:var(--dx-ember); box-shadow:none; border-color:color-mix(in srgb,var(--dx-ember) 45%,transparent); }
141
144
  .dx-btn--secondary:hover{ background:color-mix(in srgb,var(--dx-ember) 9%,transparent); filter:none; box-shadow:none; }
145
+ .dx-btn--block{ width:100%; }
142
146
  .dx-btn__mark{ flex-shrink:0; }
143
147
  .dx-btn__spin{ width:15px; height:15px; flex-shrink:0; border-radius:50%;
144
148
  border:2px solid color-mix(in srgb,currentColor 30%,transparent); border-top-color:currentColor;
@@ -152,7 +156,7 @@ var BUTTON_CSS = `
152
156
  .dx-chip__x{ margin-left:2px; border:none; background:transparent; color:inherit; cursor:pointer; font-size:16px; line-height:1; opacity:.6; }
153
157
  .dx-chip__x:hover{ opacity:1; }
154
158
  `;
155
- function ensureStyles() {
159
+ function ensureDexterButtonStyles() {
156
160
  if (typeof document === "undefined") return;
157
161
  if (document.getElementById(STYLE_ID)) return;
158
162
  const el = document.createElement("style");
@@ -160,16 +164,10 @@ function ensureStyles() {
160
164
  el.textContent = BUTTON_CSS;
161
165
  document.head.appendChild(el);
162
166
  }
163
- ensureStyles();
167
+ ensureDexterButtonStyles();
164
168
  function cx(...parts) {
165
169
  return parts.filter(Boolean).join(" ");
166
170
  }
167
- function shortAddress(addr) {
168
- return addr.length > 10 ? `${addr.slice(0, 4)}\u2026${addr.slice(-4)}` : addr;
169
- }
170
- function formatUsd(n) {
171
- return n.toLocaleString("en-US", { style: "currency", currency: "USD" });
172
- }
173
171
  function DexterMark() {
174
172
  return /* @__PURE__ */ jsxs(
175
173
  "svg",
@@ -188,17 +186,59 @@ function DexterMark() {
188
186
  }
189
187
  );
190
188
  }
189
+ function DexterButton(props) {
190
+ const {
191
+ children,
192
+ loading = false,
193
+ loadingLabel = "Connecting\u2026",
194
+ variant = "primary",
195
+ block = false,
196
+ withMark = true,
197
+ onClick,
198
+ disabled = false,
199
+ className,
200
+ type = "button"
201
+ } = props;
202
+ useEffect2(ensureDexterButtonStyles, []);
203
+ return /* @__PURE__ */ jsx(
204
+ "button",
205
+ {
206
+ type,
207
+ className: cx("dx-btn", variant === "secondary" && "dx-btn--secondary", block && "dx-btn--block", className),
208
+ onClick,
209
+ disabled: disabled || loading,
210
+ "aria-busy": loading,
211
+ children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
212
+ /* @__PURE__ */ jsx("span", { className: "dx-btn__spin", "aria-hidden": true }),
213
+ /* @__PURE__ */ jsx("span", { className: "dx-btn__doing", children: loadingLabel })
214
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
215
+ withMark && /* @__PURE__ */ jsx(DexterMark, {}),
216
+ children
217
+ ] })
218
+ }
219
+ );
220
+ }
221
+
222
+ // src/SignInWithDexter.tsx
223
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
224
+ function shortAddress(addr) {
225
+ return addr.length > 10 ? `${addr.slice(0, 4)}\u2026${addr.slice(-4)}` : addr;
226
+ }
227
+ function formatUsd(n) {
228
+ return n.toLocaleString("en-US", { style: "currency", currency: "USD" });
229
+ }
191
230
  function SignInWithDexter(props) {
192
231
  const {
193
232
  onSuccess,
194
233
  onError,
195
234
  label = "Sign in with Dexter",
196
235
  variant = "primary",
236
+ block = false,
197
237
  className,
198
238
  showConnectedChip = true,
199
239
  ...config
200
240
  } = props;
201
- useEffect2(ensureStyles, []);
241
+ useEffect3(ensureDexterButtonStyles, []);
202
242
  const c = useSignInWithDexter(config);
203
243
  const handleClick = async () => {
204
244
  try {
@@ -209,44 +249,37 @@ function SignInWithDexter(props) {
209
249
  };
210
250
  if (c.isVaultConnected) {
211
251
  if (!showConnectedChip) return null;
212
- return /* @__PURE__ */ jsxs("span", { className: cx("dx-chip", className), children: [
213
- /* @__PURE__ */ jsx("span", { className: "dx-chip__dot", "aria-hidden": true }),
214
- /* @__PURE__ */ jsx("span", { children: c.vaultAddress ? shortAddress(c.vaultAddress) : "Connected" }),
215
- c.usdcBalance !== null && /* @__PURE__ */ jsxs("span", { className: "dx-chip__bal", children: [
252
+ return /* @__PURE__ */ jsxs2("span", { className: cx("dx-chip", className), children: [
253
+ /* @__PURE__ */ jsx2("span", { className: "dx-chip__dot", "aria-hidden": true }),
254
+ /* @__PURE__ */ jsx2("span", { children: c.vaultAddress ? shortAddress(c.vaultAddress) : "Connected" }),
255
+ c.usdcBalance !== null && /* @__PURE__ */ jsxs2("span", { className: "dx-chip__bal", children: [
216
256
  formatUsd(c.usdcBalance),
217
257
  " available"
218
258
  ] }),
219
- /* @__PURE__ */ jsx("button", { type: "button", className: "dx-chip__x", onClick: c.disconnect, "aria-label": "Disconnect", children: "\xD7" })
259
+ /* @__PURE__ */ jsx2("button", { type: "button", className: "dx-chip__x", onClick: c.disconnect, "aria-label": "Disconnect", children: "\xD7" })
220
260
  ] });
221
261
  }
222
- const pending = c.status === "pending";
223
- return /* @__PURE__ */ jsx(
224
- "button",
262
+ return /* @__PURE__ */ jsx2(
263
+ DexterButton,
225
264
  {
226
- type: "button",
227
- className: cx("dx-btn", variant === "secondary" && "dx-btn--secondary", className),
265
+ loading: c.status === "pending",
266
+ variant,
267
+ block,
268
+ className,
228
269
  onClick: handleClick,
229
- disabled: pending,
230
- "aria-busy": pending,
231
- children: pending ? /* @__PURE__ */ jsxs(Fragment, { children: [
232
- /* @__PURE__ */ jsx("span", { className: "dx-btn__spin", "aria-hidden": true }),
233
- /* @__PURE__ */ jsx("span", { className: "dx-btn__doing", children: "Connecting\u2026" })
234
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
235
- /* @__PURE__ */ jsx(DexterMark, {}),
236
- label
237
- ] })
270
+ children: label
238
271
  }
239
272
  );
240
273
  }
241
274
 
242
275
  // src/useDexterWallet.ts
243
- import { useCallback as useCallback2, useEffect as useEffect3, useState as useState2 } from "react";
276
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
244
277
  var NO_SUPPORT = { rename: false, prune: false, syncAccepted: false };
245
278
  function useDexterWallet() {
246
279
  const [activeHandle, setHandle] = useState2(() => getActiveHandle());
247
280
  const [wallets, setWallets] = useState2(() => listWallets());
248
281
  const [support, setSupport] = useState2(NO_SUPPORT);
249
- useEffect3(() => {
282
+ useEffect4(() => {
250
283
  const sync = () => {
251
284
  setHandle(getActiveHandle());
252
285
  setWallets(listWallets());
@@ -282,6 +315,8 @@ function useDexterWallet() {
282
315
  };
283
316
  }
284
317
  export {
318
+ DexterButton,
319
+ DexterMark,
285
320
  SignInWithDexter,
286
321
  useDexterWallet,
287
322
  useSignInWithDexter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexterai/connect",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Sign in with Dexter — passkey connector. Composes @dexterai/vault.",
5
5
  "type": "module",
6
6
  "exports": {