@orangecheck/auth-client 0.3.0 → 0.4.1

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/index.d.mts CHANGED
@@ -33,6 +33,15 @@ declare function OcSessionProvider({ children, config, defaultReturnTo, }: OcSes
33
33
  declare function useOcSession(): OcSessionState;
34
34
  declare function useOptionalOcSession(): OcSessionState | null;
35
35
 
36
+ interface OcAccountChipProps {
37
+ dashboardUrl?: string;
38
+ signInLabel?: string;
39
+ className?: string;
40
+ triggerClassName?: string;
41
+ popoverClassName?: string;
42
+ menuItemClassName?: string;
43
+ }
44
+ declare function OcAccountChip({ dashboardUrl, signInLabel, className, triggerClassName, popoverClassName, menuItemClassName, }: OcAccountChipProps): React.ReactElement | null;
36
45
  interface OcSignInButtonProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
37
46
  label?: string;
38
47
  eager?: boolean;
@@ -79,4 +88,4 @@ interface UseOcAddressSuggestionReturn {
79
88
  declare function useOcAddressSuggestion(options: UseOcAddressSuggestionOptions): UseOcAddressSuggestionReturn;
80
89
  declare const OcAddressInput: React.ForwardRefExoticComponent<OcAddressInputProps & React.RefAttributes<HTMLInputElement>>;
81
90
 
82
- export { DEFAULT_CONFIG, type OcAccount, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignInButton, type OcSignInButtonProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
91
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignInButton, type OcSignInButtonProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
package/dist/index.d.ts CHANGED
@@ -33,6 +33,15 @@ declare function OcSessionProvider({ children, config, defaultReturnTo, }: OcSes
33
33
  declare function useOcSession(): OcSessionState;
34
34
  declare function useOptionalOcSession(): OcSessionState | null;
35
35
 
36
+ interface OcAccountChipProps {
37
+ dashboardUrl?: string;
38
+ signInLabel?: string;
39
+ className?: string;
40
+ triggerClassName?: string;
41
+ popoverClassName?: string;
42
+ menuItemClassName?: string;
43
+ }
44
+ declare function OcAccountChip({ dashboardUrl, signInLabel, className, triggerClassName, popoverClassName, menuItemClassName, }: OcAccountChipProps): React.ReactElement | null;
36
45
  interface OcSignInButtonProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
37
46
  label?: string;
38
47
  eager?: boolean;
@@ -79,4 +88,4 @@ interface UseOcAddressSuggestionReturn {
79
88
  declare function useOcAddressSuggestion(options: UseOcAddressSuggestionOptions): UseOcAddressSuggestionReturn;
80
89
  declare const OcAddressInput: React.ForwardRefExoticComponent<OcAddressInputProps & React.RefAttributes<HTMLInputElement>>;
81
90
 
82
- export { DEFAULT_CONFIG, type OcAccount, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignInButton, type OcSignInButtonProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
91
+ export { DEFAULT_CONFIG, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignInButton, type OcSignInButtonProps, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, buildSignInUrl, useOcAddressSuggestion, useOcSession, useOptionalOcSession };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React = require('react');
3
+ var React2 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  function _interopNamespace(e) {
@@ -21,7 +21,7 @@ function _interopNamespace(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
 
24
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
25
25
 
26
26
  // src/provider.tsx
27
27
 
@@ -42,7 +42,7 @@ function buildSignInUrl(cfg, returnTo) {
42
42
  u.searchParams.set("return_to", returnTo);
43
43
  return u.toString();
44
44
  }
45
- var SessionContext = React__namespace.createContext(null);
45
+ var SessionContext = React2__namespace.createContext(null);
46
46
  function normalizeAccount(raw) {
47
47
  if (!raw) return null;
48
48
  const address = raw.btc_address ?? raw.address;
@@ -60,11 +60,11 @@ function OcSessionProvider({
60
60
  config,
61
61
  defaultReturnTo
62
62
  }) {
63
- const cfg = React__namespace.useMemo(() => resolveConfig(config), [config]);
64
- const [account, setAccount] = React__namespace.useState(null);
65
- const [status, setStatus] = React__namespace.useState("loading");
66
- const [error, setError] = React__namespace.useState(null);
67
- const refresh = React__namespace.useCallback(async () => {
63
+ const cfg = React2__namespace.useMemo(() => resolveConfig(config), [config]);
64
+ const [account, setAccount] = React2__namespace.useState(null);
65
+ const [status, setStatus] = React2__namespace.useState("loading");
66
+ const [error, setError] = React2__namespace.useState(null);
67
+ const refresh = React2__namespace.useCallback(async () => {
68
68
  if (typeof window === "undefined") return;
69
69
  try {
70
70
  const res = await fetch(cfg.mePath, {
@@ -93,10 +93,10 @@ function OcSessionProvider({
93
93
  setError(err instanceof Error ? err : new Error(String(err)));
94
94
  }
95
95
  }, [cfg.mePath]);
96
- React__namespace.useEffect(() => {
96
+ React2__namespace.useEffect(() => {
97
97
  void refresh();
98
98
  }, [refresh]);
99
- const signOut = React__namespace.useCallback(async () => {
99
+ const signOut = React2__namespace.useCallback(async () => {
100
100
  try {
101
101
  await fetch(`${cfg.authOrigin}${cfg.logoutPath}`, {
102
102
  method: "POST",
@@ -107,7 +107,7 @@ function OcSessionProvider({
107
107
  setAccount(null);
108
108
  setStatus("anonymous");
109
109
  }, [cfg.authOrigin, cfg.logoutPath]);
110
- const value = React__namespace.useMemo(() => {
110
+ const value = React2__namespace.useMemo(() => {
111
111
  const returnTo = defaultReturnTo ?? (typeof window !== "undefined" ? window.location.href : void 0);
112
112
  return {
113
113
  status,
@@ -121,7 +121,7 @@ function OcSessionProvider({
121
121
  return /* @__PURE__ */ jsxRuntime.jsx(SessionContext.Provider, { value, children });
122
122
  }
123
123
  function useOcSession() {
124
- const ctx = React__namespace.useContext(SessionContext);
124
+ const ctx = React2__namespace.useContext(SessionContext);
125
125
  if (!ctx) {
126
126
  throw new Error(
127
127
  "[@orangecheck/auth-client] useOcSession() must be called inside <OcSessionProvider>"
@@ -130,7 +130,7 @@ function useOcSession() {
130
130
  return ctx;
131
131
  }
132
132
  function useOptionalOcSession() {
133
- return React__namespace.useContext(SessionContext);
133
+ return React2__namespace.useContext(SessionContext);
134
134
  }
135
135
  function shortenAddress(addr) {
136
136
  if (addr.length <= 12) return addr;
@@ -145,9 +145,270 @@ function isPrefixOf(value, target) {
145
145
  }
146
146
  var listboxIdCounter = 0;
147
147
  function useUniqueId(prefix) {
148
- const [id] = React__namespace.useState(() => `${prefix}-${++listboxIdCounter}`);
148
+ const [id] = React2__namespace.useState(() => `${prefix}-${++listboxIdCounter}`);
149
149
  return id;
150
150
  }
151
+ function OcAccountChip({
152
+ dashboardUrl = "https://ochk.io/dashboard",
153
+ signInLabel = "sign in",
154
+ className,
155
+ triggerClassName,
156
+ popoverClassName,
157
+ menuItemClassName
158
+ }) {
159
+ const { status, account, signInUrl, signOut } = useOcSession();
160
+ const [open, setOpen] = React2__namespace.useState(false);
161
+ const wrapRef = React2__namespace.useRef(null);
162
+ React2__namespace.useEffect(() => {
163
+ if (!open) return;
164
+ function handleClickOutside(e) {
165
+ if (wrapRef.current && !wrapRef.current.contains(e.target)) {
166
+ setOpen(false);
167
+ }
168
+ }
169
+ function handleEscape(e) {
170
+ if (e.key === "Escape") setOpen(false);
171
+ }
172
+ document.addEventListener("mousedown", handleClickOutside);
173
+ document.addEventListener("keydown", handleEscape);
174
+ return () => {
175
+ document.removeEventListener("mousedown", handleClickOutside);
176
+ document.removeEventListener("keydown", handleEscape);
177
+ };
178
+ }, [open]);
179
+ if (status === "loading") return null;
180
+ if (status !== "authenticated" || !account) {
181
+ return /* @__PURE__ */ jsxRuntime.jsx(
182
+ "a",
183
+ {
184
+ href: signInUrl,
185
+ className: triggerClassName ?? className,
186
+ "data-oc-account-chip-signin": "",
187
+ children: signInLabel
188
+ }
189
+ );
190
+ }
191
+ return /* @__PURE__ */ jsxRuntime.jsxs(
192
+ "div",
193
+ {
194
+ ref: wrapRef,
195
+ className,
196
+ "data-oc-account-chip": "",
197
+ style: { position: "relative", display: "inline-block" },
198
+ children: [
199
+ /* @__PURE__ */ jsxRuntime.jsxs(
200
+ "button",
201
+ {
202
+ type: "button",
203
+ onClick: () => setOpen((v) => !v),
204
+ "aria-haspopup": "menu",
205
+ "aria-expanded": open,
206
+ "aria-label": `Signed in as ${account.address}. Open account menu.`,
207
+ className: triggerClassName,
208
+ "data-oc-account-chip-trigger": "",
209
+ style: triggerClassName ? void 0 : {
210
+ display: "inline-flex",
211
+ alignItems: "center",
212
+ gap: "0.4rem",
213
+ padding: "0.25rem 0.625rem",
214
+ borderRadius: "9999px",
215
+ border: "1px solid var(--border, #27272a)",
216
+ background: "color-mix(in oklch, var(--muted, #27272a) 40%, transparent)",
217
+ color: "var(--foreground, #fafafa)",
218
+ fontFamily: "ui-monospace, SFMono-Regular, monospace",
219
+ fontSize: 12,
220
+ cursor: "pointer"
221
+ },
222
+ children: [
223
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { color: "#22c55e", fontSize: 8 }, children: "\u25CF" }),
224
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: shortenAddress(account.address) }),
225
+ /* @__PURE__ */ jsxRuntime.jsx(
226
+ "svg",
227
+ {
228
+ width: "9",
229
+ height: "9",
230
+ viewBox: "0 0 10 10",
231
+ "aria-hidden": "true",
232
+ style: {
233
+ transition: "transform 120ms",
234
+ transform: open ? "rotate(180deg)" : "rotate(0)",
235
+ opacity: 0.6
236
+ },
237
+ children: /* @__PURE__ */ jsxRuntime.jsx(
238
+ "path",
239
+ {
240
+ d: "M2 4 L5 7 L8 4",
241
+ stroke: "currentColor",
242
+ strokeWidth: "1.5",
243
+ fill: "none",
244
+ strokeLinecap: "round"
245
+ }
246
+ )
247
+ }
248
+ )
249
+ ]
250
+ }
251
+ ),
252
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
253
+ "div",
254
+ {
255
+ role: "menu",
256
+ "aria-label": "Account menu",
257
+ className: popoverClassName,
258
+ "data-oc-account-chip-popover": "",
259
+ style: popoverClassName ? { position: "absolute", zIndex: 50, top: "calc(100% + 6px)", right: 0 } : {
260
+ position: "absolute",
261
+ zIndex: 50,
262
+ top: "calc(100% + 6px)",
263
+ right: 0,
264
+ minWidth: 240,
265
+ background: "var(--popover, #0a0a0a)",
266
+ color: "var(--popover-foreground, #fafafa)",
267
+ border: "1px solid var(--border, #27272a)",
268
+ boxShadow: "0 10px 32px -4px rgba(0,0,0,0.35)",
269
+ fontFamily: "ui-monospace, SFMono-Regular, monospace"
270
+ },
271
+ children: [
272
+ /* @__PURE__ */ jsxRuntime.jsxs(
273
+ "div",
274
+ {
275
+ "data-oc-account-chip-header": "",
276
+ style: {
277
+ padding: "0.75rem 0.75rem 0.625rem",
278
+ borderBottom: "1px solid var(--border, #27272a)"
279
+ },
280
+ children: [
281
+ /* @__PURE__ */ jsxRuntime.jsx(
282
+ "div",
283
+ {
284
+ "data-oc-account-chip-label": "",
285
+ style: {
286
+ color: "var(--primary, #f97316)",
287
+ fontSize: 10,
288
+ letterSpacing: "0.18em",
289
+ textTransform: "uppercase",
290
+ marginBottom: 4
291
+ },
292
+ children: "\xA7 signed in"
293
+ }
294
+ ),
295
+ /* @__PURE__ */ jsxRuntime.jsx(
296
+ "div",
297
+ {
298
+ "data-oc-account-chip-address": "",
299
+ style: {
300
+ color: "var(--popover-foreground, #fafafa)",
301
+ fontSize: 11,
302
+ wordBreak: "break-all",
303
+ lineHeight: 1.35
304
+ },
305
+ children: account.address
306
+ }
307
+ ),
308
+ account.displayName ? /* @__PURE__ */ jsxRuntime.jsx(
309
+ "div",
310
+ {
311
+ style: {
312
+ color: "var(--muted-foreground, #a1a1aa)",
313
+ fontSize: 10,
314
+ marginTop: 4,
315
+ letterSpacing: "0.06em"
316
+ },
317
+ children: account.displayName
318
+ }
319
+ ) : null
320
+ ]
321
+ }
322
+ ),
323
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "none", style: { padding: "0.25rem" }, children: [
324
+ dashboardUrl ? /* @__PURE__ */ jsxRuntime.jsxs(
325
+ "a",
326
+ {
327
+ role: "menuitem",
328
+ href: dashboardUrl,
329
+ onClick: () => setOpen(false),
330
+ className: menuItemClassName,
331
+ "data-oc-account-chip-item": "",
332
+ style: menuItemClassName ? void 0 : {
333
+ display: "flex",
334
+ alignItems: "center",
335
+ gap: "0.5rem",
336
+ padding: "0.5rem 0.625rem",
337
+ fontSize: 12,
338
+ color: "var(--popover-foreground, #fafafa)",
339
+ textDecoration: "none",
340
+ cursor: "pointer"
341
+ },
342
+ children: [
343
+ /* @__PURE__ */ jsxRuntime.jsx(
344
+ "span",
345
+ {
346
+ "aria-hidden": "true",
347
+ style: { color: "var(--muted-foreground, #a1a1aa)" },
348
+ children: "\u2192"
349
+ }
350
+ ),
351
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 }, children: "dashboard" }),
352
+ /* @__PURE__ */ jsxRuntime.jsx(
353
+ "span",
354
+ {
355
+ style: {
356
+ color: "var(--muted-foreground, #a1a1aa)",
357
+ fontSize: 10
358
+ },
359
+ children: "\u2197"
360
+ }
361
+ )
362
+ ]
363
+ }
364
+ ) : null,
365
+ /* @__PURE__ */ jsxRuntime.jsxs(
366
+ "button",
367
+ {
368
+ type: "button",
369
+ role: "menuitem",
370
+ onClick: () => {
371
+ setOpen(false);
372
+ void signOut();
373
+ },
374
+ className: menuItemClassName,
375
+ "data-oc-account-chip-item": "",
376
+ "data-oc-account-chip-signout": "",
377
+ style: menuItemClassName ? void 0 : {
378
+ display: "flex",
379
+ alignItems: "center",
380
+ gap: "0.5rem",
381
+ width: "100%",
382
+ padding: "0.5rem 0.625rem",
383
+ fontSize: 12,
384
+ color: "var(--popover-foreground, #fafafa)",
385
+ background: "transparent",
386
+ border: 0,
387
+ fontFamily: "inherit",
388
+ textAlign: "left",
389
+ cursor: "pointer"
390
+ },
391
+ children: [
392
+ /* @__PURE__ */ jsxRuntime.jsx(
393
+ "span",
394
+ {
395
+ "aria-hidden": "true",
396
+ style: { color: "var(--muted-foreground, #a1a1aa)" },
397
+ children: "\u2192"
398
+ }
399
+ ),
400
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 }, children: "sign out" })
401
+ ]
402
+ }
403
+ )
404
+ ] })
405
+ ]
406
+ }
407
+ )
408
+ ]
409
+ }
410
+ );
411
+ }
151
412
  function OcSignInButton({
152
413
  label = "sign in with bitcoin",
153
414
  eager = false,
@@ -219,9 +480,9 @@ function useOcAddressSuggestion(options) {
219
480
  } = options;
220
481
  const { status, account } = useOcSession();
221
482
  const sessionAddress = status === "authenticated" ? account?.address ?? null : null;
222
- const [open, setOpen] = React__namespace.useState(false);
223
- const [highlighted, setHighlighted] = React__namespace.useState(false);
224
- const blurTimer = React__namespace.useRef(null);
483
+ const [open, setOpen] = React2__namespace.useState(false);
484
+ const [highlighted, setHighlighted] = React2__namespace.useState(false);
485
+ const blurTimer = React2__namespace.useRef(null);
225
486
  const listboxId = useUniqueId("oc-addr-listbox");
226
487
  const optionId = `${listboxId}-opt`;
227
488
  const valueMatchesSession = sessionAddress != null && value.toLowerCase() === sessionAddress.toLowerCase();
@@ -233,7 +494,7 @@ function useOcAddressSuggestion(options) {
233
494
  setOpen(false);
234
495
  setHighlighted(false);
235
496
  }
236
- React__namespace.useEffect(() => {
497
+ React2__namespace.useEffect(() => {
237
498
  return () => {
238
499
  if (blurTimer.current != null) window.clearTimeout(blurTimer.current);
239
500
  };
@@ -336,7 +597,7 @@ function useOcAddressSuggestion(options) {
336
597
  ) : null;
337
598
  return { inputProps, popover };
338
599
  }
339
- var OcAddressInput = React__namespace.forwardRef(
600
+ var OcAddressInput = React2__namespace.forwardRef(
340
601
  function OcAddressInput2({
341
602
  value,
342
603
  onValueChange,
@@ -351,15 +612,15 @@ var OcAddressInput = React__namespace.forwardRef(
351
612
  }, forwardedRef) {
352
613
  const { status, account } = useOcSession();
353
614
  const sessionAddress = status === "authenticated" ? account?.address ?? null : null;
354
- const [open, setOpen] = React__namespace.useState(false);
355
- const [highlighted, setHighlighted] = React__namespace.useState(false);
356
- const innerRef = React__namespace.useRef(null);
615
+ const [open, setOpen] = React2__namespace.useState(false);
616
+ const [highlighted, setHighlighted] = React2__namespace.useState(false);
617
+ const innerRef = React2__namespace.useRef(null);
357
618
  const setRef = (node) => {
358
619
  innerRef.current = node;
359
620
  if (typeof forwardedRef === "function") forwardedRef(node);
360
621
  else if (forwardedRef) forwardedRef.current = node;
361
622
  };
362
- const blurTimer = React__namespace.useRef(null);
623
+ const blurTimer = React2__namespace.useRef(null);
363
624
  const listboxId = useUniqueId("oc-addr-listbox");
364
625
  const optionId = `${listboxId}-opt`;
365
626
  const valueMatchesSession = sessionAddress != null && value.toLowerCase() === sessionAddress.toLowerCase();
@@ -406,7 +667,7 @@ var OcAddressInput = React__namespace.forwardRef(
406
667
  }
407
668
  onKeyDown?.(e);
408
669
  }
409
- React__namespace.useEffect(() => {
670
+ React2__namespace.useEffect(() => {
410
671
  return () => {
411
672
  if (blurTimer.current != null) window.clearTimeout(blurTimer.current);
412
673
  };
@@ -501,6 +762,7 @@ var OcAddressInput = React__namespace.forwardRef(
501
762
  );
502
763
 
503
764
  exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
765
+ exports.OcAccountChip = OcAccountChip;
504
766
  exports.OcAccountPill = OcAccountPill;
505
767
  exports.OcAddressInput = OcAddressInput;
506
768
  exports.OcSessionProvider = OcSessionProvider;