@studiocubics/cms 0.0.7 → 0.0.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.
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Card as i,ConfirmationForm as t,IdentityDisplay as a,Button as s,InputErrors as o,TextInput as l}from"@studiocubics/components";import m from"./SystemUserDetailsForm.module.css.js";import{initialiseForm as d}from"@studiocubics/utils";import"../../../../../server/clerk/actions/invitations.js";import{systemUserDetailsUpdateAction as c,systemUserProfileImageDeleteAction as n}from"../../../../../server/clerk/actions/systemUsers.js";import"@clerk/nextjs/server";import"../../../../../server/clerk/schemas/invitation.js";import{useActionState as u,useState as f,useRef as v,useCallback as p,useEffect as b}from"react";import{useUser as h}from"@clerk/nextjs";const g=d("firstName","lastName","imageUrl");function N({userId:d,firstName:N,lastName:R,imageUrl:U,hasImage:j,handleClose:k,...y}){const[z,C,L]=u(c.bind(null,d),g),[W,x]=f(U),[F,I]=f(),[w,B]=f(),M=v(null),{user:E}=h(),O=U!==W,q=!O||!W,D=O&&!!W,S=j&&!O,V=p(e=>{const r=e.target.files?.[0];if(r)return B(void 0),r.size>2097152?(B("Image size must be less than 2MB"),void(e.target.value="")):r.type.startsWith("image/")?void I(r):(B("Please select a valid image file"),void(e.target.value=""))},[]),$=p(()=>{W!==U&&(I(void 0),x(U),B(void 0),M.current&&(M.current.value=""))},[W,U]),P=p(async()=>{if(j)try{await n(d),I(void 0),x(void 0),B(void 0),M.current&&(M.current.value=""),d===E?.id&&await(E?.reload())}catch(e){B("Failed to remove image")}},[j,d,E]),T=p(e=>`${(e/1048576).toFixed(2)}MB`,[]);b(()=>(F&&(W&&W.startsWith("blob:")&&URL.revokeObjectURL(W),x(URL.createObjectURL(F))),()=>{W&&W.startsWith("blob:")&&URL.revokeObjectURL(W)}),[F]),b(()=>{z.success&&(d===E?.id&&E?.reload(),k())},[z.success,d,E,k]);const A=F?`Recommended size 1:1, up to 2MB. Currently: ${T(F.size)}`:"Recommended size 1:1, up to 2MB";return e(i,{fullWidth:!0,...y,children:r(t,{formTitle:"Edit Details",onCancel:k,action:C,disabled:L,children:[e(a,{profileImage:W,profileName:r("div",{className:m.formRow,children:[q&&e(s,{type:"button",size:"sm",variant:"outlined",disabled:L,onClick:()=>M.current?.click(),children:"Upload Image"}),e("input",{type:"file",accept:"image/jpeg, image/png",ref:M,name:"imageFile",onChange:V,hidden:!0,disabled:L,"aria-label":"Upload profile image"}),D&&e(s,{type:"button",size:"sm",color:"error",onClick:$,disabled:L,variant:"contained",children:"Remove Selected"}),S&&e(s,{type:"button",size:"sm",color:"error",onClick:P,disabled:L,children:"Remove"})]}),role:A}),w&&e(o,{error:w}),e(o,{error:z.error}),r("div",{className:m.formRow,children:[e(l,{fullWidth:!0,label:"First Name",defaultValue:N??"",name:"firstName",error:z.fieldErrors?.firstName,disabled:L,required:!0}),e(l,{fullWidth:!0,label:"Last Name",defaultValue:R??"",name:"lastName",error:z.fieldErrors?.lastName,disabled:L,required:!0})]})]})})}export{N as SystemUserDetailsForm};
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Card as i,ConfirmationForm as t,IdentityDisplay as a,Button as s,InputErrors as o,TextInput as l}from"@studiocubics/components";import m from"./SystemUserDetailsForm.module.css.js";import{initialiseForm as d}from"@studiocubics/utils";import"../../../../../server/clerk/actions/invitations.js";import{systemUserDetailsUpdateAction as c,systemUserProfileImageDeleteAction as n}from"../../../../../server/clerk/actions/systemUsers.js";import"@clerk/nextjs/server";import"../../../../../server/clerk/schemas/invitation.js";import{useActionState as u,useState as f,useRef as v,useCallback as p,useEffect as b}from"react";import{useUser as h}from"@clerk/nextjs";const g=d("firstName","lastName","imageUrl");function N({userId:d,firstName:N,lastName:R,imageUrl:U,hasImage:j,handleClose:k,...y}){const[z,C,L]=u(c.bind(null,d),g),[W,x]=f(U),[F,I]=f(),[w,B]=f(),M=v(null),{user:E}=h(),O=U!==W,q=!O||!W,D=O&&!!W,S=j&&!O,V=p(e=>{const r=e.target.files?.[0];if(r)return B(void 0),r.size>2097152?(B("Image size must be less than 2MB"),void(e.target.value="")):r.type.startsWith("image/")?void I(r):(B("Please select a valid image file"),void(e.target.value=""))},[]),$=p(()=>{W!==U&&(I(void 0),x(U),B(void 0),M.current&&(M.current.value=""))},[W,U]),P=p(async()=>{if(j)try{await n(d),I(void 0),x(void 0),B(void 0),M.current&&(M.current.value=""),d===E?.id&&await(E?.reload())}catch(e){B("Failed to remove image")}},[j,d,E]),T=p(e=>`${(e/1048576).toFixed(2)}MB`,[]);b(()=>(F&&(W&&W.startsWith("blob:")&&URL.revokeObjectURL(W),x(URL.createObjectURL(F))),()=>{W&&W.startsWith("blob:")&&URL.revokeObjectURL(W)}),[F]),b(()=>{z.success&&(d===E?.id&&E?.reload(),k())},[z.success,d,E,k]);const A=F?`Recommended size 1:1, up to 2MB. Currently: ${T(F.size)}`:"Recommended size 1:1, up to 2MB";return e(i,{fullWidth:!0,...y,children:r(t,{formTitle:"Edit Details",onCancel:k,action:C,disabled:L,size:"sm",children:[e(a,{profileImage:W,profileName:r("div",{className:m.formRow,children:[q&&e(s,{type:"button",size:"sm",variant:"outlined",disabled:L,onClick:()=>M.current?.click(),children:"Upload Image"}),e("input",{type:"file",accept:"image/jpeg, image/png",ref:M,name:"imageFile",onChange:V,hidden:!0,disabled:L,"aria-label":"Upload profile image"}),D&&e(s,{type:"button",size:"sm",color:"error",onClick:$,disabled:L,variant:"contained",children:"Remove Selected"}),S&&e(s,{type:"button",size:"sm",color:"error",onClick:P,disabled:L,children:"Remove"})]}),role:A}),w&&e(o,{error:w}),e(o,{error:z.error}),r("div",{className:m.formRow,children:[e(l,{fullWidth:!0,label:"First Name",defaultValue:N??"",name:"firstName",error:z.fieldErrors?.firstName,disabled:L,required:!0}),e(l,{fullWidth:!0,label:"Last Name",defaultValue:R??"",name:"lastName",error:z.fieldErrors?.lastName,disabled:L,required:!0})]})]})})}export{N as SystemUserDetailsForm};
2
2
  //# sourceMappingURL=SystemUserDetailsForm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SystemUserDetailsForm.js","sources":["../../../../../../src/client/ui/System/SystemUser/SystemUserDetailsForm/SystemUserDetailsForm.tsx"],"sourcesContent":["\"use client\";\n\nimport type { User } from \"@clerk/nextjs/server\";\nimport {\n type CardProps,\n Card,\n ConfirmationForm,\n IdentityDisplay,\n Button,\n TextInput,\n InputErrors,\n} from \"@studiocubics/components\";\nimport styles from \"./SystemUserDetailsForm.module.css\";\nimport { initialiseForm } from \"@studiocubics/utils\";\nimport {\n systemUserDetailsUpdateAction,\n systemUserProfileImageDeleteAction,\n} from \"../../../../../server/clerk/_index\";\nimport { useActionState, useEffect, useRef, useState, useCallback } from \"react\";\nimport { useUser } from \"@clerk/nextjs\";\n\nconst initialSystemUserDetailsUpdateState = initialiseForm(\n \"firstName\",\n \"lastName\",\n \"imageUrl\",\n);\nexport type SystemUserDetailsUpdateState =\n typeof initialSystemUserDetailsUpdateState;\n\nconst MAX_FILE_SIZE_MB = 2;\nconst MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;\n\nexport function SystemUserDetailsForm({\n userId,\n firstName,\n lastName,\n imageUrl,\n hasImage,\n handleClose,\n ...rest\n}: {\n userId: User[\"id\"];\n firstName?: User[\"firstName\"];\n lastName?: User[\"lastName\"];\n imageUrl?: User[\"imageUrl\"];\n hasImage?: User[\"hasImage\"];\n handleClose(): void;\n} & CardProps) {\n const [state, action, pending] = useActionState(\n systemUserDetailsUpdateAction.bind(null, userId),\n initialSystemUserDetailsUpdateState,\n );\n const [imagePreview, setImagePreview] = useState<string | undefined>(\n imageUrl,\n );\n const [inputImage, setInputImage] = useState<File>();\n const [imageError, setImageError] = useState<string>();\n const imageInputRef = useRef<HTMLInputElement | null>(null);\n const { user } = useUser();\n\n const isImageChanged = imageUrl !== imagePreview;\n const showUploadButton = !isImageChanged || !imagePreview;\n const showRemoveSelectedButton = isImageChanged && !!imagePreview;\n const showRemoveButton = hasImage && !isImageChanged;\n\n const handleImageSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n setImageError(undefined);\n\n // Validate file size\n if (file.size > MAX_FILE_SIZE_BYTES) {\n setImageError(`Image size must be less than ${MAX_FILE_SIZE_MB}MB`);\n e.target.value = \"\"; // Reset input\n return;\n }\n\n // Validate file type\n if (!file.type.startsWith(\"image/\")) {\n setImageError(\"Please select a valid image file\");\n e.target.value = \"\"; // Reset input\n return;\n }\n\n setInputImage(file);\n }, []);\n\n const removeSelectedImage = useCallback(() => {\n if (imagePreview === imageUrl) return;\n \n setInputImage(undefined);\n setImagePreview(imageUrl);\n setImageError(undefined);\n \n // Reset file input\n if (imageInputRef.current) {\n imageInputRef.current.value = \"\";\n }\n }, [imagePreview, imageUrl]);\n\n const removeImage = useCallback(async () => {\n if (!hasImage) return;\n \n try {\n await systemUserProfileImageDeleteAction(userId);\n setInputImage(undefined);\n setImagePreview(undefined);\n setImageError(undefined);\n \n // Reset file input\n if (imageInputRef.current) {\n imageInputRef.current.value = \"\";\n }\n \n if (userId === user?.id) {\n await user?.reload();\n }\n } catch (error) {\n setImageError(\"Failed to remove image\");\n }\n }, [hasImage, userId, user]);\n\n const formatFileSize = useCallback((bytes: number): string => {\n return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;\n }, []);\n\n useEffect(() => {\n if (inputImage) {\n // Revoke previous object URL to avoid memory leaks\n if (imagePreview && imagePreview.startsWith(\"blob:\")) {\n URL.revokeObjectURL(imagePreview);\n }\n setImagePreview(URL.createObjectURL(inputImage));\n }\n\n // Cleanup function to revoke object URL on unmount\n return () => {\n if (imagePreview && imagePreview.startsWith(\"blob:\")) {\n URL.revokeObjectURL(imagePreview);\n }\n };\n }, [inputImage]);\n\n useEffect(() => {\n if (state.success) {\n if (userId === user?.id) {\n user?.reload();\n }\n handleClose();\n }\n }, [state.success, userId, user, handleClose]);\n\n const roleText = inputImage\n ? `Recommended size 1:1, up to ${MAX_FILE_SIZE_MB}MB. Currently: ${formatFileSize(inputImage.size)}`\n : `Recommended size 1:1, up to ${MAX_FILE_SIZE_MB}MB`;\n\n return (\n <Card fullWidth {...rest}>\n <ConfirmationForm\n formTitle=\"Edit Details\"\n onCancel={handleClose}\n action={action}\n disabled={pending}\n >\n <IdentityDisplay\n profileImage={imagePreview}\n profileName={\n <div className={styles.formRow}>\n {showUploadButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outlined\"\n disabled={pending}\n onClick={() => imageInputRef.current?.click()}\n >\n Upload Image\n </Button>\n )}\n <input\n type=\"file\"\n accept=\"image/jpeg, image/png\"\n ref={imageInputRef}\n name=\"imageFile\"\n onChange={handleImageSelect}\n hidden\n disabled={pending}\n aria-label=\"Upload profile image\"\n />\n {showRemoveSelectedButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n color=\"error\"\n onClick={removeSelectedImage}\n disabled={pending}\n variant=\"contained\"\n >\n Remove Selected\n </Button>\n )}\n {showRemoveButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n color=\"error\"\n onClick={removeImage}\n disabled={pending}\n >\n Remove\n </Button>\n )}\n </div>\n }\n role={roleText}\n />\n {imageError && <InputErrors error={imageError} />}\n <InputErrors error={state.error} />\n <div className={styles.formRow}>\n <TextInput\n fullWidth\n label=\"First Name\"\n defaultValue={firstName ?? \"\"}\n name=\"firstName\"\n error={state.fieldErrors?.firstName}\n disabled={pending}\n required\n />\n <TextInput\n fullWidth\n label=\"Last Name\"\n defaultValue={lastName ?? \"\"}\n name=\"lastName\"\n error={state.fieldErrors?.lastName}\n disabled={pending}\n required\n />\n </div>\n </ConfirmationForm>\n </Card>\n );\n}"],"names":["initialSystemUserDetailsUpdateState","initialiseForm","SystemUserDetailsForm","userId","firstName","lastName","imageUrl","hasImage","handleClose","rest","state","action","pending","useActionState","systemUserDetailsUpdateAction","bind","imagePreview","setImagePreview","useState","inputImage","setInputImage","imageError","setImageError","imageInputRef","useRef","user","useUser","isImageChanged","showUploadButton","showRemoveSelectedButton","showRemoveButton","handleImageSelect","useCallback","e","file","target","files","undefined","size","MAX_FILE_SIZE_MB","value","type","startsWith","removeSelectedImage","current","removeImage","async","systemUserProfileImageDeleteAction","id","reload","error","formatFileSize","bytes","toFixed","useEffect","URL","revokeObjectURL","createObjectURL","success","roleText","_jsx","Card","fullWidth","children","_jsxs","ConfirmationForm","formTitle","onCancel","disabled","IdentityDisplay","profileImage","profileName","className","styles","formRow","Button","variant","onClick","click","accept","ref","name","onChange","hidden","color","role","InputErrors","TextInput","label","defaultValue","fieldErrors","required"],"mappings":"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"}
