cronus-ui 0.6.8 → 0.6.10

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 CHANGED
@@ -49,7 +49,7 @@ Notes that match the commander surface:
49
49
  `packages/cli/scripts/build-registry.ts` — each item carries its source, its npm
50
50
  `dependencies`, and its `registryDependencies` (other components it imports),
51
51
  derived by parsing imports.
52
- - The default registry is pinned to the CLI package version (`v0.6.8` here), not
52
+ - The default registry is pinned to the CLI package version (`v0.6.10` here), not
53
53
  mutable `main`, so a published CLI reads the registry snapshot it was released
54
54
  with. Use `-r, --registry ./registry` when testing local registry changes before
55
55
  a release tag exists.
@@ -80,7 +80,7 @@ Notes that match the commander surface:
80
80
  "lib": "lib",
81
81
  "blocks": "components/blocks"
82
82
  },
83
- "registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.8/registry"
83
+ "registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.10/registry"
84
84
  }
85
85
  ```
86
86
 
@@ -629,7 +629,7 @@ function membersActionsSource(authImport) {
629
629
  import { and, asc, eq } from "drizzle-orm";
630
630
  import { headers } from "next/headers";
631
631
  import { db } from "@/db";
632
- import { member, organization, user } from "@/db/schema";
632
+ import { invitation, member, organization, user } from "@/db/schema";
633
633
  import { auth } from ${JSON.stringify(authImport)};
634
634
 
635
635
  async function activeWorkspaceId(): Promise<string | null> {
@@ -656,9 +656,10 @@ async function activeWorkspaceId(): Promise<string | null> {
656
656
  export async function loadMembers(): Promise<{
657
657
  workspace: string;
658
658
  rows: { id: string; name: string; email: string; image: string | null; role: string }[];
659
+ pending: { id: string; email: string; role: string | null }[];
659
660
  }> {
660
661
  const orgId = await activeWorkspaceId();
661
- if (!orgId) return { workspace: "no workspace", rows: [] };
662
+ if (!orgId) return { workspace: "no workspace", rows: [], pending: [] };
662
663
  const [org] = await db.select().from(organization).where(eq(organization.id, orgId)).limit(1);
663
664
  const rows = await db
664
665
  .select({
@@ -672,7 +673,16 @@ export async function loadMembers(): Promise<{
672
673
  .innerJoin(user, eq(member.userId, user.id))
673
674
  .where(eq(member.organizationId, orgId))
674
675
  .orderBy(asc(member.createdAt));
675
- return { workspace: org?.name ?? "no workspace", rows };
676
+ const pending = await db
677
+ .select({
678
+ id: invitation.id,
679
+ email: invitation.email,
680
+ role: invitation.role,
681
+ })
682
+ .from(invitation)
683
+ .where(and(eq(invitation.organizationId, orgId), eq(invitation.status, "pending")))
684
+ .orderBy(asc(invitation.createdAt));
685
+ return { workspace: org?.name ?? "no workspace", rows, pending };
676
686
  }
677
687
  `;
678
688
  }
@@ -682,15 +692,16 @@ import { MembersView } from ${JSON.stringify(viewImport)};
682
692
 
683
693
  export async function MembersPanel() {
684
694
  const data = await loadMembers();
685
- return <MembersView workspace={data.workspace} rows={data.rows} />;
695
+ return <MembersView workspace={data.workspace} rows={data.rows} pending={data.pending} />;
686
696
  }
687
697
  `;
688
698
  }
689
699
  function membersViewSource(inviteImport) {
690
700
  return `"use client";
691
701
 
692
- import { Avatar, AvatarFallback, AvatarImage, Badge, Button } from "@cronus-ui/ui";
702
+ import { Avatar, AvatarFallback, AvatarImage, Badge, Button, CopyButton } from "@cronus-ui/ui";
693
703
  import { InviteMember } from ${JSON.stringify(inviteImport)};
704
+ import { useEffect, useState } from "react";
694
705
 
