@pelatform/starter 0.1.8 → 0.1.9

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/extend.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  request,
7
7
  setLastVisitedWorkspace,
8
8
  socialProviders
9
- } from "./chunk-IEJXTIKE.js";
9
+ } from "./chunk-7Y52PHJN.js";
10
10
  import {
11
11
  WORKSPACE_SCOPED_PREFIXES,
12
12
  lastVisitedWorkspace
package/dist/index.d.ts CHANGED
@@ -3914,7 +3914,7 @@ type WorkspaceProviderProps = {
3914
3914
  fetchWorkspaceList?: string;
3915
3915
  fetchWorkspaceBySlug?: string;
3916
3916
  };
3917
- declare function WorkspaceProvider({ children, initialWorkspace, workspaceSlug, fetchWorkspaceList, fetchWorkspaceBySlug, }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
3917
+ declare function WorkspaceProvider({ children, initialWorkspace, workspaceSlug, fetchWorkspaceList: fetchWorkspaceListProp, fetchWorkspaceBySlug: fetchWorkspaceBySlugProp, }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
3918
3918
 
3919
3919
  declare function CardComponent({ children, className, classNames, title, description, instructions, actionLabel, action, disabled, isDestructive, isPending, isSubmitting, ...props }: CardComponentProps): react_jsx_runtime.JSX.Element;
3920
3920
  declare function CardHeaderComponent({ className, classNames, title, description, isPending, }: CardComponentProps): react_jsx_runtime.JSX.Element;
@@ -3933,7 +3933,9 @@ declare function SkeletonInputComponent({ classNames }: {
3933
3933
 
3934
3934
  declare function getUserName(user: Profile | null | undefined): string | null | undefined;
3935
3935
  declare function UserAvatar({ className, classNames, isPending, size, user, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
3936
- declare function WorkspaceLogo({ className, classNames, isPending, size, workspace, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
3936
+ declare function WorkspaceLogo({ className, classNames, isPending, size, workspace, image, ...props }: AvatarProps & {
3937
+ image?: string;
3938
+ }): react_jsx_runtime.JSX.Element;
3937
3939
 
3938
3940
  declare function DisplayIdCard({ className, classNames, isPending, id, title, description, ...props }: CardComponentProps & {
3939
3941
  id: string | undefined;
@@ -3975,6 +3977,22 @@ declare function ApiKeyView({ className, classNames, apiKey }: ViewProps & {
3975
3977
  }): react_jsx_runtime.JSX.Element;
3976
3978
  declare function WorkspaceView({ className, classNames, isPending, size, workspace }: ViewProps): react_jsx_runtime.JSX.Element;
3977
3979
 
3980
+ declare function WorkspaceDeleteCard({ className, classNames, ...props }: CardComponentProps): react_jsx_runtime.JSX.Element | null;
3981
+
3982
+ declare function WorkspaceLogoCard({ className, classNames, logo, ...props }: CardComponentProps & {
3983
+ logo?: ImageOptions;
3984
+ }): react_jsx_runtime.JSX.Element;
3985
+
3986
+ declare function WorkspaceNameCard({ className, classNames, ...props }: CardComponentProps): react_jsx_runtime.JSX.Element;
3987
+
3988
+ declare function WorkspaceSlugCard({ className, classNames, ...props }: CardComponentProps): react_jsx_runtime.JSX.Element;
3989
+
3990
+ declare function WorkspaceSettingsCards({ className, classNames, logo, }: {
3991
+ className?: string;
3992
+ classNames?: CardClassNames;
3993
+ logo?: ImageOptions;
3994
+ }): react_jsx_runtime.JSX.Element;
3995
+
3978
3996
  declare function WorkspaceSwitcher(): react_jsx_runtime.JSX.Element;
3979
3997
 
3980
- export { AcceptInvitation, ApiKeyDeleteDialog, ApiKeyDisplayDialog, ApiKeyView, ApiKeysCard, type AuthButtonProps, AuthCallback, AuthForm, type AuthFormClassNames, type AuthFormProps, AuthLayout, AuthView, type AuthViewClassNames, type AuthViewProps, BackupCodesDialog, CardActionComponent, CardComponent, CardFooterComponent, CardHeaderComponent, ConfigContext, ConfigProvider, type ConfigProviderProps, CreateApiKeyDialog, DeleteAccountCard, DeleteAccountDialog, DialogComponent, DialogFooterComponent, DisplayIdCard, EmailOTPButton, EmailOTPForm, EmptyState, type EmptyStateProps, ForgotPasswordForm, FormAvatarCard, FormEmailCard, FormFieldsCard, FormNameCard, FormPasswordCard, FormUsernameCard, Header, HeaderLeft, HeaderRight, HeaderSidebarMobile, LanguageSwitcher, LastUsedButton, LayoutContext, type LayoutContextType, LayoutLoader, LayoutProvider, type LayoutProviderProps, LayoutWrapper, MagicLinkButton, MagicLinkForm, MultiAccountCard, NewWorkspace, NewWorkspaceForm, OTPInputGroup, OneTap, PasskeyButton, PasskeysCard, PasswordInput, ProviderButton, ProvidersCard, QueryContext, RecoverAccountForm, ResetPasswordForm, SecurityCards, SessionFreshnessDialog, SessionsCard, SettingsCards, SharedProviders, type SharedProvidersProps, Sidebar, SidebarContent, SidebarContentMenu, SidebarHeaderBack, SidebarHeaderWorkspaces, SignInForm, SignOut, SignUpForm, SignedInHint, SiteFooter, SiteHeader, SiteHeaderSecondary, SkeletonInputComponent, SkeletonViewComponent, Toolbar, TwoFactorCard, TwoFactorForm, TwoFactorPasswordDialog, UserAvatar, UserMenu, UserView, VerifyEmail, WorkspaceContext, type WorkspaceContextType, WorkspaceLogo, WorkspaceProvider, WorkspaceSwitcher, WorkspaceView, getUserName, useAccountInfo, useAuthMutation, useAuthQuery, useConfig, useCreateApiKey, useDeleteApiKey, useDeletePasskey, useInvitation, useLayout, useListAccounts, useListApiKeys, useListDeviceSessions, useListPasskeys, useListSessions, useOnMutateError, useOnSuccessTransition, useRevokeDeviceSession, useRevokeOtherSessions, useRevokeSession, useRevokeSessions, useSession, useSetActiveSession, useUnlinkAccount, useUpdateUser, useWorkspace };
3998
+ export { AcceptInvitation, ApiKeyDeleteDialog, ApiKeyDisplayDialog, ApiKeyView, ApiKeysCard, type AuthButtonProps, AuthCallback, AuthForm, type AuthFormClassNames, type AuthFormProps, AuthLayout, AuthView, type AuthViewClassNames, type AuthViewProps, BackupCodesDialog, CardActionComponent, CardComponent, CardFooterComponent, CardHeaderComponent, ConfigContext, ConfigProvider, type ConfigProviderProps, CreateApiKeyDialog, DeleteAccountCard, DeleteAccountDialog, DialogComponent, DialogFooterComponent, DisplayIdCard, EmailOTPButton, EmailOTPForm, EmptyState, type EmptyStateProps, ForgotPasswordForm, FormAvatarCard, FormEmailCard, FormFieldsCard, FormNameCard, FormPasswordCard, FormUsernameCard, Header, HeaderLeft, HeaderRight, HeaderSidebarMobile, LanguageSwitcher, LastUsedButton, LayoutContext, type LayoutContextType, LayoutLoader, LayoutProvider, type LayoutProviderProps, LayoutWrapper, MagicLinkButton, MagicLinkForm, MultiAccountCard, NewWorkspace, NewWorkspaceForm, OTPInputGroup, OneTap, PasskeyButton, PasskeysCard, PasswordInput, ProviderButton, ProvidersCard, QueryContext, RecoverAccountForm, ResetPasswordForm, SecurityCards, SessionFreshnessDialog, SessionsCard, SettingsCards, SharedProviders, type SharedProvidersProps, Sidebar, SidebarContent, SidebarContentMenu, SidebarHeaderBack, SidebarHeaderWorkspaces, SignInForm, SignOut, SignUpForm, SignedInHint, SiteFooter, SiteHeader, SiteHeaderSecondary, SkeletonInputComponent, SkeletonViewComponent, Toolbar, TwoFactorCard, TwoFactorForm, TwoFactorPasswordDialog, UserAvatar, UserMenu, UserView, VerifyEmail, WorkspaceContext, type WorkspaceContextType, WorkspaceDeleteCard, WorkspaceLogo, WorkspaceLogoCard, WorkspaceNameCard, WorkspaceProvider, WorkspaceSettingsCards, WorkspaceSlugCard, WorkspaceSwitcher, WorkspaceView, getUserName, useAccountInfo, useAuthMutation, useAuthQuery, useConfig, useCreateApiKey, useDeleteApiKey, useDeletePasskey, useInvitation, useLayout, useListAccounts, useListApiKeys, useListDeviceSessions, useListPasskeys, useListSessions, useOnMutateError, useOnSuccessTransition, useRevokeDeviceSession, useRevokeOtherSessions, useRevokeSession, useRevokeSessions, useSession, useSetActiveSession, useUnlinkAccount, useUpdateUser, useWorkspace };
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  request,
7
7
  setLastVisitedWorkspace,
8
8
  socialProviders
9
- } from "./chunk-IEJXTIKE.js";
9
+ } from "./chunk-7Y52PHJN.js";
10
10
  import {
11
11
  WORKSPACE_SCOPED_PREFIXES
12
12
  } from "./chunk-K5RU54UL.js";
@@ -839,6 +839,7 @@ function WorkspaceLogo({
839
839
  isPending,
840
840
  size,
841
841
  workspace,
842
+ image,
842
843
  ...props
843
844
  }) {
844
845
  const t = useTranslations3();
@@ -867,7 +868,7 @@ function WorkspaceLogo({
867
868
  /* @__PURE__ */ jsx5(
868
869
  AvatarImage,
869
870
  {
870
- src: src || void 0,
871
+ src: image || src || void 0,
871
872
  alt: name || t("systems.ORGANIZATION"),
872
873
  className: classNames?.image
873
874
  }
@@ -5804,9 +5805,9 @@ import { useMediaQuery } from "pelatform-ui/hooks";
5804
5805
  import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
5805
5806
  function WorkspaceSwitcher() {
5806
5807
  const { path } = useConfig();
5808
+ const { activeWorkspace, updateActiveWorkspace, workspaceList, isFetchingWorkspace } = useWorkspace();
5807
5809
  const router = useRouter16();
5808
5810
  const t = useTranslations46();
5809
- const { activeWorkspace, updateActiveWorkspace, workspaceList, isFetchingWorkspace } = useWorkspace();
5810
5811
  const ownedWorkspaces = workspaceList?.filter((workspace) => workspace.currentUserRole === "owner") || [];
5811
5812
  const sharedWorkspaces = workspaceList?.filter((workspace) => workspace.currentUserRole !== "owner") || [];
5812
5813
  async function switchWorkspace(org) {
@@ -6981,10 +6982,10 @@ function WorkspaceProvider({
6981
6982
  children,
6982
6983
  initialWorkspace,
6983
6984
  workspaceSlug,
6984
- fetchWorkspaceList = "api/workspaces",
6985
- fetchWorkspaceBySlug = "api/workspace/s"
6985
+ fetchWorkspaceList: fetchWorkspaceListProp,
6986
+ fetchWorkspaceBySlug: fetchWorkspaceBySlugProp
6986
6987
  }) {
6987
- const { authClient } = useConfig();
6988
+ const { authClient, app } = useConfig();
6988
6989
  const { queryKey } = useContext14(QueryContext);
6989
6990
  const pathname = usePathname5();
6990
6991
  const queryClient = useQueryClient3();
@@ -6992,6 +6993,8 @@ function WorkspaceProvider({
6992
6993
  const [activeWorkspace, setActiveWorkspace] = useState23(initialWorkspace);
6993
6994
  const [isSwitchingWorkspace, setIsSwitchingWorkspace] = useState23(false);
6994
6995
  const shouldFetchWorkspace = !!workspaceSlug && (!activeWorkspace || activeWorkspace.slug !== workspaceSlug);
6996
+ const fetchWorkspaceList = fetchWorkspaceListProp || `${app.api}/workspaces`;
6997
+ const fetchWorkspaceBySlug = fetchWorkspaceBySlugProp || `${app.api}/workspace/s`;
6995
6998
  const { data: usersWorkspaces } = useQuery3({
6996
6999
  queryKey: queryKey.workspaceList,
6997
7000
  queryFn: async () => {
@@ -7148,6 +7151,730 @@ function EmptyState({
7148
7151
  children
7149
7152
  ] });
7150
7153
  }
7154
+
7155
+ // src/ui/workspace/partials/delete.tsx
7156
+ import { useContext as useContext15, useState as useState24 } from "react";
7157
+ import { useRouter as useRouter22 } from "next/navigation";
7158
+ import { zodResolver as zodResolver16 } from "@hookform/resolvers/zod";
7159
+ import { useMutation as useMutation4, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
7160
+ import { useTranslations as useTranslations54 } from "next-intl";
7161
+ import { useForm as useForm17 } from "react-hook-form";
7162
+ import { z as z16 } from "zod";
7163
+ import { cn as cn47 } from "pelatform-ui";
7164
+ import { AlertToast as AlertToast29 } from "pelatform-ui/components";
7165
+ import {
7166
+ Button as Button39,
7167
+ Card as Card14,
7168
+ Form as Form17,
7169
+ FormControl as FormControl16,
7170
+ FormField as FormField16,
7171
+ FormItem as FormItem16,
7172
+ FormLabel as FormLabel15,
7173
+ FormMessage as FormMessage16,
7174
+ Input as Input13,
7175
+ Spinner as Spinner23
7176
+ } from "pelatform-ui/default";
7177
+ import { Fragment as Fragment22, jsx as jsx68, jsxs as jsxs57 } from "react/jsx-runtime";
7178
+ function WorkspaceDeleteCard({ className, classNames, ...props }) {
7179
+ const { activeWorkspace, isOwner } = useWorkspace();
7180
+ const t = useTranslations54();
7181
+ const [showDialog, setShowDialog] = useState24(false);
7182
+ if (!isOwner || !activeWorkspace) {
7183
+ return null;
7184
+ }
7185
+ return /* @__PURE__ */ jsxs57(Fragment22, { children: [
7186
+ /* @__PURE__ */ jsx68(
7187
+ CardComponent,
7188
+ {
7189
+ className,
7190
+ classNames,
7191
+ title: t("systems.DELETE_ORGANIZATION"),
7192
+ description: t("systems.DELETE_ORGANIZATION_DESCRIPTION"),
7193
+ actionLabel: t("systems.DELETE_ORGANIZATION"),
7194
+ action: () => setShowDialog(true),
7195
+ isDestructive: true,
7196
+ ...props
7197
+ }
7198
+ ),
7199
+ /* @__PURE__ */ jsx68(
7200
+ DeleteWorkspaceDialog,
7201
+ {
7202
+ classNames,
7203
+ open: showDialog,
7204
+ onOpenChange: setShowDialog
7205
+ }
7206
+ )
7207
+ ] });
7208
+ }
7209
+ function DeleteWorkspaceDialog({
7210
+ classNames,
7211
+ onOpenChange,
7212
+ title,
7213
+ description,
7214
+ ...props
7215
+ }) {
7216
+ const { authClient, path } = useConfig();
7217
+ const { queryKey } = useContext15(QueryContext);
7218
+ const { activeWorkspace, isOwner, updateActiveWorkspace, workspaceList } = useWorkspace();
7219
+ const queryClient = useQueryClient4();
7220
+ const router = useRouter22();
7221
+ const t = useTranslations54();
7222
+ const formSchema = z16.object({
7223
+ slug: z16.string().min(1, {
7224
+ error: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.IS_REQUIRED")}`
7225
+ }).refine((val) => val === activeWorkspace?.slug, {
7226
+ error: t("systems.SLUG_DOES_NOT_MATCH")
7227
+ })
7228
+ });
7229
+ const form = useForm17({
7230
+ resolver: zodResolver16(formSchema),
7231
+ defaultValues: {
7232
+ slug: ""
7233
+ }
7234
+ });
7235
+ const disableSubmit = form.formState.isSubmitting || !form.formState.isValid;
7236
+ const { mutate: deleteMutation, isPending } = useMutation4({
7237
+ mutationFn: async ({ organizationId }) => {
7238
+ await authClient.organization.delete({
7239
+ organizationId
7240
+ });
7241
+ },
7242
+ onSuccess: async () => {
7243
+ AlertToast29({
7244
+ message: t("systems.DELETE_ORGANIZATION_SUCCESS")
7245
+ });
7246
+ const remainingWorkspaces = workspaceList?.filter((org) => org.id !== activeWorkspace?.id);
7247
+ if (!remainingWorkspaces || remainingWorkspaces.length === 0) {
7248
+ router.push(path.custom.NEW_WORKSPACE || "/");
7249
+ return;
7250
+ }
7251
+ queryClient.invalidateQueries({
7252
+ queryKey: queryKey.workspaceList
7253
+ });
7254
+ const nextWorkspace = remainingWorkspaces[0];
7255
+ if (!nextWorkspace) {
7256
+ router.push(path.custom.NEW_WORKSPACE || "/");
7257
+ return;
7258
+ }
7259
+ await updateActiveWorkspace(nextWorkspace);
7260
+ router.push(`/${nextWorkspace.slug}`);
7261
+ onOpenChange?.(false);
7262
+ },
7263
+ onError: (error) => {
7264
+ AlertToast29({
7265
+ message: getTranslations({ error, t }),
7266
+ icon: "destructive"
7267
+ });
7268
+ }
7269
+ });
7270
+ const onSubmit = () => {
7271
+ if (!isOwner || !activeWorkspace?.id) {
7272
+ return;
7273
+ }
7274
+ deleteMutation({ organizationId: activeWorkspace.id });
7275
+ };
7276
+ return /* @__PURE__ */ jsxs57(
7277
+ DialogComponent,
7278
+ {
7279
+ classNames,
7280
+ onOpenChange,
7281
+ title: title || t("systems.DELETE_ORGANIZATION"),
7282
+ description: description || t("systems.DELETE_ORGANIZATION_DESCRIPTION"),
7283
+ disableFooter: true,
7284
+ ...props,
7285
+ children: [
7286
+ /* @__PURE__ */ jsx68(Card14, { className: cn47("mb-4 flex-row p-4", classNames?.cell), children: /* @__PURE__ */ jsx68(WorkspaceView, { workspace: activeWorkspace }) }),
7287
+ /* @__PURE__ */ jsx68(Form17, { ...form, children: /* @__PURE__ */ jsxs57("form", { onSubmit: form.handleSubmit(onSubmit), children: [
7288
+ /* @__PURE__ */ jsx68(
7289
+ FormField16,
7290
+ {
7291
+ control: form.control,
7292
+ name: "slug",
7293
+ render: ({ field }) => /* @__PURE__ */ jsxs57(FormItem16, { children: [
7294
+ /* @__PURE__ */ jsxs57(FormLabel15, { className: cn47("font-normal", classNames?.label), children: [
7295
+ t("systems.DELETE_ORGANIZATION_INSTRUCTIONS"),
7296
+ " ",
7297
+ /* @__PURE__ */ jsx68("span", { className: "font-bold", children: activeWorkspace?.slug })
7298
+ ] }),
7299
+ /* @__PURE__ */ jsx68(FormControl16, { children: /* @__PURE__ */ jsx68(
7300
+ Input13,
7301
+ {
7302
+ placeholder: activeWorkspace?.slug,
7303
+ className: classNames?.input,
7304
+ autoComplete: "off",
7305
+ disabled: isPending,
7306
+ ...field
7307
+ }
7308
+ ) }),
7309
+ /* @__PURE__ */ jsx68(FormMessage16, { className: classNames?.error })
7310
+ ] })
7311
+ }
7312
+ ),
7313
+ /* @__PURE__ */ jsx68(
7314
+ DialogFooterComponent,
7315
+ {
7316
+ classNames,
7317
+ onOpenChange,
7318
+ cancelButton: true,
7319
+ cancelButtonDisabled: isPending,
7320
+ button: /* @__PURE__ */ jsxs57(
7321
+ Button39,
7322
+ {
7323
+ type: "submit",
7324
+ variant: "destructive",
7325
+ className: cn47(
7326
+ disableSubmit && "pointer-events-auto! cursor-not-allowed",
7327
+ classNames?.button,
7328
+ classNames?.destructiveButton
7329
+ ),
7330
+ disabled: disableSubmit,
7331
+ children: [
7332
+ isPending && /* @__PURE__ */ jsx68(Spinner23, {}),
7333
+ t("systems.DELETE_ORGANIZATION")
7334
+ ]
7335
+ }
7336
+ )
7337
+ }
7338
+ )
7339
+ ] }) })
7340
+ ]
7341
+ }
7342
+ );
7343
+ }
7344
+
7345
+ // src/ui/workspace/partials/logo.tsx
7346
+ import { useContext as useContext16, useRef as useRef8, useState as useState25 } from "react";
7347
+ import { useRouter as useRouter23 } from "next/navigation";
7348
+ import { useMutation as useMutation5, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
7349
+ import { Trash2Icon as Trash2Icon2, UploadCloudIcon as UploadCloudIcon2 } from "lucide-react";
7350
+ import { useTranslations as useTranslations55 } from "next-intl";
7351
+ import { fileToBase64 as fileToBase642, resizeAndCropImage as resizeAndCropImage2 } from "pelatform-ui";
7352
+ import { AlertToast as AlertToast30 } from "pelatform-ui/components";
7353
+ import {
7354
+ Button as Button40,
7355
+ DropdownMenu as DropdownMenu5,
7356
+ DropdownMenuContent as DropdownMenuContent5,
7357
+ DropdownMenuItem as DropdownMenuItem5,
7358
+ DropdownMenuTrigger as DropdownMenuTrigger5
7359
+ } from "pelatform-ui/default";
7360
+ import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
7361
+ function WorkspaceLogoCard({
7362
+ className,
7363
+ classNames,
7364
+ logo,
7365
+ ...props
7366
+ }) {
7367
+ const { authClient } = useConfig();
7368
+ const { queryKey } = useContext16(QueryContext);
7369
+ const { activeWorkspace, isOwner } = useWorkspace();
7370
+ const queryClient = useQueryClient5();
7371
+ const router = useRouter23();
7372
+ const t = useTranslations55();
7373
+ const fileInputRef = useRef8(null);
7374
+ const [logoUrl, setLogoUrl] = useState25(activeWorkspace?.logo || null);
7375
+ const [loading, setLoading] = useState25(false);
7376
+ const isBase64Logo = logoUrl?.includes("data:image");
7377
+ const isDicebearLogo = logoUrl?.includes("api.dicebear.com");
7378
+ const { mutate: updateMutation, isPending } = useMutation5({
7379
+ mutationFn: async ({ organizationId, logo: logo2 }) => {
7380
+ const res = await authClient.organization.update({
7381
+ organizationId,
7382
+ data: { logo: logo2 }
7383
+ });
7384
+ if (res?.error) {
7385
+ throw new Error(res.error.message);
7386
+ }
7387
+ return res;
7388
+ },
7389
+ onSuccess: (_, variables) => {
7390
+ setLogoUrl(variables.logo);
7391
+ AlertToast30({
7392
+ message: `${t("systems.LOGO_UPDATED")}`
7393
+ });
7394
+ queryClient.invalidateQueries({
7395
+ queryKey: queryKey.workspaceById(variables.organizationId)
7396
+ });
7397
+ router.refresh();
7398
+ },
7399
+ onError: (error) => {
7400
+ AlertToast30({
7401
+ message: getTranslations({ error, t }),
7402
+ icon: "destructive"
7403
+ });
7404
+ }
7405
+ });
7406
+ const handleLogoChange = async (file) => {
7407
+ if (!activeWorkspace?.id || !isOwner) return;
7408
+ setLoading(true);
7409
+ try {
7410
+ const resizedFile = await resizeAndCropImage2(
7411
+ file,
7412
+ crypto.randomUUID(),
7413
+ logo?.size || 256,
7414
+ logo?.extension || "png"
7415
+ );
7416
+ let image;
7417
+ if (logo?.upload) {
7418
+ image = await logo.upload(resizedFile);
7419
+ } else {
7420
+ image = await fileToBase642(resizedFile);
7421
+ }
7422
+ if (!image) {
7423
+ setLoading(false);
7424
+ return;
7425
+ }
7426
+ updateMutation({
7427
+ organizationId: activeWorkspace.id,
7428
+ logo: image
7429
+ });
7430
+ } catch (error) {
7431
+ AlertToast30({
7432
+ message: getTranslations({ error, t }),
7433
+ icon: "destructive"
7434
+ });
7435
+ }
7436
+ setLoading(false);
7437
+ };
7438
+ const handleDeleteLogo = async () => {
7439
+ if (!activeWorkspace?.id || !isOwner) return;
7440
+ setLoading(true);
7441
+ try {
7442
+ if (logoUrl && !isBase64Logo && !isDicebearLogo && logo?.delete) {
7443
+ await logo.delete(logoUrl);
7444
+ }
7445
+ const defaultLogo = `https://api.dicebear.com/9.x/glass/svg?seed=${activeWorkspace.slug}`;
7446
+ updateMutation({
7447
+ organizationId: activeWorkspace.id,
7448
+ logo: defaultLogo
7449
+ });
7450
+ } catch (error) {
7451
+ AlertToast30({
7452
+ message: getTranslations({ error, t }),
7453
+ icon: "destructive"
7454
+ });
7455
+ }
7456
+ setLoading(false);
7457
+ };
7458
+ const openFileDialog = () => {
7459
+ fileInputRef.current?.click();
7460
+ };
7461
+ return /* @__PURE__ */ jsxs58(
7462
+ CardComponent,
7463
+ {
7464
+ className,
7465
+ classNames: {
7466
+ content: "flex items-center justify-between",
7467
+ header: "w-full",
7468
+ ...classNames
7469
+ },
7470
+ title: t("systems.LOGO"),
7471
+ description: t("systems.LOGO_DESCRIPTION"),
7472
+ instructions: t("systems.LOGO_INSTRUCTIONS"),
7473
+ ...props,
7474
+ children: [
7475
+ /* @__PURE__ */ jsx69(
7476
+ "input",
7477
+ {
7478
+ ref: fileInputRef,
7479
+ type: "file",
7480
+ hidden: true,
7481
+ accept: "image/*",
7482
+ onChange: (e) => {
7483
+ const file = e.target.files?.item(0);
7484
+ if (file) handleLogoChange(file);
7485
+ e.target.value = "";
7486
+ },
7487
+ disabled: loading || !isOwner
7488
+ }
7489
+ ),
7490
+ /* @__PURE__ */ jsxs58(DropdownMenu5, { children: [
7491
+ /* @__PURE__ */ jsx69(DropdownMenuTrigger5, { asChild: true, children: /* @__PURE__ */ jsx69(Button40, { variant: "ghost", size: "icon", className: "size-fit rounded-full", disabled: !isOwner, children: /* @__PURE__ */ jsx69(
7492
+ WorkspaceLogo,
7493
+ {
7494
+ className: "size-16 lg:size-20",
7495
+ classNames: {
7496
+ fallback: "text-xl lg:text-2xl",
7497
+ ...classNames?.avatar
7498
+ },
7499
+ isPending,
7500
+ workspace: activeWorkspace,
7501
+ image: logoUrl || void 0
7502
+ }
7503
+ ) }) }),
7504
+ /* @__PURE__ */ jsxs58(DropdownMenuContent5, { align: "end", onCloseAutoFocus: (e) => e.preventDefault(), children: [
7505
+ /* @__PURE__ */ jsxs58(DropdownMenuItem5, { onClick: openFileDialog, disabled: loading || !isOwner, children: [
7506
+ /* @__PURE__ */ jsx69(UploadCloudIcon2, {}),
7507
+ t("systems.UPLOAD_LOGO")
7508
+ ] }),
7509
+ !isDicebearLogo && /* @__PURE__ */ jsxs58(
7510
+ DropdownMenuItem5,
7511
+ {
7512
+ variant: "destructive",
7513
+ onClick: handleDeleteLogo,
7514
+ disabled: loading || !isOwner,
7515
+ children: [
7516
+ /* @__PURE__ */ jsx69(Trash2Icon2, {}),
7517
+ t("systems.DELETE_LOGO")
7518
+ ]
7519
+ }
7520
+ )
7521
+ ] })
7522
+ ] })
7523
+ ]
7524
+ }
7525
+ );
7526
+ }
7527
+
7528
+ // src/ui/workspace/partials/name.tsx
7529
+ import { useContext as useContext17, useId } from "react";
7530
+ import { useRouter as useRouter24 } from "next/navigation";
7531
+ import { zodResolver as zodResolver17 } from "@hookform/resolvers/zod";
7532
+ import { useMutation as useMutation6, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
7533
+ import { useTranslations as useTranslations56 } from "next-intl";
7534
+ import { useForm as useForm18 } from "react-hook-form";
7535
+ import { z as z17 } from "zod";
7536
+ import { AlertToast as AlertToast31 } from "pelatform-ui/components";
7537
+ import { Form as Form18, FormControl as FormControl17, FormField as FormField17, FormItem as FormItem17, FormMessage as FormMessage17, Input as Input14 } from "pelatform-ui/default";
7538
+ import { jsx as jsx70, jsxs as jsxs59 } from "react/jsx-runtime";
7539
+ function WorkspaceNameCard({ className, classNames, ...props }) {
7540
+ const { authClient } = useConfig();
7541
+ const { queryKey } = useContext17(QueryContext);
7542
+ const { activeWorkspace, isOwner } = useWorkspace();
7543
+ const queryClient = useQueryClient6();
7544
+ const router = useRouter24();
7545
+ const t = useTranslations56();
7546
+ const id = useId();
7547
+ const formSchema = z17.object({
7548
+ name: z17.string().min(1, {
7549
+ error: `${t("systems.ORGANIZATION_NAME")} ${t("systems.IS_REQUIRED")}`
7550
+ })
7551
+ });
7552
+ const form = useForm18({
7553
+ resolver: zodResolver17(formSchema),
7554
+ values: { name: activeWorkspace?.name || "" }
7555
+ });
7556
+ const disableSubmit = form.formState.isSubmitting || !form.formState.isValid || !form.formState.isDirty;
7557
+ const { mutate: updateMutation, isPending } = useMutation6({
7558
+ mutationFn: async ({
7559
+ organizationId,
7560
+ data
7561
+ }) => {
7562
+ const res = await authClient.organization.update({
7563
+ organizationId,
7564
+ data: {
7565
+ name: data.name
7566
+ }
7567
+ });
7568
+ if (res?.error) {
7569
+ throw new Error(res.error.message);
7570
+ }
7571
+ return res;
7572
+ },
7573
+ onSuccess: (_, variables) => {
7574
+ AlertToast31({
7575
+ message: `${t("systems.ORGANIZATION_NAME")} ${t("systems.UPDATED_SUCCESSFULLY")}`
7576
+ });
7577
+ form.reset({ name: form.getValues("name") });
7578
+ queryClient.invalidateQueries({
7579
+ queryKey: queryKey.workspaceById(variables.organizationId)
7580
+ });
7581
+ router.refresh();
7582
+ },
7583
+ onError: (error) => {
7584
+ AlertToast31({
7585
+ message: getTranslations({ error, t }),
7586
+ icon: "destructive"
7587
+ });
7588
+ }
7589
+ });
7590
+ const onSubmit = (data) => {
7591
+ if (!isOwner || !activeWorkspace?.id) {
7592
+ return;
7593
+ }
7594
+ const name = data.name.trim();
7595
+ if (activeWorkspace?.name === name) {
7596
+ AlertToast31({
7597
+ message: `${t("systems.ORGANIZATION_NAME")} ${t("systems.IS_THE_SAME")}`,
7598
+ icon: "destructive"
7599
+ });
7600
+ return;
7601
+ }
7602
+ updateMutation({
7603
+ organizationId: activeWorkspace.id,
7604
+ data: { name }
7605
+ });
7606
+ };
7607
+ return /* @__PURE__ */ jsx70(Form18, { ...form, children: /* @__PURE__ */ jsx70("form", { onSubmit: form.handleSubmit(onSubmit), children: /* @__PURE__ */ jsx70(
7608
+ CardComponent,
7609
+ {
7610
+ className,
7611
+ classNames,
7612
+ title: t("systems.ORGANIZATION_NAME"),
7613
+ description: t("systems.ORGANIZATION_NAME_DESCRIPTION"),
7614
+ instructions: t("systems.ORGANIZATION_NAME_INSTRUCTIONS"),
7615
+ actionLabel: t("systems.SAVE"),
7616
+ disabled: disableSubmit || !isOwner,
7617
+ isSubmitting: isPending,
7618
+ ...props,
7619
+ children: /* @__PURE__ */ jsx70(
7620
+ FormField17,
7621
+ {
7622
+ control: form.control,
7623
+ name: "name",
7624
+ render: ({ field }) => /* @__PURE__ */ jsxs59(FormItem17, { children: [
7625
+ /* @__PURE__ */ jsx70(FormControl17, { children: /* @__PURE__ */ jsx70(
7626
+ Input14,
7627
+ {
7628
+ id,
7629
+ className: classNames?.input,
7630
+ placeholder: t("systems.ORGANIZATION_NAME_PLACEHOLDER"),
7631
+ disabled: !isOwner,
7632
+ ...field
7633
+ }
7634
+ ) }),
7635
+ /* @__PURE__ */ jsx70(FormMessage17, { className: classNames?.error })
7636
+ ] })
7637
+ }
7638
+ )
7639
+ }
7640
+ ) }) });
7641
+ }
7642
+
7643
+ // src/ui/workspace/partials/slug.tsx
7644
+ import { useContext as useContext18, useId as useId2 } from "react";
7645
+ import { useRouter as useRouter25 } from "next/navigation";
7646
+ import { zodResolver as zodResolver18 } from "@hookform/resolvers/zod";
7647
+ import { useMutation as useMutation7, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
7648
+ import { useTranslations as useTranslations57 } from "next-intl";
7649
+ import { useForm as useForm19 } from "react-hook-form";
7650
+ import { z as z18 } from "zod";
7651
+ import { AlertToast as AlertToast32 } from "pelatform-ui/components";
7652
+ import { Form as Form19, FormControl as FormControl18, FormField as FormField18, FormItem as FormItem18, FormMessage as FormMessage18, Input as Input15 } from "pelatform-ui/default";
7653
+
7654
+ // src/lib/string.ts
7655
+ function generateSlug(text) {
7656
+ const slug = text.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
7657
+ return slug;
7658
+ }
7659
+
7660
+ // src/ui/workspace/partials/slug.tsx
7661
+ import { jsx as jsx71, jsxs as jsxs60 } from "react/jsx-runtime";
7662
+ function WorkspaceSlugCard({ className, classNames, ...props }) {
7663
+ const { authClient, path } = useConfig();
7664
+ const { queryKey } = useContext18(QueryContext);
7665
+ const { activeWorkspace, isOwner } = useWorkspace();
7666
+ const queryClient = useQueryClient7();
7667
+ const router = useRouter25();
7668
+ const t = useTranslations57();
7669
+ const RESERVED_SLUGS = [
7670
+ // Main routes
7671
+ path.main.ERROR.replace("/", ""),
7672
+ path.main.HOME.replace("/", ""),
7673
+ path.main.FEATURES.replace("/", ""),
7674
+ path.main.PRICING.replace("/", ""),
7675
+ path.main.TERMS.replace("/", ""),
7676
+ path.main.PRIVACY.replace("/", ""),
7677
+ // Auth routes
7678
+ path.auth.EMAIL_OTP.replace("/", ""),
7679
+ path.auth.FORGOT_PASSWORD.replace("/", ""),
7680
+ path.auth.MAGIC_LINK.replace("/", ""),
7681
+ path.auth.RECOVER_ACCOUNT.replace("/", ""),
7682
+ path.auth.RESET_PASSWORD.replace("/", ""),
7683
+ path.auth.SIGN_IN.replace("/", ""),
7684
+ path.auth.SIGN_OUT.replace("/", ""),
7685
+ path.auth.SIGN_UP.replace("/", ""),
7686
+ path.auth.TWO_FACTOR.replace("/", ""),
7687
+ // System routes
7688
+ "new",
7689
+ "accept",
7690
+ "invitation",
7691
+ "join",
7692
+ "verify",
7693
+ "api",
7694
+ "account",
7695
+ "accounts",
7696
+ "billing",
7697
+ "billings",
7698
+ "user",
7699
+ "users",
7700
+ "onboarding",
7701
+ "organization",
7702
+ "organizations",
7703
+ "workspace",
7704
+ "workspaces",
7705
+ "setting",
7706
+ "settings",
7707
+ "apikey",
7708
+ "apikeys",
7709
+ "member",
7710
+ "members",
7711
+ "people",
7712
+ "peoples",
7713
+ // Next.js internals
7714
+ "_next",
7715
+ "static",
7716
+ "favicon",
7717
+ "robots",
7718
+ "sitemap",
7719
+ // Future-proofing common patterns
7720
+ "admin",
7721
+ "dashboard",
7722
+ "app",
7723
+ "www",
7724
+ "home",
7725
+ "blog",
7726
+ "docs",
7727
+ "help",
7728
+ "support",
7729
+ "about",
7730
+ "contact",
7731
+ "features",
7732
+ "pricing",
7733
+ "terms",
7734
+ "privacy"
7735
+ ];
7736
+ const id = useId2();
7737
+ const formSchema = z18.object({
7738
+ slug: z18.string().min(1, {
7739
+ error: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.IS_REQUIRED")}`
7740
+ }).regex(/^[a-z0-9]+([a-z0-9-]*[a-z0-9])?$/, {
7741
+ error: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.IS_INVALID")}`
7742
+ }).refine((slug) => !RESERVED_SLUGS.includes(slug), {
7743
+ error: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.IS_INVALID")}`
7744
+ })
7745
+ });
7746
+ const form = useForm19({
7747
+ resolver: zodResolver18(formSchema),
7748
+ values: { slug: activeWorkspace?.slug || "" }
7749
+ });
7750
+ const disableSubmit = form.formState.isSubmitting || !form.formState.isValid || !form.formState.isDirty;
7751
+ const { mutate: updateMutation, isPending } = useMutation7({
7752
+ mutationFn: async ({
7753
+ organizationId,
7754
+ data
7755
+ }) => {
7756
+ const { data: checkSlug, error } = await authClient.organization.checkSlug({
7757
+ slug: data.slug
7758
+ });
7759
+ if (error) {
7760
+ throw new Error(error.message);
7761
+ }
7762
+ if (!checkSlug.status) {
7763
+ form.setError("slug", { message: t("systems.SLUG_ALREADY_TAKEN") });
7764
+ throw new Error(t("systems.SLUG_ALREADY_TAKEN"));
7765
+ }
7766
+ const res = await authClient.organization.update({
7767
+ organizationId,
7768
+ data: {
7769
+ slug: data.slug
7770
+ }
7771
+ });
7772
+ if (res?.error) {
7773
+ throw new Error(res.error.message);
7774
+ }
7775
+ return res;
7776
+ },
7777
+ onSuccess: (data, variables) => {
7778
+ if (!data) {
7779
+ return;
7780
+ }
7781
+ AlertToast32({
7782
+ message: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.UPDATED_SUCCESSFULLY")}`
7783
+ });
7784
+ form.reset({ slug: data.data?.slug });
7785
+ queryClient.invalidateQueries({
7786
+ queryKey: queryKey.workspaceById(variables.organizationId)
7787
+ });
7788
+ router.replace(`/${data.data?.slug}${path.workspaces.SETTINGS}`);
7789
+ router.refresh();
7790
+ },
7791
+ onError: (error) => {
7792
+ AlertToast32({
7793
+ message: getTranslations({ error, t }),
7794
+ icon: "destructive"
7795
+ });
7796
+ }
7797
+ });
7798
+ const onSubmit = (data) => {
7799
+ if (!isOwner || !activeWorkspace?.id) {
7800
+ return;
7801
+ }
7802
+ const slug = generateSlug(data.slug);
7803
+ if (activeWorkspace?.slug === slug) {
7804
+ AlertToast32({
7805
+ message: `${t("systems.ORGANIZATION_SLUG")} ${t("systems.IS_THE_SAME")}`,
7806
+ icon: "destructive"
7807
+ });
7808
+ return;
7809
+ }
7810
+ updateMutation({
7811
+ organizationId: activeWorkspace.id,
7812
+ data: { slug }
7813
+ });
7814
+ };
7815
+ return /* @__PURE__ */ jsx71(Form19, { ...form, children: /* @__PURE__ */ jsx71("form", { onSubmit: form.handleSubmit(onSubmit), children: /* @__PURE__ */ jsx71(
7816
+ CardComponent,
7817
+ {
7818
+ className,
7819
+ classNames,
7820
+ title: t("systems.ORGANIZATION_SLUG"),
7821
+ description: t("systems.ORGANIZATION_SLUG_DESCRIPTION"),
7822
+ instructions: t("systems.ORGANIZATION_SLUG_INSTRUCTIONS"),
7823
+ actionLabel: t("systems.SAVE"),
7824
+ disabled: disableSubmit || !isOwner,
7825
+ isSubmitting: isPending,
7826
+ ...props,
7827
+ children: /* @__PURE__ */ jsx71(
7828
+ FormField18,
7829
+ {
7830
+ control: form.control,
7831
+ name: "slug",
7832
+ render: ({ field }) => /* @__PURE__ */ jsxs60(FormItem18, { children: [
7833
+ /* @__PURE__ */ jsx71(FormControl18, { children: /* @__PURE__ */ jsx71(
7834
+ Input15,
7835
+ {
7836
+ id,
7837
+ className: classNames?.input,
7838
+ placeholder: t("systems.ORGANIZATION_SLUG_PLACEHOLDER"),
7839
+ disabled: !isOwner,
7840
+ ...field
7841
+ }
7842
+ ) }),
7843
+ /* @__PURE__ */ jsx71(FormMessage18, { className: classNames?.error })
7844
+ ] })
7845
+ }
7846
+ )
7847
+ }
7848
+ ) }) });
7849
+ }
7850
+
7851
+ // src/ui/workspace/settings.tsx
7852
+ import { useTranslations as useTranslations58 } from "next-intl";
7853
+ import { cn as cn48 } from "pelatform-ui";
7854
+ import { jsx as jsx72, jsxs as jsxs61 } from "react/jsx-runtime";
7855
+ function WorkspaceSettingsCards({
7856
+ className,
7857
+ classNames,
7858
+ logo
7859
+ }) {
7860
+ const t = useTranslations58();
7861
+ const { activeWorkspace } = useWorkspace();
7862
+ return /* @__PURE__ */ jsxs61("div", { className: cn48("grid w-full gap-6 md:gap-8", className), children: [
7863
+ /* @__PURE__ */ jsx72(WorkspaceLogoCard, { classNames, logo }),
7864
+ /* @__PURE__ */ jsx72(WorkspaceNameCard, { classNames }),
7865
+ /* @__PURE__ */ jsx72(WorkspaceSlugCard, { classNames }),
7866
+ /* @__PURE__ */ jsx72(
7867
+ DisplayIdCard,
7868
+ {
7869
+ classNames,
7870
+ id: activeWorkspace?.id,
7871
+ title: t("systems.DISPLAY_ORGANIZATION_TITLE"),
7872
+ description: t("systems.DISPLAY_ORGANIZATION_DESCRIPTION")
7873
+ }
7874
+ ),
7875
+ /* @__PURE__ */ jsx72(WorkspaceDeleteCard, { classNames })
7876
+ ] });
7877
+ }
7151
7878
  export {
7152
7879
  AcceptInvitation,
7153
7880
  ApiKeyDeleteDialog,
@@ -7234,8 +7961,13 @@ export {
7234
7961
  UserView,
7235
7962
  VerifyEmail,
7236
7963
  WorkspaceContext,
7964
+ WorkspaceDeleteCard,
7237
7965
  WorkspaceLogo,
7966
+ WorkspaceLogoCard,
7967
+ WorkspaceNameCard,
7238
7968
  WorkspaceProvider,
7969
+ WorkspaceSettingsCards,
7970
+ WorkspaceSlugCard,
7239
7971
  WorkspaceSwitcher,
7240
7972
  WorkspaceView,
7241
7973
  getUserName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pelatform/starter",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "A collection of SaaS starter kit components and utilities for Pelatform applications.",
5
5
  "author": "Pelatform",
6
6
  "license": "MIT",
File without changes