1
+ {"version":3,"file":"SystemUserDetailsForm.js","sources":["../../../../../../src/client/ui/System/SystemUser/SystemUserDetailsForm/SystemUserDetailsForm.tsx"],"sourcesContent":["\"use client\";\n\nimport type { User } from \"@clerk/nextjs/server\";\nimport {\n type CardProps,\n Card,\n ConfirmationForm,\n IdentityDisplay,\n Button,\n TextInput,\n InputErrors,\n} from \"@studiocubics/components\";\nimport styles from \"./SystemUserDetailsForm.module.css\";\nimport { initialiseForm } from \"@studiocubics/utils\";\nimport {\n systemUserDetailsUpdateAction,\n systemUserProfileImageDeleteAction,\n} from \"../../../../../server/clerk/_index\";\nimport {\n useActionState,\n useEffect,\n useRef,\n useState,\n useCallback,\n} from \"react\";\nimport { useUser } from \"@clerk/nextjs\";\n\nconst initialSystemUserDetailsUpdateState = initialiseForm(\n \"firstName\",\n \"lastName\",\n \"imageUrl\",\n);\nexport type SystemUserDetailsUpdateState =\n typeof initialSystemUserDetailsUpdateState;\n\nconst MAX_FILE_SIZE_MB = 2;\nconst MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;\n\nexport function SystemUserDetailsForm({\n userId,\n firstName,\n lastName,\n imageUrl,\n hasImage,\n handleClose,\n ...rest\n}: {\n userId: User[\"id\"];\n firstName?: User[\"firstName\"];\n lastName?: User[\"lastName\"];\n imageUrl?: User[\"imageUrl\"];\n hasImage?: User[\"hasImage\"];\n handleClose(): void;\n} & CardProps) {\n const [state, action, pending] = useActionState(\n systemUserDetailsUpdateAction.bind(null, userId),\n initialSystemUserDetailsUpdateState,\n );\n const [imagePreview, setImagePreview] = useState<string | undefined>(\n imageUrl,\n );\n const [inputImage, setInputImage] = useState<File>();\n const [imageError, setImageError] = useState<string>();\n const imageInputRef = useRef<HTMLInputElement | null>(null);\n const { user } = useUser();\n\n const isImageChanged = imageUrl !== imagePreview;\n const showUploadButton = !isImageChanged || !imagePreview;\n const showRemoveSelectedButton = isImageChanged && !!imagePreview;\n const showRemoveButton = hasImage && !isImageChanged;\n\n const handleImageSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n setImageError(undefined);\n\n // Validate file size\n if (file.size > MAX_FILE_SIZE_BYTES) {\n setImageError(`Image size must be less than ${MAX_FILE_SIZE_MB}MB`);\n e.target.value = \"\"; // Reset input\n return;\n }\n\n // Validate file type\n if (!file.type.startsWith(\"image/\")) {\n setImageError(\"Please select a valid image file\");\n e.target.value = \"\"; // Reset input\n return;\n }\n\n setInputImage(file);\n },\n [],\n );\n\n const removeSelectedImage = useCallback(() => {\n if (imagePreview === imageUrl) return;\n\n setInputImage(undefined);\n setImagePreview(imageUrl);\n setImageError(undefined);\n\n // Reset file input\n if (imageInputRef.current) {\n imageInputRef.current.value = \"\";\n }\n }, [imagePreview, imageUrl]);\n\n const removeImage = useCallback(async () => {\n if (!hasImage) return;\n\n try {\n await systemUserProfileImageDeleteAction(userId);\n setInputImage(undefined);\n setImagePreview(undefined);\n setImageError(undefined);\n\n // Reset file input\n if (imageInputRef.current) {\n imageInputRef.current.value = \"\";\n }\n\n if (userId === user?.id) {\n await user?.reload();\n }\n } catch (error) {\n setImageError(\"Failed to remove image\");\n }\n }, [hasImage, userId, user]);\n\n const formatFileSize = useCallback((bytes: number): string => {\n return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;\n }, []);\n\n useEffect(() => {\n if (inputImage) {\n // Revoke previous object URL to avoid memory leaks\n if (imagePreview && imagePreview.startsWith(\"blob:\")) {\n URL.revokeObjectURL(imagePreview);\n }\n setImagePreview(URL.createObjectURL(inputImage));\n }\n\n // Cleanup function to revoke object URL on unmount\n return () => {\n if (imagePreview && imagePreview.startsWith(\"blob:\")) {\n URL.revokeObjectURL(imagePreview);\n }\n };\n }, [inputImage]);\n\n useEffect(() => {\n if (state.success) {\n if (userId === user?.id) {\n user?.reload();\n }\n handleClose();\n }\n }, [state.success, userId, user, handleClose]);\n\n const roleText = inputImage\n ? `Recommended size 1:1, up to ${MAX_FILE_SIZE_MB}MB. Currently: ${formatFileSize(inputImage.size)}`\n : `Recommended size 1:1, up to ${MAX_FILE_SIZE_MB}MB`;\n\n return (\n <Card fullWidth {...rest}>\n <ConfirmationForm\n formTitle=\"Edit Details\"\n onCancel={handleClose}\n action={action}\n disabled={pending}\n size=\"sm\"\n >\n <IdentityDisplay\n profileImage={imagePreview}\n profileName={\n <div className={styles.formRow}>\n {showUploadButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outlined\"\n disabled={pending}\n onClick={() => imageInputRef.current?.click()}\n >\n Upload Image\n </Button>\n )}\n <input\n type=\"file\"\n accept=\"image/jpeg, image/png\"\n ref={imageInputRef}\n name=\"imageFile\"\n onChange={handleImageSelect}\n hidden\n disabled={pending}\n aria-label=\"Upload profile image\"\n />\n {showRemoveSelectedButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n color=\"error\"\n onClick={removeSelectedImage}\n disabled={pending}\n variant=\"contained\"\n >\n Remove Selected\n </Button>\n )}\n {showRemoveButton && (\n <Button\n type=\"button\"\n size=\"sm\"\n color=\"error\"\n onClick={removeImage}\n disabled={pending}\n >\n Remove\n </Button>\n )}\n </div>\n }\n role={roleText}\n />\n {imageError && <InputErrors error={imageError} />}\n <InputErrors error={state.error} />\n <div className={styles.formRow}>\n <TextInput\n fullWidth\n label=\"First Name\"\n defaultValue={firstName ?? \"\"}\n name=\"firstName\"\n error={state.fieldErrors?.firstName}\n disabled={pending}\n required\n />\n <TextInput\n fullWidth\n label=\"Last Name\"\n defaultValue={lastName ?? \"\"}\n name=\"lastName\"\n error={state.fieldErrors?.lastName}\n disabled={pending}\n required\n />\n </div>\n </ConfirmationForm>\n </Card>\n );\n}\n"],"names":["initialSystemUserDetailsUpdateState","initialiseForm","SystemUserDetailsForm","userId","firstName","lastName","imageUrl","hasImage","handleClose","rest","state","action","pending","useActionState","systemUserDetailsUpdateAction","bind","imagePreview","setImagePreview","useState","inputImage","setInputImage","imageError","setImageError","imageInputRef","useRef","user","useUser","isImageChanged","showUploadButton","showRemoveSelectedButton","showRemoveButton","handleImageSelect","useCallback","e","file","target","files","undefined","size","MAX_FILE_SIZE_MB","value","type","startsWith","removeSelectedImage","current","removeImage","async","systemUserProfileImageDeleteAction","id","reload","error","formatFileSize","bytes","toFixed","useEffect","URL","revokeObjectURL","createObjectURL","success","roleText","_jsx","Card","fullWidth","children","_jsxs","ConfirmationForm","formTitle","onCancel","disabled","IdentityDisplay","profileImage","profileName","className","styles","formRow","Button","variant","onClick","click","accept","ref","name","onChange","hidden","color","role","InputErrors","TextInput","label","defaultValue","fieldErrors","required"],"mappings":"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"}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "access": "public"
6
6
  },
7
7
  "private": false,
8
- "version": "0.0.7",
8
+ "version": "0.0.9",
9
9
  "keywords": [
10
10
  "@studiocubics",
11
11
  "cubics",
@@ -37,10 +37,10 @@
37
37
  "lucide-react": "^0.554.0",
38
38
  "next-themes": "^0.4.6",
39
39
  "zod": "^4.3.6",
40
- "@studiocubics/components": "^0.0.7",
41
- "@studiocubics/hooks": "^0.0.7",
42
- "@studiocubics/next": "^0.0.7",
43
- "@studiocubics/utils": "^0.0.7"
40
+ "@studiocubics/components": "^0.0.9",
41
+ "@studiocubics/hooks": "^0.0.9",
42
+ "@studiocubics/next": "^0.0.9",
43
+ "@studiocubics/utils": "^0.0.9"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@eslint/js": "^9.39.1",
@@ -61,7 +61,7 @@
61
61
  "rollup-plugin-bundle-stats": "^4.21.9",
62
62
  "typescript": "^5.9.3",
63
63
  "typescript-eslint": "^8.46.4",
64
- "@studiocubics/types": "^0.0.7"
64
+ "@studiocubics/types": "^0.0.9"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@clerk/nextjs": ">= 6",