695
706
  function initialsOf(name: string, email: string): string {
696
707
  const parts = name.trim().split(/\\s+/).filter(Boolean);
@@ -714,13 +725,23 @@ function roleVariant(role: string): "primary" | "info" | "secondary" {
714
725
  return "secondary";
715
726
  }
716
727
 
728
+ function inviteHref(origin: string, id: string): string {
729
+ return \`\${origin}/accept-invitation?id=\${encodeURIComponent(id)}\`;
730
+ }
731
+
717
732
  export function MembersView({
718
733
  workspace,
719
734
  rows,
735
+ pending,
720
736
  }: {
721
737
  workspace: string;
722
738
  rows: { id: string; name: string; email: string; image: string | null; role: string }[];
739
+ pending: { id: string; email: string; role: string | null }[];
723
740
  }) {
741
+ const [origin, setOrigin] = useState("");
742
+ useEffect(() => {
743
+ setOrigin(window.location.origin);
744
+ }, []);
724
745
  const count = String(rows.length);
725
746
  return (
726
747
  <section
@@ -768,6 +789,33 @@ export function MembersView({
768
789
  ))}
769
790
  </ul>
770
791
  )}
792
+ {pending.length > 0 ? (
793
+ <>
794
+ <h2 className="mt-6 text-sm font-semibold text-fg">Pending</h2>
795
+ <ul>
796
+ {pending.map((row) => (
797
+ <li
798
+ key={row.id}
799
+ data-slot="pending-invite"
800
+ className="flex items-center gap-3 border-t border-border py-3"
801
+ >
802
+ <div className="flex min-w-0 flex-1 flex-col">
803
+ <span className="truncate text-sm text-fg">{row.email}</span>
804
+ <span className="truncate text-sm text-fg-tertiary">
805
+ {roleLabel(row.role ?? "member")}
806
+ </span>
807
+ </div>
808
+ <CopyButton
809
+ value={inviteHref(origin, row.id)}
810
+ copyLabel="Copy invite link"
811
+ variant="outline"
812
+ size="icon"
813
+ />
814
+ </li>
815
+ ))}
816
+ </ul>
817
+ </>
818
+ ) : null}
771
819
  </section>
772
820
  );
773
821
  }
@@ -811,20 +859,33 @@ function inviteMemberSource(authClientImport) {
811
859
  return `"use client";
812
860
 
813
861
  import { InviteDialog } from "@cronus-ui/ui";
814
- import type { ReactNode } from "react";
862
+ import { useRouter } from "next/navigation";
863
+ import { type ReactNode, useRef } from "react";
815
864
  import { authClient } from ${JSON.stringify(authClientImport)};
816
865
 
817
866
  export function InviteMember({ trigger }: { trigger: ReactNode }) {
867
+ const router = useRouter();
868
+ const sent = useRef(false);
818
869
  return (
819
870
  <InviteDialog
820
871
  trigger={trigger}
872
+ onOpenChange={(open) => {
873
+ if (!open && sent.current) {
874
+ sent.current = false;
875
+ router.refresh();
876
+ }
877
+ }}
821
878
  onInvite={async ({ email, role }) => {
822
879
  const assigned = role === "admin" || role === "owner" ? role : "member";
823
- const { error } = await authClient.organization.inviteMember({
880
+ const { data, error } = await authClient.organization.inviteMember({
824
881
  email,
825
882
  role: assigned,
826
883
  });
827
884
  if (error) throw new Error(error.message || "Invite failed");
885
+ const id = data?.id ? String(data.id) : "";
886
+ if (!id) return;
887
+ sent.current = true;
888
+ return { url: \`\${window.location.origin}/accept-invitation?id=\${encodeURIComponent(id)}\` };
828
889
  }}
829
890
  />
830
891
  );
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare const CONFIG_FILE = "cronus-ui.json";
2
- export declare const CLI_VERSION = "0.6.8";
3
- export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.8/registry";
2
+ export declare const CLI_VERSION = "0.6.10";
3
+ export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.10/registry";
4
4
  /** Manifest entry `add`/`upgrade` record per installed registry item. */
5
5
  export interface InstalledRecord {
6
6
  /** Registry release the files came from (git tag without the leading "v"). */
package/dist/config.js CHANGED
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
2
2
  import { readFile, writeFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  export const CONFIG_FILE = "cronus-ui.json";
5
- export const CLI_VERSION = "0.6.8";
5
+ export const CLI_VERSION = "0.6.10";
6
6
  export const DEFAULT_REGISTRY = `https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v${CLI_VERSION}/registry`;
7
7
  export const DEFAULT_CONFIG = {
8
8
  aliases: { ui: "@/components/ui", lib: "@/lib", blocks: "@/components/blocks" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cronus-ui",
3
- "version": "0.6.8",
3
+ "version": "0.6.10",
4
4
  "description": "cronus-ui — add Cronus UI components to your project, shadcn-style (copy-paste registry).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "registry:check": "bun run scripts/check-registry.ts"
55
55
  },
56
56
  "dependencies": {
57
- "@cronus-ui/ai-kit": "0.6.8",
57
+ "@cronus-ui/ai-kit": "0.6.10",
58
58
  "commander": "^15.0.0",
59
59
  "picocolors": "^1.1.1"
60
60
  },
@@ -4,7 +4,7 @@
4
4
  "planVersion": 1,
5
5
  "manifest": {
6
6
  "title": "Admin",
7
- "description": "An admin console: split login, an (app) shell, overview, users, analytics, a sprint board and an audit trail — composed from validated blocks.",
7
+ "description": "An admin console: split login/signup, password reset, an (app) shell, overview, users, analytics, a sprint board and an audit trail — composed from validated blocks.",
8
8
  "chrome": {
9
9
  "shell": { "block": "app-shell-chrome" },
10
10
  "bare": {}
@@ -16,11 +16,17 @@
16
16
  "chrome": "bare",
17
17
  "blocks": [{ "block": "login", "variant": "split" }]
18
18
  },
19
+ {
20
+ "route": "/signup",
21
+ "title": "Create account",
22
+ "chrome": "bare",
23
+ "blocks": [{ "block": "signup", "variant": "split" }]
24
+ },
19
25
  {
20
26
  "route": "/forgot-password",
21
27
  "title": "Reset password",
22
28
  "chrome": "bare",
23
- "blocks": ["forgot-password"]
29
+ "blocks": [{ "block": "forgot-password", "variant": "split" }]
24
30
  },
25
31
  {
26
32
  "route": "/reset-password",
@@ -26,7 +26,7 @@
26
26
  "route": "/forgot-password",
27
27
  "title": "Reset password",
28
28
  "chrome": "bare",
29
- "blocks": ["forgot-password"]
29
+ "blocks": [{ "block": "forgot-password", "variant": "split" }]
30
30
  },
31
31
  {
32
32
  "route": "/reset-password",