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 +2 -2
- package/dist/compose/gold-path.js +68 -7
- package/dist/config.d.ts +2 -2
- package/dist/config.js +1 -1
- package/package.json +2 -2
- package/templates/apps/admin.json +8 -2
- package/templates/apps/saas.json +1 -1
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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.
|
|
3
|
-
export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.
|
|
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.
|
|
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.
|
|
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.
|
|
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",
|
package/templates/apps/saas.json
CHANGED