@camstack/ui-library 1.2.339 → 1.2.341

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/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.341] - 2026-10-28
11
+
12
+ ### Changed
13
+
14
+ - Account sign-in fields follow the vendor-login path of the hub login proxy
15
+
16
+ ## [1.2.340] - 2026-10-27
17
+
18
+ ### Changed
19
+
20
+ - The account sign-in form waits for the hub to finish the sign-in on its own and keeps the paste box as a fallback.
21
+
10
22
  ## [1.2.339] - 2026-10-27
11
23
 
12
24
  ### Added
package/dist/index.cjs CHANGED
@@ -14514,6 +14514,7 @@ Button.displayName = "Button";
14514
14514
  //#endregion
14515
14515
  //#region src/composites/account-sign-in-field.tsx
14516
14516
  var INPUT_CLASS$1 = "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed";
14517
+ var CLAIM_POLL_MS = 2e3;
14517
14518
  var BARE_CODE = /^[A-Za-z0-9._~-]{8,}$/;
14518
14519
  function isRecord$4(value) {
14519
14520
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -14557,6 +14558,10 @@ function choicesOf(value) {
14557
14558
  function selectedChoice(value) {
14558
14559
  return typeof value === "string" ? value : "";
14559
14560
  }
14561
+ /** A hub-relative path (the proxied login) opens on the hub's own origin. */
14562
+ function openableUrl(url) {
14563
+ return url.startsWith("/") && !url.startsWith("//") ? new URL(url, window.location.origin).toString() : url;
14564
+ }
14560
14565
  function shouldComplete(text) {
14561
14566
  const trimmed = text.trim();
14562
14567
  if (trimmed.length === 0) return false;
@@ -14595,6 +14600,33 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14595
14600
  setAttemptId(null);
14596
14601
  setAuthorizeUrl(null);
14597
14602
  };
14603
+ const claimAction = field.claimAction;
14604
+ (0, react$1.useEffect)(() => {
14605
+ if (claimAction === void 0 || attemptId === null || phase !== "pasting" || !onAction) return;
14606
+ let stopped = false;
14607
+ const timer = setInterval(() => {
14608
+ if (inFlight.current) return;
14609
+ onAction(claimAction, field.key, { attemptId }).then((result) => {
14610
+ if (stopped || !isRecord$4(result) || result["pending"] === true) return;
14611
+ stopped = true;
14612
+ applyResult(result);
14613
+ }).catch((err) => {
14614
+ if (stopped) return;
14615
+ stopped = true;
14616
+ setError(err instanceof Error ? err.message : String(err));
14617
+ });
14618
+ }, CLAIM_POLL_MS);
14619
+ return () => {
14620
+ stopped = true;
14621
+ clearInterval(timer);
14622
+ };
14623
+ }, [
14624
+ claimAction,
14625
+ attemptId,
14626
+ phase,
14627
+ onAction,
14628
+ field.key
14629
+ ]);
14598
14630
  const begin = async () => {
14599
14631
  if (!onAction || working) return;
14600
14632
  setWorking(true);
@@ -14612,7 +14644,7 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14612
14644
  setAttemptId(result["attemptId"]);
14613
14645
  setAuthorizeUrl(result["authorizeUrl"]);
14614
14646
  setPhase("pasting");
14615
- window.open(result["authorizeUrl"], "_blank", "noopener,noreferrer");
14647
+ window.open(openableUrl(result["authorizeUrl"]), "_blank", "noopener,noreferrer");
14616
14648
  } catch (err) {
14617
14649
  setError(err instanceof Error ? err.message : String(err));
14618
14650
  } finally {
@@ -14725,24 +14757,31 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14725
14757
  }),
14726
14758
  showPaste && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14727
14759
  className: "flex flex-col gap-1.5",
14728
- children: [authorizeUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
14729
- className: "text-[11px] text-primary break-all",
14730
- href: authorizeUrl,
14731
- target: "_blank",
14732
- rel: "noopener noreferrer",
14733
- children: t("uiLibrary.accountSignIn.open", "Open the sign-in page")
14734
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
14735
- className: `${INPUT_CLASS$1} min-h-[60px] resize-y`,
14736
- "aria-label": t("uiLibrary.accountSignIn.paste", "Redirect address or code"),
14737
- placeholder: field.pastePlaceholder,
14738
- value: paste,
14739
- disabled: disabled || working,
14740
- onChange: (event) => {
14741
- const next = event.target.value;
14742
- setPaste(next);
14743
- if (shouldComplete(next)) complete(next);
14744
- }
14745
- })]
14760
+ children: [
14761
+ authorizeUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
14762
+ className: "text-[11px] text-primary break-all",
14763
+ href: authorizeUrl,
14764
+ target: "_blank",
14765
+ rel: "noopener noreferrer",
14766
+ children: t("uiLibrary.accountSignIn.open", "Open the sign-in page")
14767
+ }),
14768
+ claimAction !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14769
+ className: "text-[11px] text-muted-foreground",
14770
+ children: t("uiLibrary.accountSignIn.pasteFallback", "If the page does not finish, paste the address it stops on here.")
14771
+ }),
14772
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
14773
+ className: `${INPUT_CLASS$1} min-h-[60px] resize-y`,
14774
+ "aria-label": t("uiLibrary.accountSignIn.paste", "Redirect address or code"),
14775
+ placeholder: field.pastePlaceholder,
14776
+ value: paste,
14777
+ disabled: disabled || working,
14778
+ onChange: (event) => {
14779
+ const next = event.target.value;
14780
+ setPaste(next);
14781
+ if (shouldComplete(next)) complete(next);
14782
+ }
14783
+ })
14784
+ ]
14746
14785
  }),
14747
14786
  error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14748
