@shipfox/client-workspace-settings 17.0.0 → 22.0.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +34 -0
- package/dist/components/members/workspace-members-section.d.ts.map +1 -1
- package/dist/components/members/workspace-members-section.js +90 -73
- package/dist/components/members/workspace-members-section.js.map +1 -1
- package/dist/routes/general.d.ts +3 -0
- package/dist/routes/general.js +3 -0
- package/dist/routes/general.js.map +1 -1
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/members.d.ts +3 -0
- package/dist/routes/members.js +3 -0
- package/dist/routes/members.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/components/members/workspace-members-section.tsx +68 -51
- package/src/routes/general.tsx +4 -1
- package/src/routes/index.tsx +1 -0
- package/src/routes/members.tsx +4 -1
- package/tsconfig.build.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
$ shipfox-swc
|
|
2
|
-
Successfully compiled: 19 files with swc (
|
|
2
|
+
Successfully compiled: 19 files with swc (249.21ms)
|
package/.turbo/turbo-type.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @shipfox/client-workspace-settings
|
|
2
2
|
|
|
3
|
+
## 22.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7693eb3: Render empty and load-error states inside bordered panel bodies and keep loading placeholders aligned with their data regions.
|
|
8
|
+
- Updated dependencies [50b3867]
|
|
9
|
+
- Updated dependencies [00c1cb8]
|
|
10
|
+
- Updated dependencies [7693eb3]
|
|
11
|
+
- Updated dependencies [00c1cb8]
|
|
12
|
+
- Updated dependencies [56f4526]
|
|
13
|
+
- @shipfox/client-auth@22.0.0
|
|
14
|
+
- @shipfox/client-shell@22.0.0
|
|
15
|
+
- @shipfox/react-ui@2.1.0
|
|
16
|
+
- @shipfox/client-ui@22.0.0
|
|
17
|
+
|
|
18
|
+
## 21.0.0
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [0f4abe4]
|
|
23
|
+
- Updated dependencies [71d0c44]
|
|
24
|
+
- Updated dependencies [9c21429]
|
|
25
|
+
- Updated dependencies [30beb8f]
|
|
26
|
+
- Updated dependencies [16733a7]
|
|
27
|
+
- Updated dependencies [163c40a]
|
|
28
|
+
- Updated dependencies [c4376a1]
|
|
29
|
+
- Updated dependencies [6703982]
|
|
30
|
+
- Updated dependencies [f1d127e]
|
|
31
|
+
- Updated dependencies [0e860d7]
|
|
32
|
+
- @shipfox/react-ui@2.0.0
|
|
33
|
+
- @shipfox/client-shell@21.0.0
|
|
34
|
+
- @shipfox/client-auth@21.0.0
|
|
35
|
+
- @shipfox/client-ui@21.0.0
|
|
36
|
+
|
|
3
37
|
## 17.0.0
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-members-section.d.ts","sourceRoot":"","sources":["../../../src/components/members/workspace-members-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace-members-section.d.ts","sourceRoot":"","sources":["../../../src/components/members/workspace-members-section.tsx"],"names":[],"mappings":"AA+CA,wBAAgB,+BAA+B,CAAC,EAC9C,WAAW,EACX,aAAa,GACd,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB,+BAOA"}
|
|
@@ -9,6 +9,7 @@ import { EmptyState } from '@shipfox/react-ui/empty-state';
|
|
|
9
9
|
import { FormField, FormFieldInput, fieldError } from '@shipfox/react-ui/form-field';
|
|
10
10
|
import { Icon } from '@shipfox/react-ui/icon';
|
|
11
11
|
import { Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalTitle, ModalTrigger } from '@shipfox/react-ui/modal';
|
|
12
|
+
import { Panel } from '@shipfox/react-ui/panel';
|
|
12
13
|
import { Skeleton } from '@shipfox/react-ui/skeleton';
|
|
13
14
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@shipfox/react-ui/table';
|
|
14
15
|
import { toast } from '@shipfox/react-ui/toast';
|
|
@@ -61,43 +62,49 @@ function MembersSection({ workspaceId, workspaceName }) {
|
|
|
61
62
|
}),
|
|
62
63
|
query.isPending ? /*#__PURE__*/ _jsx(TableSkeleton, {
|
|
63
64
|
rows: 3,
|
|
64
|
-
cols: 3
|
|
65
|
+
cols: 3,
|
|
66
|
+
label: "Loading members"
|
|
65
67
|
}) : null,
|
|
66
|
-
query.isError && query.data === undefined ? /*#__PURE__*/ _jsx(
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
query.isError && query.data === undefined ? /*#__PURE__*/ _jsx(Panel, {
|
|
69
|
+
children: /*#__PURE__*/ _jsx(QueryLoadError, {
|
|
70
|
+
query: query,
|
|
71
|
+
subject: "members",
|
|
72
|
+
variant: "panel"
|
|
73
|
+
})
|
|
69
74
|
}) : null,
|
|
70
|
-
members.length > 0 ? /*#__PURE__*/
|
|
71
|
-
children:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
children:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
75
|
+
members.length > 0 ? /*#__PURE__*/ _jsx(Panel, {
|
|
76
|
+
children: /*#__PURE__*/ _jsxs(Table, {
|
|
77
|
+
children: [
|
|
78
|
+
/*#__PURE__*/ _jsx(TableHeader, {
|
|
79
|
+
children: /*#__PURE__*/ _jsxs(TableRow, {
|
|
80
|
+
children: [
|
|
81
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
82
|
+
children: "Name"
|
|
83
|
+
}),
|
|
84
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
85
|
+
children: "Email"
|
|
86
|
+
}),
|
|
87
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
88
|
+
children: "Joined"
|
|
89
|
+
}),
|
|
90
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
91
|
+
className: "w-80 text-right",
|
|
92
|
+
children: "Actions"
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
}),
|
|
97
|
+
/*#__PURE__*/ _jsx(TableBody, {
|
|
98
|
+
children: members.map((member)=>/*#__PURE__*/ _jsx(MemberRow, {
|
|
99
|
+
member: member,
|
|
100
|
+
members: members,
|
|
101
|
+
currentUserId: auth.user?.id,
|
|
102
|
+
workspaceId: workspaceId,
|
|
103
|
+
workspaceName: workspaceName
|
|
104
|
+
}, member.id))
|
|
89
105
|
})
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
children: members.map((member)=>/*#__PURE__*/ _jsx(MemberRow, {
|
|
93
|
-
member: member,
|
|
94
|
-
members: members,
|
|
95
|
-
currentUserId: auth.user?.id,
|
|
96
|
-
workspaceId: workspaceId,
|
|
97
|
-
workspaceName: workspaceName
|
|
98
|
-
}, member.id))
|
|
99
|
-
})
|
|
100
|
-
]
|
|
106
|
+
]
|
|
107
|
+
})
|
|
101
108
|
}) : null
|
|
102
109
|
]
|
|
103
110
|
});
|
|
@@ -239,41 +246,49 @@ function PendingInvitationsSection({ workspaceId, workspaceName }) {
|
|
|
239
246
|
}),
|
|
240
247
|
query.isPending ? /*#__PURE__*/ _jsx(TableSkeleton, {
|
|
241
248
|
rows: 2,
|
|
242
|
-
cols: 3
|
|
249
|
+
cols: 3,
|
|
250
|
+
label: "Loading invitations"
|
|
243
251
|
}) : null,
|
|
244
|
-
query.isError && query.data === undefined ? /*#__PURE__*/ _jsx(
|
|
245
|
-
|
|
246
|
-
|
|
252
|
+
query.isError && query.data === undefined ? /*#__PURE__*/ _jsx(Panel, {
|
|
253
|
+
children: /*#__PURE__*/ _jsx(QueryLoadError, {
|
|
254
|
+
query: query,
|
|
255
|
+
subject: "invitations",
|
|
256
|
+
variant: "panel"
|
|
257
|
+
})
|
|
247
258
|
}) : null,
|
|
248
|
-
query.data !== undefined && invitations.length === 0 ? /*#__PURE__*/ _jsx(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
259
|
+
query.data !== undefined && invitations.length === 0 ? /*#__PURE__*/ _jsx(Panel, {
|
|
260
|
+
children: /*#__PURE__*/ _jsx(EmptyInvitations, {})
|
|
261
|
+
}) : null,
|
|
262
|
+
invitations.length > 0 ? /*#__PURE__*/ _jsx(Panel, {
|
|
263
|
+
children: /*#__PURE__*/ _jsxs(Table, {
|
|
264
|
+
children: [
|
|
265
|
+
/*#__PURE__*/ _jsx(TableHeader, {
|
|
266
|
+
children: /*#__PURE__*/ _jsxs(TableRow, {
|
|
267
|
+
children: [
|
|
268
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
269
|
+
children: "Email"
|
|
270
|
+
}),
|
|
271
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
272
|
+
children: "Invited by"
|
|
273
|
+
}),
|
|
274
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
275
|
+
children: "Expires"
|
|
276
|
+
}),
|
|
277
|
+
/*#__PURE__*/ _jsx(TableHead, {
|
|
278
|
+
className: "w-80 text-right",
|
|
279
|
+
children: "Actions"
|
|
280
|
+
})
|
|
281
|
+
]
|
|
282
|
+
})
|
|
283
|
+
}),
|
|
284
|
+
/*#__PURE__*/ _jsx(TableBody, {
|
|
285
|
+
children: invitations.map((invitation)=>/*#__PURE__*/ _jsx(InvitationRow, {
|
|
286
|
+
invitation: invitation,
|
|
287
|
+
workspaceId: workspaceId
|
|
288
|
+
}, invitation.id))
|
|
268
289
|
})
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
children: invitations.map((invitation)=>/*#__PURE__*/ _jsx(InvitationRow, {
|
|
272
|
-
invitation: invitation,
|
|
273
|
-
workspaceId: workspaceId
|
|
274
|
-
}, invitation.id))
|
|
275
|
-
})
|
|
276
|
-
]
|
|
290
|
+
]
|
|
291
|
+
})
|
|
277
292
|
}) : null
|
|
278
293
|
]
|
|
279
294
|
});
|
|
@@ -520,17 +535,19 @@ function EmptyInvitations() {
|
|
|
520
535
|
return /*#__PURE__*/ _jsx(EmptyState, {
|
|
521
536
|
icon: "mailLine",
|
|
522
537
|
title: "No pending invitations.",
|
|
523
|
-
description: "Invite someone above to grow your workspace."
|
|
538
|
+
description: "Invite someone above to grow your workspace.",
|
|
539
|
+
variant: "panel"
|
|
524
540
|
});
|
|
525
541
|
}
|
|
526
|
-
function TableSkeleton({ rows, cols }) {
|
|
527
|
-
return /*#__PURE__*/ _jsx(
|
|
528
|
-
|
|
542
|
+
function TableSkeleton({ rows, cols, label }) {
|
|
543
|
+
return /*#__PURE__*/ _jsx(Panel, {
|
|
544
|
+
role: "status",
|
|
545
|
+
"aria-label": label,
|
|
546
|
+
className: "divide-y",
|
|
529
547
|
children: Array.from({
|
|
530
548
|
length: rows
|
|
531
|
-
}).map((_, rowIdx)
|
|
532
|
-
|
|
533
|
-
className: "grid grid-cols-3 gap-group",
|
|
549
|
+
}).map((_, rowIdx)=>/*#__PURE__*/ _jsx("div", {
|
|
550
|
+
className: "grid min-h-44 grid-cols-3 gap-group px-row py-row",
|
|
534
551
|
children: Array.from({
|
|
535
552
|
length: cols
|
|
536
553
|
}).map((__, colIdx)=>// biome-ignore lint/suspicious/noArrayIndexKey: stable placeholder cells
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/members/workspace-members-section.tsx"],"sourcesContent":["import {createInvitationBodySchema} from '@shipfox/api-workspaces-dto';\nimport {useAuthState} from '@shipfox/client-auth';\nimport {QueryLoadError} from '@shipfox/client-ui';\nimport {Badge} from '@shipfox/react-ui/badge';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n ModalTrigger,\n} from '@shipfox/react-ui/modal';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@shipfox/react-ui/table';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Header, Text} from '@shipfox/react-ui/typography';\nimport {formatDate} from '@shipfox/react-ui/utils';\nimport {useForm} from '@tanstack/react-form';\nimport {useState} from 'react';\nimport {\n getInvitationExpiry,\n getMemberRemovalRestriction,\n memberCount,\n type PendingInvitation,\n type WorkspaceMember,\n} from '#core/membership.js';\nimport {useCreateInvitation} from '#hooks/api/create-invitation.js';\nimport {useListInvitations} from '#hooks/api/list-invitations.js';\nimport {useListMembers} from '#hooks/api/list-members.js';\nimport {useRemoveMember} from '#hooks/api/remove-member.js';\nimport {useRevokeInvitation} from '#hooks/api/revoke-invitation.js';\nimport {invitationErrorToFormError, memberRemovalErrorMessage} from './form-errors.js';\n\nexport function WorkspaceMembersSettingsSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n return (\n <div className=\"flex min-w-0 flex-col gap-region\">\n <MembersSection workspaceId={workspaceId} workspaceName={workspaceName} />\n <PendingInvitationsSection workspaceId={workspaceId} workspaceName={workspaceName} />\n </div>\n );\n}\n\nfunction MembersSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n const auth = useAuthState();\n const query = useListMembers(workspaceId);\n const members = query.data ?? [];\n\n return (\n <section className=\"flex flex-col gap-group\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Members</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {query.isPending\n ? 'Loading members…'\n : `${memberCount(members)} ${memberCount(members) === 1 ? 'member' : 'members'}`}\n </Text>\n </div>\n\n {query.isPending ? <TableSkeleton rows={3} cols={3} /> : null}\n\n {query.isError && query.data === undefined ? (\n <QueryLoadError query={query} subject=\"members\" />\n ) : null}\n\n {members.length > 0 ? (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Email</TableHead>\n <TableHead>Joined</TableHead>\n <TableHead className=\"w-80 text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {members.map((member) => (\n <MemberRow\n key={member.id}\n member={member}\n members={members}\n currentUserId={auth.user?.id}\n workspaceId={workspaceId}\n workspaceName={workspaceName}\n />\n ))}\n </TableBody>\n </Table>\n ) : null}\n </section>\n );\n}\n\nfunction MemberRow({\n member,\n members,\n currentUserId,\n workspaceId,\n workspaceName,\n}: {\n member: WorkspaceMember;\n members: readonly WorkspaceMember[];\n currentUserId: string | undefined;\n workspaceId: string;\n workspaceName: string;\n}) {\n const [open, setOpen] = useState(false);\n const remove = useRemoveMember(workspaceId);\n const restriction = getMemberRemovalRestriction({member, members, currentUserId});\n\n async function handleRemove() {\n try {\n await remove.mutateAsync({userId: member.userId});\n toast.success(`Removed ${member.email} from ${workspaceName}.`);\n setOpen(false);\n } catch (error) {\n toast.error(memberRemovalErrorMessage(error));\n }\n }\n\n return (\n <TableRow className={remove.isPending ? 'opacity-60' : undefined}>\n <TableCell className=\"font-medium\">{member.name ?? 'N/A'}</TableCell>\n <TableCell>\n <Code variant=\"paragraph\">{member.email}</Code>\n </TableCell>\n <TableCell>{formatDate(member.joinedAt)}</TableCell>\n <TableCell className=\"text-right\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button\n size=\"sm\"\n variant=\"transparentMuted\"\n aria-label=\"Remove member\"\n disabled={restriction !== undefined}\n isLoading={remove.isPending}\n className={\n remove.isPending\n ? 'opacity-100 transition-opacity'\n : 'opacity-0 transition-opacity group-hover/row:opacity-100 focus-visible:opacity-100'\n }\n >\n <Icon name=\"userUnfollowLine\" className=\"size-16\" />\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Remove member</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">\n Remove {member.name ?? member.email} from {workspaceName}?\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\">\n They will lose access immediately. They can be re-invited later.\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"danger\" onClick={handleRemove} isLoading={remove.isPending}>\n Remove\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </TableCell>\n </TableRow>\n );\n}\n\nfunction PendingInvitationsSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n const query = useListInvitations(workspaceId);\n const invitations = query.data ?? [];\n const [inviteOpen, setInviteOpen] = useState(false);\n\n return (\n <section className=\"flex flex-col gap-group\">\n <div className=\"flex items-center justify-between gap-group\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Pending invitations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {query.isPending\n ? 'Loading invitations…'\n : `${invitations.length} ${invitations.length === 1 ? 'invitation' : 'invitations'}`}\n </Text>\n </div>\n <InviteMemberModal\n open={inviteOpen}\n onOpenChange={setInviteOpen}\n workspaceId={workspaceId}\n workspaceName={workspaceName}\n />\n </div>\n\n {query.isPending ? <TableSkeleton rows={2} cols={3} /> : null}\n\n {query.isError && query.data === undefined ? (\n <QueryLoadError query={query} subject=\"invitations\" />\n ) : null}\n\n {query.data !== undefined && invitations.length === 0 ? <EmptyInvitations /> : null}\n\n {invitations.length > 0 ? (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Email</TableHead>\n <TableHead>Invited by</TableHead>\n <TableHead>Expires</TableHead>\n <TableHead className=\"w-80 text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invitations.map((invitation) => (\n <InvitationRow\n key={invitation.id}\n invitation={invitation}\n workspaceId={workspaceId}\n />\n ))}\n </TableBody>\n </Table>\n ) : null}\n </section>\n );\n}\n\nfunction InvitationRow({\n invitation,\n workspaceId,\n}: {\n invitation: PendingInvitation;\n workspaceId: string;\n}) {\n const [open, setOpen] = useState(false);\n const revoke = useRevokeInvitation(workspaceId);\n const expiry = getInvitationExpiry(invitation);\n\n async function handleRevoke() {\n try {\n await revoke.mutateAsync({invitationId: invitation.id});\n toast.success(`Invitation to ${invitation.email} revoked.`);\n setOpen(false);\n } catch {\n toast.error('Could not revoke invitation.');\n }\n }\n\n return (\n <TableRow className={revoke.isPending ? 'opacity-60' : undefined}>\n <TableCell>\n <Code variant=\"paragraph\">{invitation.email}</Code>\n </TableCell>\n <TableCell>{invitation.invitedByDisplay ?? 'N/A'}</TableCell>\n <TableCell>\n <div className=\"flex items-center gap-inline\">\n <Text size=\"sm\">{formatDate(invitation.expiresAt)}</Text>\n {expiry === 'expires-soon' ? <Badge variant=\"warning\">Soon</Badge> : null}\n {expiry === 'expired' ? <Badge variant=\"error\">Expired</Badge> : null}\n </div>\n </TableCell>\n <TableCell className=\"text-right\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button\n size=\"sm\"\n variant=\"transparentMuted\"\n aria-label=\"Revoke invitation\"\n isLoading={revoke.isPending}\n className={\n revoke.isPending\n ? 'opacity-100 transition-opacity'\n : 'opacity-0 transition-opacity group-hover/row:opacity-100 focus-visible:opacity-100'\n }\n >\n <Icon name=\"closeLine\" className=\"size-16\" />\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Revoke invitation</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">Revoke invitation to {invitation.email}?</Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\">They will no longer be able to use the link from their email.</Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"danger\" onClick={handleRevoke} isLoading={revoke.isPending}>\n Revoke\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </TableCell>\n </TableRow>\n );\n}\n\nfunction InviteMemberModal({\n open,\n onOpenChange,\n workspaceId,\n workspaceName,\n}: {\n open: boolean;\n onOpenChange: (next: boolean) => void;\n workspaceId: string;\n workspaceName: string;\n}) {\n const create = useCreateInvitation(workspaceId);\n const [formError, setFormError] = useState<string | undefined>();\n\n const form = useForm({\n defaultValues: {email: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n const result = await create.mutateAsync({email: value.email});\n toast.success(`Invitation sent to ${result.email}.`);\n // Go through handleOpenChange so form.reset() fires and reopening the\n // modal does not show stale form state.\n handleOpenChange(false);\n } catch (error) {\n const mapped = invitationErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n function handleOpenChange(nextOpen: boolean) {\n if (!nextOpen) {\n form.reset();\n setFormError(undefined);\n create.reset();\n }\n onOpenChange(nextOpen);\n }\n\n return (\n <Modal open={open} onOpenChange={handleOpenChange}>\n <ModalTrigger asChild>\n <Button size=\"sm\" variant=\"secondary\">\n Invite member\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Invite a member</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">Invite a member</Text>\n </ModalHeader>\n <ModalBody className=\"gap-group\">\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n {formError}\n </Callout>\n ) : null}\n <form\n id=\"invite-member-form\"\n className=\"flex flex-col gap-group\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"email\"\n validators={{\n onBlur: createInvitationBodySchema.shape.email,\n onSubmit: createInvitationBodySchema.shape.email,\n }}\n >\n {(field) => (\n <FormField\n label=\"Email\"\n id=\"invite-email\"\n error={fieldError(field)}\n description={`They'll receive an email with a link to join ${workspaceName}.`}\n >\n <FormFieldInput\n autoComplete=\"email\"\n autoFocus\n name=\"email\"\n type=\"email\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </form>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => handleOpenChange(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"invite-member-form\" isLoading={create.isPending}>\n Send invitation\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n );\n}\n\nfunction EmptyInvitations() {\n return (\n <EmptyState\n icon=\"mailLine\"\n title=\"No pending invitations.\"\n description=\"Invite someone above to grow your workspace.\"\n />\n );\n}\n\nfunction TableSkeleton({rows, cols}: {rows: number; cols: number}) {\n return (\n <div className=\"flex flex-col gap-cluster\">\n {Array.from({length: rows}).map((_, rowIdx) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: stable placeholder rows\n <div key={rowIdx} className=\"grid grid-cols-3 gap-group\">\n {Array.from({length: cols}).map((__, colIdx) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: stable placeholder cells\n <Skeleton key={colIdx} className=\"h-20\" />\n ))}\n </div>\n ))}\n </div>\n );\n}\n"],"names":["createInvitationBodySchema","useAuthState","QueryLoadError","Badge","Button","Callout","EmptyState","FormField","FormFieldInput","fieldError","Icon","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","ModalTrigger","Skeleton","Table","TableBody","TableCell","TableHead","TableHeader","TableRow","toast","Code","Header","Text","formatDate","useForm","useState","getInvitationExpiry","getMemberRemovalRestriction","memberCount","useCreateInvitation","useListInvitations","useListMembers","useRemoveMember","useRevokeInvitation","invitationErrorToFormError","memberRemovalErrorMessage","WorkspaceMembersSettingsSection","workspaceId","workspaceName","div","className","MembersSection","PendingInvitationsSection","auth","query","members","data","section","variant","size","isPending","TableSkeleton","rows","cols","isError","undefined","subject","length","map","member","MemberRow","currentUserId","user","id","open","setOpen","remove","restriction","handleRemove","mutateAsync","userId","success","email","error","name","joinedAt","onOpenChange","asChild","aria-label","disabled","isLoading","onClick","invitations","inviteOpen","setInviteOpen","InviteMemberModal","EmptyInvitations","invitation","InvitationRow","revoke","expiry","handleRevoke","invitationId","invitedByDisplay","expiresAt","create","formError","setFormError","form","defaultValues","onSubmit","value","result","handleOpenChange","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","nextOpen","reset","role","type","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","validators","onBlur","shape","label","description","autoComplete","autoFocus","state","onChange","handleChange","target","handleBlur","icon","title","Array","from","_","rowIdx","__","colIdx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/members/workspace-members-section.tsx"],"sourcesContent":["import {createInvitationBodySchema} from '@shipfox/api-workspaces-dto';\nimport {useAuthState} from '@shipfox/client-auth';\nimport {QueryLoadError} from '@shipfox/client-ui';\nimport {Badge} from '@shipfox/react-ui/badge';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n ModalTrigger,\n} from '@shipfox/react-ui/modal';\nimport {Panel} from '@shipfox/react-ui/panel';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@shipfox/react-ui/table';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Header, Text} from '@shipfox/react-ui/typography';\nimport {formatDate} from '@shipfox/react-ui/utils';\nimport {useForm} from '@tanstack/react-form';\nimport {useState} from 'react';\nimport {\n getInvitationExpiry,\n getMemberRemovalRestriction,\n memberCount,\n type PendingInvitation,\n type WorkspaceMember,\n} from '#core/membership.js';\nimport {useCreateInvitation} from '#hooks/api/create-invitation.js';\nimport {useListInvitations} from '#hooks/api/list-invitations.js';\nimport {useListMembers} from '#hooks/api/list-members.js';\nimport {useRemoveMember} from '#hooks/api/remove-member.js';\nimport {useRevokeInvitation} from '#hooks/api/revoke-invitation.js';\nimport {invitationErrorToFormError, memberRemovalErrorMessage} from './form-errors.js';\n\nexport function WorkspaceMembersSettingsSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n return (\n <div className=\"flex min-w-0 flex-col gap-region\">\n <MembersSection workspaceId={workspaceId} workspaceName={workspaceName} />\n <PendingInvitationsSection workspaceId={workspaceId} workspaceName={workspaceName} />\n </div>\n );\n}\n\nfunction MembersSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n const auth = useAuthState();\n const query = useListMembers(workspaceId);\n const members = query.data ?? [];\n\n return (\n <section className=\"flex flex-col gap-group\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Members</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {query.isPending\n ? 'Loading members…'\n : `${memberCount(members)} ${memberCount(members) === 1 ? 'member' : 'members'}`}\n </Text>\n </div>\n\n {query.isPending ? <TableSkeleton rows={3} cols={3} label=\"Loading members\" /> : null}\n\n {query.isError && query.data === undefined ? (\n <Panel>\n <QueryLoadError query={query} subject=\"members\" variant=\"panel\" />\n </Panel>\n ) : null}\n\n {members.length > 0 ? (\n <Panel>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Email</TableHead>\n <TableHead>Joined</TableHead>\n <TableHead className=\"w-80 text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {members.map((member) => (\n <MemberRow\n key={member.id}\n member={member}\n members={members}\n currentUserId={auth.user?.id}\n workspaceId={workspaceId}\n workspaceName={workspaceName}\n />\n ))}\n </TableBody>\n </Table>\n </Panel>\n ) : null}\n </section>\n );\n}\n\nfunction MemberRow({\n member,\n members,\n currentUserId,\n workspaceId,\n workspaceName,\n}: {\n member: WorkspaceMember;\n members: readonly WorkspaceMember[];\n currentUserId: string | undefined;\n workspaceId: string;\n workspaceName: string;\n}) {\n const [open, setOpen] = useState(false);\n const remove = useRemoveMember(workspaceId);\n const restriction = getMemberRemovalRestriction({member, members, currentUserId});\n\n async function handleRemove() {\n try {\n await remove.mutateAsync({userId: member.userId});\n toast.success(`Removed ${member.email} from ${workspaceName}.`);\n setOpen(false);\n } catch (error) {\n toast.error(memberRemovalErrorMessage(error));\n }\n }\n\n return (\n <TableRow className={remove.isPending ? 'opacity-60' : undefined}>\n <TableCell className=\"font-medium\">{member.name ?? 'N/A'}</TableCell>\n <TableCell>\n <Code variant=\"paragraph\">{member.email}</Code>\n </TableCell>\n <TableCell>{formatDate(member.joinedAt)}</TableCell>\n <TableCell className=\"text-right\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button\n size=\"sm\"\n variant=\"transparentMuted\"\n aria-label=\"Remove member\"\n disabled={restriction !== undefined}\n isLoading={remove.isPending}\n className={\n remove.isPending\n ? 'opacity-100 transition-opacity'\n : 'opacity-0 transition-opacity group-hover/row:opacity-100 focus-visible:opacity-100'\n }\n >\n <Icon name=\"userUnfollowLine\" className=\"size-16\" />\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Remove member</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">\n Remove {member.name ?? member.email} from {workspaceName}?\n </Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\">\n They will lose access immediately. They can be re-invited later.\n </Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"danger\" onClick={handleRemove} isLoading={remove.isPending}>\n Remove\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </TableCell>\n </TableRow>\n );\n}\n\nfunction PendingInvitationsSection({\n workspaceId,\n workspaceName,\n}: {\n workspaceId: string;\n workspaceName: string;\n}) {\n const query = useListInvitations(workspaceId);\n const invitations = query.data ?? [];\n const [inviteOpen, setInviteOpen] = useState(false);\n\n return (\n <section className=\"flex flex-col gap-group\">\n <div className=\"flex items-center justify-between gap-group\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Pending invitations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {query.isPending\n ? 'Loading invitations…'\n : `${invitations.length} ${invitations.length === 1 ? 'invitation' : 'invitations'}`}\n </Text>\n </div>\n <InviteMemberModal\n open={inviteOpen}\n onOpenChange={setInviteOpen}\n workspaceId={workspaceId}\n workspaceName={workspaceName}\n />\n </div>\n\n {query.isPending ? <TableSkeleton rows={2} cols={3} label=\"Loading invitations\" /> : null}\n\n {query.isError && query.data === undefined ? (\n <Panel>\n <QueryLoadError query={query} subject=\"invitations\" variant=\"panel\" />\n </Panel>\n ) : null}\n\n {query.data !== undefined && invitations.length === 0 ? (\n <Panel>\n <EmptyInvitations />\n </Panel>\n ) : null}\n\n {invitations.length > 0 ? (\n <Panel>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Email</TableHead>\n <TableHead>Invited by</TableHead>\n <TableHead>Expires</TableHead>\n <TableHead className=\"w-80 text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invitations.map((invitation) => (\n <InvitationRow\n key={invitation.id}\n invitation={invitation}\n workspaceId={workspaceId}\n />\n ))}\n </TableBody>\n </Table>\n </Panel>\n ) : null}\n </section>\n );\n}\n\nfunction InvitationRow({\n invitation,\n workspaceId,\n}: {\n invitation: PendingInvitation;\n workspaceId: string;\n}) {\n const [open, setOpen] = useState(false);\n const revoke = useRevokeInvitation(workspaceId);\n const expiry = getInvitationExpiry(invitation);\n\n async function handleRevoke() {\n try {\n await revoke.mutateAsync({invitationId: invitation.id});\n toast.success(`Invitation to ${invitation.email} revoked.`);\n setOpen(false);\n } catch {\n toast.error('Could not revoke invitation.');\n }\n }\n\n return (\n <TableRow className={revoke.isPending ? 'opacity-60' : undefined}>\n <TableCell>\n <Code variant=\"paragraph\">{invitation.email}</Code>\n </TableCell>\n <TableCell>{invitation.invitedByDisplay ?? 'N/A'}</TableCell>\n <TableCell>\n <div className=\"flex items-center gap-inline\">\n <Text size=\"sm\">{formatDate(invitation.expiresAt)}</Text>\n {expiry === 'expires-soon' ? <Badge variant=\"warning\">Soon</Badge> : null}\n {expiry === 'expired' ? <Badge variant=\"error\">Expired</Badge> : null}\n </div>\n </TableCell>\n <TableCell className=\"text-right\">\n <Modal open={open} onOpenChange={setOpen}>\n <ModalTrigger asChild>\n <Button\n size=\"sm\"\n variant=\"transparentMuted\"\n aria-label=\"Revoke invitation\"\n isLoading={revoke.isPending}\n className={\n revoke.isPending\n ? 'opacity-100 transition-opacity'\n : 'opacity-0 transition-opacity group-hover/row:opacity-100 focus-visible:opacity-100'\n }\n >\n <Icon name=\"closeLine\" className=\"size-16\" />\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Revoke invitation</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">Revoke invitation to {invitation.email}?</Text>\n </ModalHeader>\n <ModalBody>\n <Text size=\"sm\">They will no longer be able to use the link from their email.</Text>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button variant=\"danger\" onClick={handleRevoke} isLoading={revoke.isPending}>\n Revoke\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </TableCell>\n </TableRow>\n );\n}\n\nfunction InviteMemberModal({\n open,\n onOpenChange,\n workspaceId,\n workspaceName,\n}: {\n open: boolean;\n onOpenChange: (next: boolean) => void;\n workspaceId: string;\n workspaceName: string;\n}) {\n const create = useCreateInvitation(workspaceId);\n const [formError, setFormError] = useState<string | undefined>();\n\n const form = useForm({\n defaultValues: {email: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n const result = await create.mutateAsync({email: value.email});\n toast.success(`Invitation sent to ${result.email}.`);\n // Go through handleOpenChange so form.reset() fires and reopening the\n // modal does not show stale form state.\n handleOpenChange(false);\n } catch (error) {\n const mapped = invitationErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n function handleOpenChange(nextOpen: boolean) {\n if (!nextOpen) {\n form.reset();\n setFormError(undefined);\n create.reset();\n }\n onOpenChange(nextOpen);\n }\n\n return (\n <Modal open={open} onOpenChange={handleOpenChange}>\n <ModalTrigger asChild>\n <Button size=\"sm\" variant=\"secondary\">\n Invite member\n </Button>\n </ModalTrigger>\n <ModalContent>\n <ModalTitle className=\"sr-only\">Invite a member</ModalTitle>\n <ModalHeader>\n <Text size=\"lg\">Invite a member</Text>\n </ModalHeader>\n <ModalBody className=\"gap-group\">\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n {formError}\n </Callout>\n ) : null}\n <form\n id=\"invite-member-form\"\n className=\"flex flex-col gap-group\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"email\"\n validators={{\n onBlur: createInvitationBodySchema.shape.email,\n onSubmit: createInvitationBodySchema.shape.email,\n }}\n >\n {(field) => (\n <FormField\n label=\"Email\"\n id=\"invite-email\"\n error={fieldError(field)}\n description={`They'll receive an email with a link to join ${workspaceName}.`}\n >\n <FormFieldInput\n autoComplete=\"email\"\n autoFocus\n name=\"email\"\n type=\"email\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </form>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"secondary\" onClick={() => handleOpenChange(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" form=\"invite-member-form\" isLoading={create.isPending}>\n Send invitation\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n );\n}\n\nfunction EmptyInvitations() {\n return (\n <EmptyState\n icon=\"mailLine\"\n title=\"No pending invitations.\"\n description=\"Invite someone above to grow your workspace.\"\n variant=\"panel\"\n />\n );\n}\n\nfunction TableSkeleton({rows, cols, label}: {rows: number; cols: number; label: string}) {\n return (\n <Panel role=\"status\" aria-label={label} className=\"divide-y\">\n {Array.from({length: rows}).map((_, rowIdx) => (\n <div\n // biome-ignore lint/suspicious/noArrayIndexKey: stable placeholder rows\n key={rowIdx}\n className=\"grid min-h-44 grid-cols-3 gap-group px-row py-row\"\n >\n {Array.from({length: cols}).map((__, colIdx) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: stable placeholder cells\n <Skeleton key={colIdx} className=\"h-20\" />\n ))}\n </div>\n ))}\n </Panel>\n );\n}\n"],"names":["createInvitationBodySchema","useAuthState","QueryLoadError","Badge","Button","Callout","EmptyState","FormField","FormFieldInput","fieldError","Icon","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","ModalTrigger","Panel","Skeleton","Table","TableBody","TableCell","TableHead","TableHeader","TableRow","toast","Code","Header","Text","formatDate","useForm","useState","getInvitationExpiry","getMemberRemovalRestriction","memberCount","useCreateInvitation","useListInvitations","useListMembers","useRemoveMember","useRevokeInvitation","invitationErrorToFormError","memberRemovalErrorMessage","WorkspaceMembersSettingsSection","workspaceId","workspaceName","div","className","MembersSection","PendingInvitationsSection","auth","query","members","data","section","variant","size","isPending","TableSkeleton","rows","cols","label","isError","undefined","subject","length","map","member","MemberRow","currentUserId","user","id","open","setOpen","remove","restriction","handleRemove","mutateAsync","userId","success","email","error","name","joinedAt","onOpenChange","asChild","aria-label","disabled","isLoading","onClick","invitations","inviteOpen","setInviteOpen","InviteMemberModal","EmptyInvitations","invitation","InvitationRow","revoke","expiry","handleRevoke","invitationId","invitedByDisplay","expiresAt","create","formError","setFormError","form","defaultValues","onSubmit","value","result","handleOpenChange","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","nextOpen","reset","role","type","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","validators","onBlur","shape","description","autoComplete","autoFocus","state","onChange","handleChange","target","handleBlur","icon","title","Array","from","_","rowIdx","__","colIdx"],"mappings":"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"}
|
package/dist/routes/general.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { GeneralSettingsPage } from '#pages/general-settings-page.js';
|
|
2
2
|
declare const _default: import("@shipfox/client-shell/runtime").RouteImpl<{
|
|
3
|
+
readonly staticData: {
|
|
4
|
+
readonly frame: "content";
|
|
5
|
+
};
|
|
3
6
|
readonly component: typeof GeneralSettingsPage;
|
|
4
7
|
}>;
|
|
5
8
|
export default _default;
|
package/dist/routes/general.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/general.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {GeneralSettingsPage} from '#pages/general-settings-page.js';\n\nexport default defineRoute({component: GeneralSettingsPage});\n"],"names":["defineRoute","GeneralSettingsPage","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,mBAAmB,QAAO,kCAAkC;AAEpE,eAAeD,YAAY;
|
|
1
|
+
{"version":3,"sources":["../../src/routes/general.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {GeneralSettingsPage} from '#pages/general-settings-page.js';\n\nexport default defineRoute({\n staticData: {frame: 'content'},\n component: GeneralSettingsPage,\n});\n"],"names":["defineRoute","GeneralSettingsPage","staticData","frame","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,mBAAmB,QAAO,kCAAkC;AAEpE,eAAeD,YAAY;IACzBE,YAAY;QAACC,OAAO;IAAS;IAC7BC,WAAWH;AACb,GAAG"}
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.tsx"],"names":[],"mappings":";;;;sCAKyB;QAAC,MAAM,EAAE;YAAC,aAAa,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC"}
|
package/dist/routes/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { defineRoute } from '@shipfox/client-shell/runtime';
|
|
2
2
|
import { redirect } from '@tanstack/react-router';
|
|
3
3
|
export default defineRoute({
|
|
4
|
+
staticData: {
|
|
5
|
+
frame: 'content'
|
|
6
|
+
},
|
|
4
7
|
beforeLoad: ({ params })=>{
|
|
5
8
|
throw redirect({
|
|
6
9
|
to: '/w/$workspaceSlug/settings/members',
|
package/dist/routes/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/index.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {redirect} from '@tanstack/react-router';\n\nexport default defineRoute({\n beforeLoad: ({params}: {params: {workspaceSlug: string}}) => {\n throw redirect({\n to: '/w/$workspaceSlug/settings/members',\n params: {workspaceSlug: params.workspaceSlug},\n });\n },\n});\n"],"names":["defineRoute","redirect","beforeLoad","params","to","workspaceSlug"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,QAAQ,QAAO,yBAAyB;AAEhD,eAAeD,YAAY;IACzBE,YAAY,CAAC,EAACC,MAAM,EAAoC;QACtD,
|
|
1
|
+
{"version":3,"sources":["../../src/routes/index.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {redirect} from '@tanstack/react-router';\n\nexport default defineRoute({\n staticData: {frame: 'content'},\n beforeLoad: ({params}: {params: {workspaceSlug: string}}) => {\n throw redirect({\n to: '/w/$workspaceSlug/settings/members',\n params: {workspaceSlug: params.workspaceSlug},\n });\n },\n});\n"],"names":["defineRoute","redirect","staticData","frame","beforeLoad","params","to","workspaceSlug"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,QAAQ,QAAO,yBAAyB;AAEhD,eAAeD,YAAY;IACzBE,YAAY;QAACC,OAAO;IAAS;IAC7BC,YAAY,CAAC,EAACC,MAAM,EAAoC;QACtD,MAAMJ,SAAS;YACbK,IAAI;YACJD,QAAQ;gBAACE,eAAeF,OAAOE,aAAa;YAAA;QAC9C;IACF;AACF,GAAG"}
|
package/dist/routes/members.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { MembersSettingsPage } from '#pages/members-settings-page.js';
|
|
2
2
|
declare const _default: import("@shipfox/client-shell/runtime").RouteImpl<{
|
|
3
|
+
readonly staticData: {
|
|
4
|
+
readonly frame: "content";
|
|
5
|
+
};
|
|
3
6
|
readonly component: typeof MembersSettingsPage;
|
|
4
7
|
}>;
|
|
5
8
|
export default _default;
|
package/dist/routes/members.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/members.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {MembersSettingsPage} from '#pages/members-settings-page.js';\nexport default defineRoute({component: MembersSettingsPage});\n"],"names":["defineRoute","MembersSettingsPage","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,mBAAmB,QAAO,kCAAkC;AACpE,eAAeD,YAAY;
|
|
1
|
+
{"version":3,"sources":["../../src/routes/members.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {MembersSettingsPage} from '#pages/members-settings-page.js';\nexport default defineRoute({\n staticData: {frame: 'content'},\n component: MembersSettingsPage,\n});\n"],"names":["defineRoute","MembersSettingsPage","staticData","frame","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,mBAAmB,QAAO,kCAAkC;AACpE,eAAeD,YAAY;IACzBE,YAAY;QAACC,OAAO;IAAS;IAC7BC,WAAWH;AACb,GAAG"}
|