14787
  className: "text-[11px] text-danger",
package/dist/index.js CHANGED
@@ -14490,6 +14490,7 @@ Button.displayName = "Button";
14490
14490
  //#endregion
14491
14491
  //#region src/composites/account-sign-in-field.tsx
14492
14492
  var INPUT_CLASS$1 = "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed";
14493
+ var CLAIM_POLL_MS = 2e3;
14493
14494
  var BARE_CODE = /^[A-Za-z0-9._~-]{8,}$/;
14494
14495
  function isRecord$4(value) {
14495
14496
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -14533,6 +14534,10 @@ function choicesOf(value) {
14533
14534
  function selectedChoice(value) {
14534
14535
  return typeof value === "string" ? value : "";
14535
14536
  }
14537
+ /** A hub-relative path (the proxied login) opens on the hub's own origin. */
14538
+ function openableUrl(url) {
14539
+ return url.startsWith("/") && !url.startsWith("//") ? new URL(url, window.location.origin).toString() : url;
14540
+ }
14536
14541
  function shouldComplete(text) {
14537
14542
  const trimmed = text.trim();
14538
14543
  if (trimmed.length === 0) return false;
@@ -14571,6 +14576,33 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14571
14576
  setAttemptId(null);
14572
14577
  setAuthorizeUrl(null);
14573
14578
  };
14579
+ const claimAction = field.claimAction;
14580
+ useEffect(() => {
14581
+ if (claimAction === void 0 || attemptId === null || phase !== "pasting" || !onAction) return;
14582
+ let stopped = false;
14583
+ const timer = setInterval(() => {
14584
+ if (inFlight.current) return;
14585
+ onAction(claimAction, field.key, { attemptId }).then((result) => {
14586
+ if (stopped || !isRecord$4(result) || result["pending"] === true) return;
14587
+ stopped = true;
14588
+ applyResult(result);
14589
+ }).catch((err) => {
14590
+ if (stopped) return;
14591
+ stopped = true;
14592
+ setError(err instanceof Error ? err.message : String(err));
14593
+ });
14594
+ }, CLAIM_POLL_MS);
14595
+ return () => {
14596
+ stopped = true;
14597
+ clearInterval(timer);
14598
+ };
14599
+ }, [
14600
+ claimAction,
14601
+ attemptId,
14602
+ phase,
14603
+ onAction,
14604
+ field.key
14605
+ ]);
14574
14606
  const begin = async () => {
14575
14607
  if (!onAction || working) return;
14576
14608
  setWorking(true);
@@ -14588,7 +14620,7 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14588
14620
  setAttemptId(result["attemptId"]);
14589
14621
  setAuthorizeUrl(result["authorizeUrl"]);
14590
14622
  setPhase("pasting");
14591
- window.open(result["authorizeUrl"], "_blank", "noopener,noreferrer");
14623
+ window.open(openableUrl(result["authorizeUrl"]), "_blank", "noopener,noreferrer");
14592
14624
  } catch (err) {
14593
14625
  setError(err instanceof Error ? err.message : String(err));
14594
14626
  } finally {
@@ -14701,24 +14733,31 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
14701
14733
  }),
14702
14734
  showPaste && /* @__PURE__ */ jsxs("div", {
14703
14735
  className: "flex flex-col gap-1.5",
14704
- children: [authorizeUrl !== null && /* @__PURE__ */ jsx("a", {
14705
- className: "text-[11px] text-primary break-all",
14706
- href: authorizeUrl,
14707
- target: "_blank",
14708
- rel: "noopener noreferrer",
14709
- children: t("uiLibrary.accountSignIn.open", "Open the sign-in page")
14710
- }), /* @__PURE__ */ jsx("textarea", {
14711
- className: `${INPUT_CLASS$1} min-h-[60px] resize-y`,
14712
- "aria-label": t("uiLibrary.accountSignIn.paste", "Redirect address or code"),
14713
- placeholder: field.pastePlaceholder,
14714
- value: paste,
14715
- disabled: disabled || working,
14716
- onChange: (event) => {
14717
- const next = event.target.value;
14718
- setPaste(next);
14719
- if (shouldComplete(next)) complete(next);
14720
- }
14721
- })]
14736
+ children: [
14737
+ authorizeUrl !== null && /* @__PURE__ */ jsx("a", {
14738
+ className: "text-[11px] text-primary break-all",
14739
+ href: authorizeUrl,
14740
+ target: "_blank",
14741
+ rel: "noopener noreferrer",
14742
+ children: t("uiLibrary.accountSignIn.open", "Open the sign-in page")
14743
+ }),
14744
+ claimAction !== void 0 && /* @__PURE__ */ jsx("p", {
14745
+ className: "text-[11px] text-muted-foreground",
14746
+ children: t("uiLibrary.accountSignIn.pasteFallback", "If the page does not finish, paste the address it stops on here.")
14747
+ }),
14748
+ /* @__PURE__ */ jsx("textarea", {
14749
+ className: `${INPUT_CLASS$1} min-h-[60px] resize-y`,
14750
+ "aria-label": t("uiLibrary.accountSignIn.paste", "Redirect address or code"),
14751
+ placeholder: field.pastePlaceholder,
14752
+ value: paste,
14753
+ disabled: disabled || working,
14754
+ onChange: (event) => {
14755
+ const next = event.target.value;
14756
+ setPaste(next);
14757
+ if (shouldComplete(next)) complete(next);
14758
+ }
14759
+ })
14760
+ ]
14722
14761
  }),
14723
14762
  error !== null && /* @__PURE__ */ jsx("p", {
14724
14763
  className: "text-[11px] text-danger",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.2.339",
3
+ "version": "1.2.341",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/camstack/server.git",