From 7443efd84a39dfe69d3ea6e3f54255fb445ef451 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Tue, 14 May 2024 03:29:21 +0530 Subject: [PATCH 01/79] reply feature for doctor notes --- .../ConsultationDoctorNotes/index.tsx | 71 ++++++++++-------- src/Components/Facility/DoctorNote.tsx | 27 ++++--- .../Facility/DoctorNoteReplyPreviewCard.tsx | 64 +++++++++++++++++ .../Facility/PatientConsultationNotesList.tsx | 12 +++- src/Components/Facility/PatientNoteCard.tsx | 37 ++++++---- src/Components/Facility/PatientNotesList.tsx | 10 ++- .../Facility/PatientNotesSlideover.tsx | 72 +++++++++++-------- src/Components/Facility/models.tsx | 1 + src/Components/Patient/PatientNotes.tsx | 61 +++++++++------- src/Redux/api.tsx | 4 +- 10 files changed, 247 insertions(+), 112 deletions(-) create mode 100644 src/Components/Facility/DoctorNoteReplyPreviewCard.tsx diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx index 522ad168b8..8854a0daf5 100644 --- a/src/Components/Facility/ConsultationDoctorNotes/index.tsx +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -6,7 +6,7 @@ import CareIcon from "../../../CAREUI/icons/CareIcon"; import { NonReadOnlyUsers } from "../../../Utils/AuthorizeFor"; import { useMessageListener } from "../../../Common/hooks/useMessageListener"; import PatientConsultationNotesList from "../PatientConsultationNotesList.js"; -import { PatientNoteStateType } from "../models.js"; +import { PatientNoteStateType, PatientNotesModel } from "../models.js"; import routes from "../../../Redux/api.js"; import request from "../../../Utils/request/request.js"; import useQuery from "../../../Utils/request/useQuery.js"; @@ -15,6 +15,7 @@ import { classNames, isAppleDevice } from "../../../Utils/utils.js"; import AutoExpandingTextInputFormField from "../../Form/FormFields/AutoExpandingTextInputFormField.js"; import { PATIENT_NOTES_THREADS } from "../../../Common/constants.js"; import useAuthUser from "../../../Common/hooks/useAuthUser.js"; +import DoctorNoteReplyPreviewCard from "../DoctorNoteReplyPreviewCard.js"; interface ConsultationDoctorNotesProps { patientId: string; @@ -38,6 +39,9 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); const [focused, setFocused] = useState(false); + const [reply_to, setReplyTo] = useState( + undefined, + ); const initialData: PatientNoteStateType = { notes: [], @@ -64,6 +68,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { note: noteField, thread, consultation: consultationId, + reply_to: reply_to?.id, }, }); @@ -72,6 +77,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { setState({ ...state, cPage: 1 }); setNoteField(""); setReload(true); + setReplyTo(undefined); } }; @@ -148,36 +154,41 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { reload={reload} setReload={setReload} thread={thread} + setReplyTo={setReplyTo} /> - -
- setNoteField(e.value)} - className="w-full grow" - innerClassName="pr-10" - errorClassName="hidden" - placeholder="Type your Note" - disabled={!patientActive} - onFocus={() => setFocused(true)} - onBlur={() => setFocused(false)} - /> - - - -
+ setReplyTo(undefined)} + > +
+ setNoteField(e.value)} + className="w-full grow" + innerClassName="pr-10" + errorClassName="hidden" + placeholder="Type your Note" + disabled={!patientActive} + onFocus={() => setFocused(true)} + onBlur={() => setFocused(false)} + /> + + + +
+
); diff --git a/src/Components/Facility/DoctorNote.tsx b/src/Components/Facility/DoctorNote.tsx index b70ccfdf51..bf2fb97159 100644 --- a/src/Components/Facility/DoctorNote.tsx +++ b/src/Components/Facility/DoctorNote.tsx @@ -1,17 +1,19 @@ import InfiniteScroll from "react-infinite-scroll-component"; import CircularProgress from "../Common/components/CircularProgress"; import PatientNoteCard from "./PatientNoteCard"; -import { PatientNoteStateType } from "./models"; +import { PatientNoteStateType, PatientNotesModel } from "./models"; +import DoctorNoteReplyPreviewCard from "./DoctorNoteReplyPreviewCard"; interface DoctorNoteProps { state: PatientNoteStateType; setReload: any; handleNext: () => void; disableEdit?: boolean; + setReplyTo?: (reply_to: PatientNotesModel | undefined) => void; } const DoctorNote = (props: DoctorNoteProps) => { - const { state, handleNext, setReload, disableEdit } = props; + const { state, handleNext, setReload, disableEdit, setReplyTo } = props; return (
{ dataLength={state.notes.length} scrollableTarget="patient-notes-list" > - {state.notes.map((note) => ( - - ))} + {state.notes.map((note) => { + const parentNote = state.notes.find((n) => n.id === note.reply_to); + return ( + + + + ); + })} ) : (
diff --git a/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx b/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx new file mode 100644 index 0000000000..cb0368b408 --- /dev/null +++ b/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx @@ -0,0 +1,64 @@ +import React from "react"; +import { PatientNotesModel } from "./models"; +import { USER_TYPES_MAP } from "../../Common/constants"; +import { formatDateTime, relativeDate } from "../../Utils/utils"; + +interface Props { + parentNote: PatientNotesModel | undefined; + children: React.ReactNode; + cancelReply?: () => void; +} + +const DoctorNoteReplyPreviewCard = ({ + parentNote, + children, + cancelReply, +}: Props) => { + return ( +
+ {parentNote ? ( +
+
+
+
+
+ + {parentNote.created_by_object?.first_name || "Unknown"}{" "} + {parentNote.created_by_object?.last_name} + + {parentNote.user_type && ( + + {`(${USER_TYPES_MAP[parentNote.user_type]})`} + + )} +
+
+
+ + {formatDateTime(parentNote.created_date)} + + Created {relativeDate(parentNote.created_date, true)} +
+
+
+ {cancelReply && ( +
+ Cancel +
+ )} +
+
{parentNote.note}
+
+
{children}
+
+ ) : ( +
{children}
+ )} +
+ ); +}; + +export default DoctorNoteReplyPreviewCard; diff --git a/src/Components/Facility/PatientConsultationNotesList.tsx b/src/Components/Facility/PatientConsultationNotesList.tsx index e7e0bb2550..99d9b1cd34 100644 --- a/src/Components/Facility/PatientConsultationNotesList.tsx +++ b/src/Components/Facility/PatientConsultationNotesList.tsx @@ -14,12 +14,21 @@ interface PatientNotesProps { setReload?: (value: boolean) => void; disableEdit?: boolean; thread: PatientNotesModel["thread"]; + setReplyTo?: (value: PatientNotesModel | undefined) => void; } const pageSize = RESULTS_PER_PAGE_LIMIT; const PatientConsultationNotesList = (props: PatientNotesProps) => { - const { state, setState, reload, setReload, disableEdit, thread } = props; + const { + state, + setState, + reload, + setReload, + disableEdit, + thread, + setReplyTo, + } = props; const consultationId = useSlug("consultation") ?? ""; const [isLoading, setIsLoading] = useState(true); @@ -94,6 +103,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { handleNext={handleNext} setReload={setReload} disableEdit={disableEdit} + setReplyTo={setReplyTo} /> ); }; diff --git a/src/Components/Facility/PatientNoteCard.tsx b/src/Components/Facility/PatientNoteCard.tsx index 5ea41cfb04..5a31359577 100644 --- a/src/Components/Facility/PatientNoteCard.tsx +++ b/src/Components/Facility/PatientNoteCard.tsx @@ -18,10 +18,12 @@ const PatientNoteCard = ({ note, setReload, disableEdit, + setReplyTo, }: { note: PatientNotesModel; setReload: any; disableEdit?: boolean; + setReplyTo?: (reply_to: PatientNotesModel | undefined) => void; }) => { const patientId = useSlug("patient"); const [isEditing, setIsEditing] = useState(false); @@ -124,19 +126,28 @@ const PatientNoteCard = ({ ) }
- - {!disableEdit && - note.created_by_object.id === authUser.id && - !isEditing && ( - { - setIsEditing(true); - }} - > - - - )} +
+ {!disableEdit && + note.created_by_object.id === authUser.id && + !isEditing && ( + { + setIsEditing(true); + }} + > + + + )} + { + setReplyTo && setReplyTo(note); + }} + > + + +
{
diff --git a/src/Components/Facility/PatientNotesList.tsx b/src/Components/Facility/PatientNotesList.tsx index 9585ace5db..e1d801806f 100644 --- a/src/Components/Facility/PatientNotesList.tsx +++ b/src/Components/Facility/PatientNotesList.tsx @@ -14,12 +14,13 @@ interface PatientNotesProps { reload?: boolean; setReload?: any; thread: PatientNotesModel["thread"]; + setReplyTo?: (reply_to: PatientNotesModel | undefined) => void; } const pageSize = RESULTS_PER_PAGE_LIMIT; const PatientNotesList = (props: PatientNotesProps) => { - const { state, setState, reload, setReload, thread } = props; + const { state, setState, reload, setReload, thread, setReplyTo } = props; const [isLoading, setIsLoading] = useState(true); @@ -83,7 +84,12 @@ const PatientNotesList = (props: PatientNotesProps) => { } return ( - + ); }; diff --git a/src/Components/Facility/PatientNotesSlideover.tsx b/src/Components/Facility/PatientNotesSlideover.tsx index 3fd46f92f5..2f7b8a8e4c 100644 --- a/src/Components/Facility/PatientNotesSlideover.tsx +++ b/src/Components/Facility/PatientNotesSlideover.tsx @@ -9,12 +9,13 @@ import { useMessageListener } from "../../Common/hooks/useMessageListener"; import PatientConsultationNotesList from "./PatientConsultationNotesList"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; -import { PatientNoteStateType } from "./models"; +import { PatientNoteStateType, PatientNotesModel } from "./models"; import useKeyboardShortcut from "use-keyboard-shortcut"; import AutoExpandingTextInputFormField from "../Form/FormFields/AutoExpandingTextInputFormField.js"; import * as Sentry from "@sentry/browser"; import useAuthUser from "../../Common/hooks/useAuthUser"; import { PATIENT_NOTES_THREADS } from "../../Common/constants.js"; +import DoctorNoteReplyPreviewCard from "./DoctorNoteReplyPreviewCard.js"; interface PatientNotesProps { patientId: string; @@ -34,6 +35,9 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { const [patientActive, setPatientActive] = useState(true); const [reload, setReload] = useState(false); const [focused, setFocused] = useState(false); + const [reply_to, setReplyTo] = useState( + undefined, + ); const { username } = useAuthUser(); @@ -92,6 +96,7 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { note: noteField, consultation: consultationId, thread, + reply_to: reply_to?.id, }, }); if (res?.status === 201) { @@ -99,6 +104,7 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { setNoteField(""); setState({ ...state, cPage: 1 }); setReload(true); + setReplyTo(undefined); } }; @@ -233,36 +239,42 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { setReload={setReload} disableEdit={!patientActive} thread={thread} + setReplyTo={setReplyTo} /> -
- setNoteField(e.value)} - className="w-full grow" - errorClassName="hidden" - innerClassName="pr-10" - placeholder="Type your Note" - disabled={!patientActive} - onFocus={() => setFocused(true)} - onBlur={() => setFocused(false)} - /> - - - -
+ setReplyTo(undefined)} + > +
+ setNoteField(e.value)} + className="w-full grow" + errorClassName="hidden" + innerClassName="pr-10" + placeholder="Type your Note" + disabled={!patientActive} + onFocus={() => setFocused(true)} + onBlur={() => setFocused(false)} + /> + + + +
+
)} diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index d61d5a9f12..67dc495028 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -517,6 +517,7 @@ export interface PatientNotesModel { created_date: string; last_edited_by?: BaseUserModel; last_edited_date?: string; + reply_to?: string; } export interface PatientNoteStateType { diff --git a/src/Components/Patient/PatientNotes.tsx b/src/Components/Patient/PatientNotes.tsx index 520486620b..b170633941 100644 --- a/src/Components/Patient/PatientNotes.tsx +++ b/src/Components/Patient/PatientNotes.tsx @@ -7,12 +7,13 @@ import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor"; import PatientNotesList from "../Facility/PatientNotesList"; import Page from "../Common/components/Page"; import { useMessageListener } from "../../Common/hooks/useMessageListener"; -import { PatientNoteStateType } from "../Facility/models"; +import { PatientNoteStateType, PatientNotesModel } from "../Facility/models"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; import { PATIENT_NOTES_THREADS } from "../../Common/constants.js"; import useAuthUser from "../../Common/hooks/useAuthUser.js"; import { classNames } from "../../Utils/utils.js"; +import DoctorNoteReplyPreviewCard from "../Facility/DoctorNoteReplyPreviewCard.js"; interface PatientNotesProps { patientId: any; @@ -34,6 +35,9 @@ const PatientNotes = (props: PatientNotesProps) => { const [reload, setReload] = useState(false); const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); + const [reply_to, setReplyTo] = useState( + undefined, + ); const initialData: PatientNoteStateType = { notes: [], @@ -55,6 +59,7 @@ const PatientNotes = (props: PatientNotesProps) => { body: { note: noteField, thread, + reply_to: reply_to?.id, }, }); if (res?.status === 201) { @@ -62,6 +67,7 @@ const PatientNotes = (props: PatientNotesProps) => { setNoteField(""); setReload(!reload); setState({ ...state, cPage: 1 }); + setReplyTo(undefined); } }; @@ -133,31 +139,36 @@ const PatientNotes = (props: PatientNotesProps) => { reload={reload} setReload={setReload} thread={thread} + setReplyTo={setReplyTo} /> - -
- setNoteField(e.value)} - className="grow" - type="text" - errorClassName="hidden" - placeholder="Type your Note" - disabled={!patientActive} - /> - - - -
+ setReplyTo(undefined)} + > +
+ setNoteField(e.value)} + className="grow" + type="text" + errorClassName="hidden" + placeholder="Type your Note" + disabled={!patientActive} + /> + + + +
+
); diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 82ae52f26a..b46425f185 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -754,7 +754,9 @@ const routes = { method: "POST", TRes: Type(), TBody: Type< - Pick & { consultation?: string } + Pick & { + consultation?: string; + } >(), }, updatePatientNote: { From 3128fd7943b84ce91364a9acc46b3e218f7c1674 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Wed, 15 May 2024 20:55:44 +0530 Subject: [PATCH 02/79] code reviews --- .../ConsultationDoctorNotes/index.tsx | 4 +-- src/Components/Facility/DoctorNote.tsx | 26 +++++++++---------- .../Facility/DoctorNoteReplyPreviewCard.tsx | 4 +-- .../Facility/PatientNotesSlideover.tsx | 4 +-- src/Components/Facility/models.tsx | 10 ++++++- src/Redux/api.tsx | 3 ++- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx index 8854a0daf5..bac946e90e 100644 --- a/src/Components/Facility/ConsultationDoctorNotes/index.tsx +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -6,7 +6,7 @@ import CareIcon from "../../../CAREUI/icons/CareIcon"; import { NonReadOnlyUsers } from "../../../Utils/AuthorizeFor"; import { useMessageListener } from "../../../Common/hooks/useMessageListener"; import PatientConsultationNotesList from "../PatientConsultationNotesList.js"; -import { PatientNoteStateType, PatientNotesModel } from "../models.js"; +import { PatientNoteStateType, PaitentNotesReplyModel } from "../models.js"; import routes from "../../../Redux/api.js"; import request from "../../../Utils/request/request.js"; import useQuery from "../../../Utils/request/useQuery.js"; @@ -39,7 +39,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { const [facilityName, setFacilityName] = useState(""); const [patientName, setPatientName] = useState(""); const [focused, setFocused] = useState(false); - const [reply_to, setReplyTo] = useState( + const [reply_to, setReplyTo] = useState( undefined, ); diff --git a/src/Components/Facility/DoctorNote.tsx b/src/Components/Facility/DoctorNote.tsx index bf2fb97159..01d16dca38 100644 --- a/src/Components/Facility/DoctorNote.tsx +++ b/src/Components/Facility/DoctorNote.tsx @@ -34,19 +34,19 @@ const DoctorNote = (props: DoctorNoteProps) => { dataLength={state.notes.length} scrollableTarget="patient-notes-list" > - {state.notes.map((note) => { - const parentNote = state.notes.find((n) => n.id === note.reply_to); - return ( - - - - ); - })} + {state.notes.map((note) => ( + + + + ))} ) : (
diff --git a/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx b/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx index cb0368b408..470f05f2bf 100644 --- a/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx +++ b/src/Components/Facility/DoctorNoteReplyPreviewCard.tsx @@ -1,10 +1,10 @@ import React from "react"; -import { PatientNotesModel } from "./models"; +import { PaitentNotesReplyModel } from "./models"; import { USER_TYPES_MAP } from "../../Common/constants"; import { formatDateTime, relativeDate } from "../../Utils/utils"; interface Props { - parentNote: PatientNotesModel | undefined; + parentNote: PaitentNotesReplyModel | undefined; children: React.ReactNode; cancelReply?: () => void; } diff --git a/src/Components/Facility/PatientNotesSlideover.tsx b/src/Components/Facility/PatientNotesSlideover.tsx index 2f7b8a8e4c..bfac0905ca 100644 --- a/src/Components/Facility/PatientNotesSlideover.tsx +++ b/src/Components/Facility/PatientNotesSlideover.tsx @@ -9,7 +9,7 @@ import { useMessageListener } from "../../Common/hooks/useMessageListener"; import PatientConsultationNotesList from "./PatientConsultationNotesList"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; -import { PatientNoteStateType, PatientNotesModel } from "./models"; +import { PatientNoteStateType, PaitentNotesReplyModel } from "./models"; import useKeyboardShortcut from "use-keyboard-shortcut"; import AutoExpandingTextInputFormField from "../Form/FormFields/AutoExpandingTextInputFormField.js"; import * as Sentry from "@sentry/browser"; @@ -35,7 +35,7 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { const [patientActive, setPatientActive] = useState(true); const [reload, setReload] = useState(false); const [focused, setFocused] = useState(false); - const [reply_to, setReplyTo] = useState( + const [reply_to, setReplyTo] = useState( undefined, ); diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 67dc495028..82631da7dd 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -507,6 +507,14 @@ export interface PatientNotesEditModel { note: string; } +export interface PaitentNotesReplyModel { + id: string; + note: string; + user_type?: UserRole | "RemoteSpecialist"; + created_by_object: BaseUserModel; + created_date: string; +} + export interface PatientNotesModel { id: string; note: string; @@ -517,7 +525,7 @@ export interface PatientNotesModel { created_date: string; last_edited_by?: BaseUserModel; last_edited_date?: string; - reply_to?: string; + reply_to?: PaitentNotesReplyModel; } export interface PatientNoteStateType { diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index b46425f185..96dca95b27 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -754,8 +754,9 @@ const routes = { method: "POST", TRes: Type(), TBody: Type< - Pick & { + Pick & { consultation?: string; + reply_to?: string; } >(), }, From 51edb8d22679ce6c6192ba3edaa612fbe2aad0bc Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Thu, 16 May 2024 13:54:58 +0530 Subject: [PATCH 03/79] code review --- src/Components/Facility/DoctorNote.tsx | 2 +- src/Components/Facility/models.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Facility/DoctorNote.tsx b/src/Components/Facility/DoctorNote.tsx index 01d16dca38..d388fcfb86 100644 --- a/src/Components/Facility/DoctorNote.tsx +++ b/src/Components/Facility/DoctorNote.tsx @@ -37,7 +37,7 @@ const DoctorNote = (props: DoctorNoteProps) => { {state.notes.map((note) => ( Date: Fri, 7 Jun 2024 12:20:55 +0530 Subject: [PATCH 04/79] profile picture feature --- .../Users/ProfilePicUploadModal.tsx | 452 ++++++++++++++++++ src/Components/Users/UserProfile.tsx | 49 +- src/Components/Users/models.tsx | 1 + src/Redux/api.tsx | 13 + 4 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 src/Components/Users/ProfilePicUploadModal.tsx diff --git a/src/Components/Users/ProfilePicUploadModal.tsx b/src/Components/Users/ProfilePicUploadModal.tsx new file mode 100644 index 0000000000..8ac60c7ec0 --- /dev/null +++ b/src/Components/Users/ProfilePicUploadModal.tsx @@ -0,0 +1,452 @@ +import { + ChangeEventHandler, + useCallback, + useEffect, + useRef, + useState, +} from "react"; +import { Success } from "../../Utils/Notifications"; +import useDragAndDrop from "../../Utils/useDragAndDrop"; +import { sleep } from "../../Utils/utils"; +import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; +import Webcam from "react-webcam"; +import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import * as Notification from "../../Utils/Notifications.js"; +import { useTranslation } from "react-i18next"; +import { LocalStorageKeys } from "../../Common/constants"; +import DialogModal from "../Common/Dialog"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import uploadFile from "../../Utils/request/uploadFile"; +import { UserModel } from "./models"; +interface Props { + open: boolean; + onClose: (() => void) | undefined; + onSave?: (() => void) | undefined; + onDelete?: (() => void) | undefined; + user: UserModel; +} + +const ProfilePicUploadModal = ({ + open, + onClose, + onSave, + onDelete, + user, +}: Props) => { + const [isUploading, setIsUploading] = useState(false); + const [selectedFile, setSelectedFile] = useState(); + const [preview, setPreview] = useState(); + const [isCameraOpen, setIsCameraOpen] = useState(false); + const webRef = useRef(null); + const [previewImage, setPreviewImage] = useState(null); + const [isCaptureImgBeingUploaded, setIsCaptureImgBeingUploaded] = + useState(false); + const FACING_MODE_USER = "user"; + const FACING_MODE_ENVIRONMENT = { exact: "environment" }; + const [facingMode, setFacingMode] = useState(FACING_MODE_USER); + const videoConstraints = { + width: 1280, + height: 720, + facingMode: "user", + }; + const { width } = useWindowDimensions(); + const LaptopScreenBreakpoint = 640; + const isLaptopScreen = width >= LaptopScreenBreakpoint; + const { t } = useTranslation(); + const handleSwitchCamera = useCallback(() => { + setFacingMode((prevState: any) => + prevState === FACING_MODE_USER + ? FACING_MODE_ENVIRONMENT + : FACING_MODE_USER, + ); + }, []); + + const captureImage = () => { + setPreviewImage(webRef.current.getScreenshot()); + const canvas = webRef.current.getCanvas(); + canvas?.toBlob((blob: Blob) => { + const myFile = new File([blob], "image.png", { + type: blob.type, + }); + setSelectedFile(myFile); + }); + }; + const closeModal = () => { + setPreview(undefined); + setSelectedFile(undefined); + onClose?.(); + }; + + useEffect(() => { + if (selectedFile) { + const objectUrl = URL.createObjectURL(selectedFile); + setPreview(objectUrl); + return () => URL.revokeObjectURL(objectUrl); + } + }, [selectedFile]); + + const onSelectFile: ChangeEventHandler = (e) => { + if (!e.target.files || e.target.files.length === 0) { + setSelectedFile(undefined); + return; + } + setSelectedFile(e.target.files[0]); + }; + + const handleUpload = async () => { + setIsCaptureImgBeingUploaded(true); + if (!selectedFile) { + setIsCaptureImgBeingUploaded(false); + closeModal(); + return; + } + + const formData = new FormData(); + formData.append("profile_picture_url", selectedFile); + const url = `/api/v1/users/${user.username}/profile_picture/`; + setIsUploading(true); + + uploadFile( + url, + formData, + "POST", + { + Authorization: + "Bearer " + localStorage.getItem(LocalStorageKeys.accessToken), + }, + (xhr: XMLHttpRequest) => { + if (xhr.status === 200) { + Success({ msg: "Profile Picture updated." }); + } else { + Notification.Error({ + msg: "Something went wrong!", + }); + setIsUploading(false); + } + }, + null, + () => { + Notification.Error({ + msg: "Network Failure. Please check your internet connectivity.", + }); + setIsUploading(false); + }, + ); + + await sleep(1000); + setIsUploading(false); + setIsCaptureImgBeingUploaded(false); + onSave && onSave(); + closeModal(); + }; + + const handleDelete = async () => { + const { res } = await request(routes.deleteProfilePicture, { + pathParams: { id: user.id }, + }); + if (res?.ok) { + Success({ msg: "Profile picture deleted" }); + onDelete?.(); + closeModal(); + } + }; + + const hasImage = !!(preview || user.read_profile_picture_url); + const imgSrc = + preview || `${user.read_profile_picture_url}?requested_on=${Date.now()}`; + + const dragProps = useDragAndDrop(); + const onDrop = (e: React.DragEvent) => { + e.preventDefault(); + dragProps.setDragOver(false); + const dropedFile = e?.dataTransfer?.files[0]; + if (dropedFile.type.split("/")[0] !== "image") + return dragProps.setFileDropError("Please drop an image file to upload!"); + setSelectedFile(dropedFile); + }; + const commonHint = ( + <> + {t("max_size_for_image_uploaded_should_be")} 1mb. +
+ {t("allowed_formats_are")} jpg,png,jpeg. + {t("recommended_aspect_ratio_for")} user profile image is 1:1 + + ); + + return ( + +
+ {!isCameraOpen ? ( +
+ {hasImage ? ( + <> +
+ profile-pic +
+

+ {commonHint} +

+ + ) : ( +
+ +

+ {dragProps.fileDropError !== "" + ? dragProps.fileDropError + : `${t("drag_drop_image_to_upload")}`} +

+

+ No Profile image uploaded yet. {commonHint} +

+
+ )} + +
+
+ +
+
+ { + setIsCameraOpen(true); + }} + > + {`${t("open")} ${t("camera")}`} + + { + e.stopPropagation(); + closeModal(); + dragProps.setFileDropError(""); + }} + disabled={isUploading} + /> + {user.read_profile_picture_url && ( + + {t("delete")} + + )} + + {isUploading ? ( + + ) : ( + + )} + + {isUploading ? `${t("uploading")}...` : `${t("save")}`} + + +
+ + ) : ( +
+
+ {!previewImage ? ( + <> + + + ) : ( + <> + + + )} +
+ {/* buttons for mobile screens */} +
+
+ {!previewImage ? ( + + {t("switch")} + + ) : ( + <> + )} +
+
+ {!previewImage ? ( + <> +
+ { + captureImage(); + }} + className="my-2 w-full" + > + {t("capture")} + +
+ + ) : ( + <> +
+ { + setPreviewImage(null); + }} + className="my-2 w-full" + disabled={isUploading} + > + {t("retake")} + + + {isCaptureImgBeingUploaded && ( + + )} + {t("submit")} + +
+ + )} +
+
+ { + setPreviewImage(null); + setIsCameraOpen(false); + webRef.current.stopCamera(); + }} + className="border-grey-200 my-2 w-full border-2" + > + {t("close")} + +
+
+ {/* buttons for laptop screens */} + + )} +
+ + ); +}; + +export default ProfilePicUploadModal; diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index 50dbc5890c..e9f7e925fc 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -16,7 +16,12 @@ import CareIcon from "../../CAREUI/icons/CareIcon"; import PhoneNumberFormField from "../Form/FormFields/PhoneNumberFormField"; import { FieldChangeEvent } from "../Form/FormFields/Utils"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; -import { GenderType, SkillModel, UpdatePasswordForm } from "../Users/models"; +import { + GenderType, + SkillModel, + UpdatePasswordForm, + UserModel, +} from "../Users/models"; import UpdatableApp, { checkForUpdate } from "../Common/UpdatableApp"; import dayjs from "../../Utils/dayjs"; import useAuthUser, { useAuthContext } from "../../Common/hooks/useAuthUser"; @@ -26,6 +31,7 @@ import routes from "../../Redux/api"; import request from "../../Utils/request/request"; import DateFormField from "../Form/FormFields/DateFormField"; import { validateRule } from "./UserAdd"; +import ProfilePicUploadModal from "./ProfilePicUploadModal"; const Loading = lazy(() => import("../Common/Loading")); type EditForm = { @@ -112,6 +118,8 @@ const editFormReducer = (state: State, action: Action) => { export default function UserProfile() { const { signOut } = useAuthContext(); const [states, dispatch] = useReducer(editFormReducer, initialState); + const [editProfilePic, setEditProfilePic] = useState(false); + const [imageKey, setImageKey] = useState(Date.now()); const [updateStatus, setUpdateStatus] = useState({ isChecking: false, isUpdateAvailable: false, @@ -452,6 +460,17 @@ export default function UserProfile() { }; return (
+ + userData?.read_profile_picture_url + ? setImageKey(Date.now()) + : refetchUserData() + } + onClose={() => setEditProfilePic(false)} + onDelete={() => refetchUserData()} + user={userData ?? ({} as UserModel)} + />
@@ -462,6 +481,34 @@ export default function UserProfile() {

Local Body, District and State are Non Editable Settings.

+
+
setEditProfilePic(!editProfilePic)} + > + +
+ + {`${userData?.read_profile_picture_url ? "Edit" : "Upload"}`} +
+
+
+

+ {userData?.first_name} {userData?.last_name} +

+

+ @{userData?.username} +

+
+
setShowEdit(!showEdit)} diff --git a/src/Components/Users/models.tsx b/src/Components/Users/models.tsx index 1bbe494b9e..3dbb637e11 100644 --- a/src/Components/Users/models.tsx +++ b/src/Components/Users/models.tsx @@ -32,6 +32,7 @@ export type UserModel = UserBareMinimum & { phone_number?: string; alt_phone_number?: string; gender?: GenderType; + read_profile_picture_url?: string; date_of_birth: Date | null | string; is_superuser?: boolean; verified?: boolean; diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 439b122ca0..007d7e30b5 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -301,6 +301,19 @@ const routes = { TBody: Type>(), }, + updateProfilePicture: { + path: "/api/v1/users/{username}/profile_picture/", + method: "PATCH", + TRes: Type(), + TBody: Type<{ profile_picture_url: string }>(), + }, + + deleteProfilePicture: { + path: "/api/v1/users/{username}/profile_picture/", + method: "DELETE", + TRes: Type(), + }, + deleteUser: { path: "/api/v1/users/{username}/", method: "DELETE", From 7abc974f1c1725e150cacca8852bdfd65ed35137 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sat, 8 Jun 2024 11:05:49 +0530 Subject: [PATCH 05/79] bug fix --- src/Components/Users/ProfilePicUploadModal.tsx | 2 +- src/Components/Users/UserProfile.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Users/ProfilePicUploadModal.tsx b/src/Components/Users/ProfilePicUploadModal.tsx index 8ac60c7ec0..869ba3b280 100644 --- a/src/Components/Users/ProfilePicUploadModal.tsx +++ b/src/Components/Users/ProfilePicUploadModal.tsx @@ -144,7 +144,7 @@ const ProfilePicUploadModal = ({ const handleDelete = async () => { const { res } = await request(routes.deleteProfilePicture, { - pathParams: { id: user.id }, + pathParams: { username: user.username }, }); if (res?.ok) { Success({ msg: "Profile picture deleted" }); diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index e9f7e925fc..e0dfb2c247 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -487,11 +487,11 @@ export default function UserProfile() { onClick={() => setEditProfilePic(!editProfilePic)} > From 8eb0dd27f688e4d242b6e859c10cc5e0d2091fdd Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sat, 8 Jun 2024 11:25:07 +0530 Subject: [PATCH 06/79] minor ui fix --- src/Components/Users/ProfilePicUploadModal.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Components/Users/ProfilePicUploadModal.tsx b/src/Components/Users/ProfilePicUploadModal.tsx index 869ba3b280..7a2916eed0 100644 --- a/src/Components/Users/ProfilePicUploadModal.tsx +++ b/src/Components/Users/ProfilePicUploadModal.tsx @@ -194,9 +194,6 @@ const ProfilePicUploadModal = ({ className="h-full w-full object-cover" />
-

- {commonHint} -

) : (
Date: Tue, 11 Jun 2024 17:11:01 +0530 Subject: [PATCH 07/79] add profile image in the side bar --- src/Components/Common/Sidebar/SidebarUserCard.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Components/Common/Sidebar/SidebarUserCard.tsx b/src/Components/Common/Sidebar/SidebarUserCard.tsx index 02170f453d..9153935e16 100644 --- a/src/Components/Common/Sidebar/SidebarUserCard.tsx +++ b/src/Components/Common/Sidebar/SidebarUserCard.tsx @@ -15,8 +15,14 @@ const SidebarUserCard = ({ shrinked }: { shrinked: boolean }) => { shrinked ? "mx-auto flex-col" : "mx-5" } transition-all duration-200 ease-in-out`} > - - + + profile
Date: Thu, 20 Jun 2024 16:07:56 +0530 Subject: [PATCH 08/79] Rich text editor --- package-lock.json | 2752 ++++++++++++++++++++-- package.json | 6 +- src/Components/Common/MarkdownEditor.tsx | 396 ++++ src/Routers/routes/UserRoutes.tsx | 2 + 4 files changed, 2995 insertions(+), 161 deletions(-) create mode 100644 src/Components/Common/MarkdownEditor.tsx diff --git a/package-lock.json b/package-lock.json index 3a56259835..93171d56a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,9 +34,11 @@ "events": "^3.3.0", "glob": "^10.3.15", "hi-profiles": "^1.0.6", + "i": "^0.3.7", "i18next": "^23.11.4", "i18next-browser-languagedetector": "^7.2.1", "lodash-es": "^4.17.21", + "npm": "^10.8.1", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", @@ -59,6 +61,7 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", + "turndown": "^7.2.0", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.1", "xlsx": "^0.18.5" @@ -84,6 +87,7 @@ "@types/react-google-recaptcha": "^2.1.9", "@types/react-qr-reader": "^2.1.7", "@types/react-transition-group": "^4.4.10", + "@types/turndown": "^5.0.4", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.6.0", @@ -3184,6 +3188,11 @@ "react": ">=16" } }, + "node_modules/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==" + }, "node_modules/@ndelangen/get-tarball": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", @@ -6690,6 +6699,12 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "dev": true }, + "node_modules/@types/turndown": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.4.tgz", + "integrity": "sha512-28GI33lCCkU4SGH1GvjDhFgOVr+Tym4PXGBIU1buJUa6xQolniPArtUT+kv42RR2N9MsMLInkr904Aq+ESHBJg==", + "dev": true + }, "node_modules/@types/unist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", @@ -14584,6 +14599,14 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/i18next": { "version": "23.11.4", "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.4.tgz", @@ -18550,6 +18573,165 @@ "node": ">=0.10.0" } }, + "node_modules/npm": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.1.tgz", + "integrity": "sha512-Dp1C6SvSMYQI7YHq/y2l94uvI+59Eqbu1EpuKQHQ8p16txXRuRit5gH3Lnaagk2aXDIjg/Iru9pd05bnneKgdw==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.5.3", + "@npmcli/config": "^8.3.3", + "@npmcli/fs": "^3.1.1", + "@npmcli/map-workspaces": "^3.0.6", + "@npmcli/package-json": "^5.1.1", + "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", + "@sigstore/tuf": "^2.3.4", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.3", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.4.1", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.2", + "ini": "^4.1.3", + "init-package-json": "^6.0.3", + "is-cidr": "^5.1.0", + "json-parse-even-better-errors": "^3.0.2", + "libnpmaccess": "^8.0.6", + "libnpmdiff": "^6.1.3", + "libnpmexec": "^8.1.2", + "libnpmfund": "^5.0.11", + "libnpmhook": "^10.0.5", + "libnpmorg": "^6.0.6", + "libnpmpack": "^7.0.3", + "libnpmpublish": "^9.0.9", + "libnpmsearch": "^7.0.6", + "libnpmteam": "^6.0.5", + "libnpmversion": "^6.0.3", + "make-fetch-happen": "^13.0.1", + "minimatch": "^9.0.4", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.1.0", + "nopt": "^7.2.1", + "normalize-package-data": "^6.0.1", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.2", + "npm-pick-manifest": "^9.0.1", + "npm-profile": "^10.0.0", + "npm-registry-fetch": "^17.0.1", + "npm-user-validate": "^2.0.1", + "p-map": "^4.0.0", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^4.2.0", + "qrcode-terminal": "^0.12.0", + "read": "^3.0.1", + "semver": "^7.6.2", + "spdx-expression-parse": "^4.0.0", + "ssri": "^10.0.6", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.1", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm-normalize-package-bin": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", @@ -18570,98 +18752,47 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/nypm": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.8.tgz", - "integrity": "sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==", - "dev": true, - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.2.3", - "execa": "^8.0.1", - "pathe": "^1.1.2", - "ufo": "^1.4.0" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.10.0" - } - }, - "node_modules/nypm/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=12" } }, - "node_modules/nypm/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/nypm/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" }, - "node_modules/nypm/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -18669,121 +18800,2414 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nypm/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/nypm/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "mimic-fn": "^4.0.0" + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nypm/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.5.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.1", + "@npmcli/installed-package-contents": "^2.1.0", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.1.1", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.1.0", + "@npmcli/query": "^3.1.0", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", + "bin-links": "^4.0.4", + "cacache": "^18.0.3", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.2", + "json-parse-even-better-errors": "^3.0.2", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^10.2.2", + "minimatch": "^9.0.4", + "nopt": "^7.2.1", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.2", + "npm-pick-manifest": "^9.0.1", + "npm-registry-fetch": "^17.0.1", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.0", + "proc-log": "^4.2.0", + "proggy": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.6", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nypm/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.3.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.2", + "nopt": "^7.2.1", + "proc-log": "^4.2.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nypm/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.7", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^4.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, "engines": { - "node": ">= 6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.1.1", + "inBundle": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^18.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", "engines": { - "node": ">= 0.4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^4.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "8.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.3.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "1.1.0", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.2", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.3.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^13.0.1", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^2.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "1.2.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "18.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.4.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.3", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^5.0.0", + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^3.0.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.1.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "3.1.2", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.1.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.3", + "@npmcli/installed-package-contents": "^2.1.0", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "tar": "^6.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "8.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.3", + "@npmcli/run-script": "^8.1.0", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "proc-log": "^4.2.0", + "read": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.11", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "7.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.3", + "@npmcli/run-script": "^8.1.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.9", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.1", + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.2.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.7", + "@npmcli/run-script": "^8.1.0", + "json-parse-even-better-errors": "^3.0.2", + "proc-log": "^4.2.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.2.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.1.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.1", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "10.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "17.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^2.0.0", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.1", + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "18.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^8.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.11.1", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "4.2.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/proggy": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.2", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "2.3.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^2.3.2", + "@sigstore/tuf": "^2.3.4", + "@sigstore/verify": "^1.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.18", + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/sprintf-js": { + "version": "1.1.3", + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "2.0.1", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nypm": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.8.tgz", + "integrity": "sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "ufo": "^1.4.0" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.assign": { @@ -23697,6 +26121,14 @@ "node": "*" } }, + "node_modules/turndown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", + "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + } + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", diff --git a/package.json b/package.json index 8981eca79c..f3b1e6767a 100644 --- a/package.json +++ b/package.json @@ -72,11 +72,13 @@ "echarts-for-react": "^3.0.2", "eslint-mdx": "^3.1.5", "events": "^3.3.0", - "hi-profiles": "^1.0.6", "glob": "^10.3.15", + "hi-profiles": "^1.0.6", + "i": "^0.3.7", "i18next": "^23.11.4", "i18next-browser-languagedetector": "^7.2.1", "lodash-es": "^4.17.21", + "npm": "^10.8.1", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", @@ -99,6 +101,7 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", + "turndown": "^7.2.0", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.1", "xlsx": "^0.18.5" @@ -124,6 +127,7 @@ "@types/react-google-recaptcha": "^2.1.9", "@types/react-qr-reader": "^2.1.7", "@types/react-transition-group": "^4.4.10", + "@types/turndown": "^5.0.4", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.6.0", diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx new file mode 100644 index 0000000000..0293b6b995 --- /dev/null +++ b/src/Components/Common/MarkdownEditor.tsx @@ -0,0 +1,396 @@ +import { useRef, useState, useEffect } from "react"; +import { + FaBold, + FaItalic, + FaListOl, + FaListUl, + FaUndo, + FaRedo, + FaLink, + FaUnlink, + FaQuoteRight, +} from "react-icons/fa"; +import TurndownService from "turndown"; +import ReactMarkdown from "react-markdown"; + +interface RichTextEditorProps { + markdown?: string; + onChange?: (markdown: string, htmlCode: string) => void; +} + +const RichTextEditor: React.FC = () => { + const [markdown, setMarkdown] = useState(""); + const [htmlCode, setHtmlCode] = useState(""); + const editorRef = useRef(null); + const undoStack = useRef([]); + const redoStack = useRef([]); + const [isBoldActive, setIsBoldActive] = useState(false); + const [isItalicActive, setIsItalicActive] = useState(false); + const [isQuoteActive, setIsQuoteActive] = useState(false); + const [isUnorderedListActive, setIsUnorderedListActive] = + useState(false); + const [isOrderedListActive, setIsOrderedListActive] = + useState(false); + + useEffect(() => { + document.addEventListener("selectionchange", handleSelectionChange); + return () => { + document.removeEventListener("selectionchange", handleSelectionChange); + }; + }, []); + + const handleSelectionChange = () => { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + setIsBoldActive(document.queryCommandState("bold")); + setIsItalicActive(document.queryCommandState("italic")); + setIsQuoteActive( + selection.focusNode?.parentElement?.tagName === "BLOCKQUOTE", + ); + + const listNode = findParentNode(selection.anchorNode, ["UL", "OL"]); + setIsUnorderedListActive(listNode?.nodeName === "UL" ?? false); + setIsOrderedListActive((listNode && listNode.nodeName === "OL") ?? false); + }; + + const saveState = () => { + if (editorRef.current) { + undoStack.current.push(editorRef.current.innerHTML); + redoStack.current = []; + updatePreview(); + } + }; + + const undo = () => { + if (undoStack.current.length > 0 && editorRef.current) { + redoStack.current.push(editorRef.current.innerHTML); + const lastState = undoStack.current.pop(); + if (lastState && editorRef.current) { + editorRef.current.innerHTML = lastState; + updatePreview(); + } + } + }; + + const redo = () => { + if (redoStack.current.length > 0 && editorRef.current) { + undoStack.current.push(editorRef.current.innerHTML); + const nextState = redoStack.current.pop(); + if (nextState && editorRef.current) { + editorRef.current.innerHTML = nextState; + updatePreview(); + } + } + }; + + const applyStyle = (style: "bold" | "italic") => { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + + if (isQuoteActive && (style === "bold" || style === "italic")) return; + + const tagName = style === "bold" ? "strong" : "em"; + const tagNode = document.createElement(tagName); + tagNode.appendChild(range.extractContents()); + range.insertNode(tagNode); + + saveState(); + }; + + const toggleList = (listType: "ul" | "ol") => { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + const listNode = findParentNode(range.startContainer, ["UL", "OL"]); + + if (listNode && listNode.nodeName === listType.toUpperCase()) { + const parentList = listNode.parentNode; + Array.from(listNode.childNodes).forEach((item) => { + const newListItem = document.createElement("li"); + newListItem.textContent = item.textContent; + if (parentList) { + parentList.insertBefore(newListItem, listNode); + } + }); + if (parentList) { + parentList.removeChild(listNode); + } + } else { + const list = document.createElement(listType === "ul" ? "ul" : "ol"); + const listItem = document.createElement("li"); + listItem.appendChild(range.cloneContents()); + list.appendChild(listItem); + range.deleteContents(); + range.insertNode(list); + + const br = document.createElement("br"); + if (list.parentNode) { + list.parentNode.insertBefore(br, list.nextSibling); + } + } + + saveState(); + }; + + const applyHeading = (level: string) => { + document.execCommand("formatBlock", false, ``); + saveState(); + }; + + const applyQuote = () => { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + const blockquote = document.createElement("blockquote"); + blockquote.appendChild(range.extractContents()); + range.insertNode(blockquote); + + const br = document.createElement("br"); + if (blockquote.parentNode) { + blockquote.parentNode.insertBefore(br, blockquote.nextSibling); + } + + saveState(); + }; + + const handleLink = () => { + const userLink = prompt("Enter a URL"); + if (userLink) { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + const anchor = document.createElement("a"); + anchor.href = userLink.startsWith("http") + ? userLink + : `http://${userLink}`; + anchor.textContent = range.toString(); + + range.deleteContents(); + range.insertNode(anchor); + saveState(); + } + }; + + const handleUnlink = () => { + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + const container = range.startContainer.parentNode as HTMLElement; + if (container && container.tagName === "A") { + const parent = container.parentNode; + while (container.firstChild) { + if (parent) { + parent.insertBefore(container.firstChild, container); + } + } + if (parent) { + parent.removeChild(container); + } + } + saveState(); + }; + + const handleLineBreak = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + e.preventDefault(); + const selection = window.getSelection(); + if (!selection) return; + + const range = selection.getRangeAt(0); + const container = range.startContainer.parentNode as HTMLElement; + + if (container && container.tagName === "LI") { + const listNode = container.parentNode as HTMLElement; + if (listNode) { + const newList = document.createElement(listNode.tagName); + const newListItem = document.createElement("li"); + + newListItem.appendChild(range.extractContents()); + newList.appendChild(newListItem); + if (listNode.parentNode) { + listNode.insertBefore(newListItem, container.nextSibling); + } + + range.setStart(newListItem, 0); + range.setEnd(newListItem, 0); + + if ( + container && + container.textContent && + container.textContent.trim() === "" + ) { + if (listNode.parentNode) { + listNode.removeChild(container); + } + } + } + } else { + if (isUnorderedListActive || isOrderedListActive) { + document.execCommand("insertHTML", false, "

"); + } else { + document.execCommand("insertLineBreak"); + } + } + + saveState(); + } + }; + + const updatePreview = () => { + const turndownService = new TurndownService(); + const htmlContent = editorRef.current?.innerHTML || ""; + const markdownText = turndownService.turndown(htmlContent); + setMarkdown(markdownText); + setHtmlCode(htmlContent); + }; + + const findParentNode = ( + node: Node | null, + tagNames: string[], + ): HTMLElement | null => { + while (node && node.parentNode) { + node = node.parentNode; + if (node && tagNames.includes(node.nodeName)) { + return node as HTMLElement; + } + } + return null; + }; + + return ( +
+
+
+
+ + +
+ +
+ + +
+ + + +
+ + +
+ + + +
+ +
+ + +
+
+ +
+
+
+
+

Markdown Preview:

+ {markdown} +
+
+

Markdown Output:

+
+            {markdown}
+          
+
+
+

HTML Code:

+
+            {htmlCode}
+          
+
+
+
+ ); +}; + +export default RichTextEditor; diff --git a/src/Routers/routes/UserRoutes.tsx b/src/Routers/routes/UserRoutes.tsx index 56877ca4c7..40081ef394 100644 --- a/src/Routers/routes/UserRoutes.tsx +++ b/src/Routers/routes/UserRoutes.tsx @@ -1,3 +1,4 @@ +import RichTextEditor from "../../Components/Common/MarkdownEditor"; import ManageUsers from "../../Components/Users/ManageUsers"; import { UserAdd } from "../../Components/Users/UserAdd"; import UserProfile from "../../Components/Users/UserProfile"; @@ -6,4 +7,5 @@ export default { "/users": () => , "/users/add": () => , "/user/profile": () => , + "/test": () => , }; From b955e78c50471a615d09c8e3eeac06debe706c3b Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Thu, 27 Jun 2024 21:21:16 +0530 Subject: [PATCH 09/79] code suggestions --- .../Common/Sidebar/SidebarUserCard.tsx | 9 ++- .../Users/ProfilePicUploadModal.tsx | 75 +++++++++---------- src/Components/Users/UserProfile.tsx | 8 +- 3 files changed, 40 insertions(+), 52 deletions(-) diff --git a/src/Components/Common/Sidebar/SidebarUserCard.tsx b/src/Components/Common/Sidebar/SidebarUserCard.tsx index 9153935e16..2a12efc7c5 100644 --- a/src/Components/Common/Sidebar/SidebarUserCard.tsx +++ b/src/Components/Common/Sidebar/SidebarUserCard.tsx @@ -1,7 +1,7 @@ import { Link } from "raviger"; import { useTranslation } from "react-i18next"; import CareIcon from "../../../CAREUI/icons/CareIcon"; -import { formatName } from "../../../Utils/utils"; +import { classNames, formatName } from "../../../Utils/utils"; import useAuthUser, { useAuthContext } from "../../../Common/hooks/useAuthUser"; const SidebarUserCard = ({ shrinked }: { shrinked: boolean }) => { @@ -19,9 +19,10 @@ const SidebarUserCard = ({ shrinked }: { shrinked: boolean }) => { profile
diff --git a/src/Components/Users/ProfilePicUploadModal.tsx b/src/Components/Users/ProfilePicUploadModal.tsx index 7a2916eed0..71c652738d 100644 --- a/src/Components/Users/ProfilePicUploadModal.tsx +++ b/src/Components/Users/ProfilePicUploadModal.tsx @@ -7,7 +7,6 @@ import { } from "react"; import { Success } from "../../Utils/Notifications"; import useDragAndDrop from "../../Utils/useDragAndDrop"; -import { sleep } from "../../Utils/utils"; import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; import Webcam from "react-webcam"; import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; @@ -19,54 +18,47 @@ import DialogModal from "../Common/Dialog"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; import uploadFile from "../../Utils/request/uploadFile"; -import { UserModel } from "./models"; +import useAuthUser from "../../Common/hooks/useAuthUser"; interface Props { open: boolean; - onClose: (() => void) | undefined; - onSave?: (() => void) | undefined; - onDelete?: (() => void) | undefined; - user: UserModel; + onClose: () => void; + onSave?: () => void; + onDelete?: () => void; } -const ProfilePicUploadModal = ({ - open, - onClose, - onSave, - onDelete, - user, -}: Props) => { - const [isUploading, setIsUploading] = useState(false); - const [selectedFile, setSelectedFile] = useState(); +const ProfilePicUploadModal = ({ open, onClose, onSave, onDelete }: Props) => { + const user = useAuthUser(); + const [isUploading, setIsUploading] = useState(false); + const [selectedFile, setSelectedFile] = useState(); const [preview, setPreview] = useState(); const [isCameraOpen, setIsCameraOpen] = useState(false); - const webRef = useRef(null); - const [previewImage, setPreviewImage] = useState(null); - const [isCaptureImgBeingUploaded, setIsCaptureImgBeingUploaded] = - useState(false); + const webRef = useRef(null); + const [previewImage, setPreviewImage] = useState(null); const FACING_MODE_USER = "user"; const FACING_MODE_ENVIRONMENT = { exact: "environment" }; - const [facingMode, setFacingMode] = useState(FACING_MODE_USER); + const [uploadPercent, setUploadPercent] = useState(0); + + const [facingMode, setFacingMode] = useState<"front" | "rear">("front"); const videoConstraints = { width: 1280, height: 720, - facingMode: "user", + facingMode: + facingMode === "front" ? FACING_MODE_USER : FACING_MODE_ENVIRONMENT, }; const { width } = useWindowDimensions(); const LaptopScreenBreakpoint = 640; const isLaptopScreen = width >= LaptopScreenBreakpoint; const { t } = useTranslation(); const handleSwitchCamera = useCallback(() => { - setFacingMode((prevState: any) => - prevState === FACING_MODE_USER - ? FACING_MODE_ENVIRONMENT - : FACING_MODE_USER, - ); + setFacingMode((prev) => (prev === "front" ? "rear" : "front")); }, []); const captureImage = () => { + if (!webRef.current) return; setPreviewImage(webRef.current.getScreenshot()); const canvas = webRef.current.getCanvas(); - canvas?.toBlob((blob: Blob) => { + canvas?.toBlob((blob: Blob | null) => { + if (!blob) return; const myFile = new File([blob], "image.png", { type: blob.type, }); @@ -95,10 +87,19 @@ const ProfilePicUploadModal = ({ setSelectedFile(e.target.files[0]); }; + useEffect(() => { + if (uploadPercent === 100) { + setIsUploading(false); + onSave?.(); + closeModal(); + setUploadPercent(0); + } + }, [uploadPercent]); + const handleUpload = async () => { - setIsCaptureImgBeingUploaded(true); + setIsUploading(true); if (!selectedFile) { - setIsCaptureImgBeingUploaded(false); + setIsUploading(false); closeModal(); return; } @@ -126,7 +127,7 @@ const ProfilePicUploadModal = ({ setIsUploading(false); } }, - null, + setUploadPercent, () => { Notification.Error({ msg: "Network Failure. Please check your internet connectivity.", @@ -134,12 +135,6 @@ const ProfilePicUploadModal = ({ setIsUploading(false); }, ); - - await sleep(1000); - setIsUploading(false); - setIsCaptureImgBeingUploaded(false); - onSave && onSave(); - closeModal(); }; const handleDelete = async () => { @@ -299,7 +294,7 @@ const ProfilePicUploadModal = ({ screenshotFormat="image/jpeg" width={1280} ref={webRef} - videoConstraints={{ ...videoConstraints, facingMode }} + videoConstraints={videoConstraints} /> ) : ( @@ -349,7 +344,7 @@ const ProfilePicUploadModal = ({ {t("retake")} - {isCaptureImgBeingUploaded && ( + {isUploading && ( { setPreviewImage(null); setIsCameraOpen(false); - webRef.current.stopCamera(); }} className="border-grey-200 my-2 w-full border-2" > @@ -410,7 +404,7 @@ const ProfilePicUploadModal = ({ {t("retake")} - {isCaptureImgBeingUploaded ? ( + {isUploading ? ( <> { setPreviewImage(null); setIsCameraOpen(false); - webRef.current.stopCamera(); }} > {`${t("close")} ${t("camera")}`} diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index e0dfb2c247..c334309d6a 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -16,12 +16,7 @@ import CareIcon from "../../CAREUI/icons/CareIcon"; import PhoneNumberFormField from "../Form/FormFields/PhoneNumberFormField"; import { FieldChangeEvent } from "../Form/FormFields/Utils"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; -import { - GenderType, - SkillModel, - UpdatePasswordForm, - UserModel, -} from "../Users/models"; +import { GenderType, SkillModel, UpdatePasswordForm } from "../Users/models"; import UpdatableApp, { checkForUpdate } from "../Common/UpdatableApp"; import dayjs from "../../Utils/dayjs"; import useAuthUser, { useAuthContext } from "../../Common/hooks/useAuthUser"; @@ -469,7 +464,6 @@ export default function UserProfile() { } onClose={() => setEditProfilePic(false)} onDelete={() => refetchUserData()} - user={userData ?? ({} as UserModel)} />
From 966970f363b3e027391a72bc5941fcf5e867d073 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Thu, 27 Jun 2024 21:53:10 +0530 Subject: [PATCH 10/79] removes npm i packages --- package-lock.json | 2411 --------------------------------------------- package.json | 2 - 2 files changed, 2413 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93171d56a7..86596973e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,11 +34,9 @@ "events": "^3.3.0", "glob": "^10.3.15", "hi-profiles": "^1.0.6", - "i": "^0.3.7", "i18next": "^23.11.4", "i18next-browser-languagedetector": "^7.2.1", "lodash-es": "^4.17.21", - "npm": "^10.8.1", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", @@ -14599,14 +14597,6 @@ "url": "https://github.com/sponsors/typicode" } }, - "node_modules/i": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", - "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", - "engines": { - "node": ">=0.4" - } - }, "node_modules/i18next": { "version": "23.11.4", "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.4.tgz", @@ -18573,165 +18563,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.1.tgz", - "integrity": "sha512-Dp1C6SvSMYQI7YHq/y2l94uvI+59Eqbu1EpuKQHQ8p16txXRuRit5gH3Lnaagk2aXDIjg/Iru9pd05bnneKgdw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/redact", - "@npmcli/run-script", - "@sigstore/tuf", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "normalize-package-data", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "spdx-expression-parse", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "workspaces": [ - "docs", - "smoke-tests", - "mock-globals", - "mock-registry", - "workspaces/*" - ], - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^7.5.3", - "@npmcli/config": "^8.3.3", - "@npmcli/fs": "^3.1.1", - "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.1.1", - "@npmcli/promise-spawn": "^7.0.2", - "@npmcli/redact": "^2.0.0", - "@npmcli/run-script": "^8.1.0", - "@sigstore/tuf": "^2.3.4", - "abbrev": "^2.0.0", - "archy": "~1.0.0", - "cacache": "^18.0.3", - "chalk": "^5.3.0", - "ci-info": "^4.0.0", - "cli-columns": "^4.0.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.3", - "glob": "^10.4.1", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^7.0.2", - "ini": "^4.1.3", - "init-package-json": "^6.0.3", - "is-cidr": "^5.1.0", - "json-parse-even-better-errors": "^3.0.2", - "libnpmaccess": "^8.0.6", - "libnpmdiff": "^6.1.3", - "libnpmexec": "^8.1.2", - "libnpmfund": "^5.0.11", - "libnpmhook": "^10.0.5", - "libnpmorg": "^6.0.6", - "libnpmpack": "^7.0.3", - "libnpmpublish": "^9.0.9", - "libnpmsearch": "^7.0.6", - "libnpmteam": "^6.0.5", - "libnpmversion": "^6.0.3", - "make-fetch-happen": "^13.0.1", - "minimatch": "^9.0.4", - "minipass": "^7.1.1", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^10.1.0", - "nopt": "^7.2.1", - "normalize-package-data": "^6.0.1", - "npm-audit-report": "^5.0.0", - "npm-install-checks": "^6.3.0", - "npm-package-arg": "^11.0.2", - "npm-pick-manifest": "^9.0.1", - "npm-profile": "^10.0.0", - "npm-registry-fetch": "^17.0.1", - "npm-user-validate": "^2.0.1", - "p-map": "^4.0.0", - "pacote": "^18.0.6", - "parse-conflict-json": "^3.0.1", - "proc-log": "^4.2.0", - "qrcode-terminal": "^0.12.0", - "read": "^3.0.1", - "semver": "^7.6.2", - "spdx-expression-parse": "^4.0.0", - "ssri": "^10.0.6", - "supports-color": "^9.4.0", - "tar": "^6.2.1", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^5.0.1", - "which": "^4.0.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/npm-normalize-package-bin": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", @@ -18752,2248 +18583,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "7.5.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^3.1.1", - "@npmcli/installed-package-contents": "^2.1.0", - "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^7.1.1", - "@npmcli/name-from-folder": "^2.0.0", - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.1.0", - "@npmcli/query": "^3.1.0", - "@npmcli/redact": "^2.0.0", - "@npmcli/run-script": "^8.1.0", - "bin-links": "^4.0.4", - "cacache": "^18.0.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^7.0.2", - "json-parse-even-better-errors": "^3.0.2", - "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", - "nopt": "^7.2.1", - "npm-install-checks": "^6.2.0", - "npm-package-arg": "^11.0.2", - "npm-pick-manifest": "^9.0.1", - "npm-registry-fetch": "^17.0.1", - "pacote": "^18.0.6", - "parse-conflict-json": "^3.0.0", - "proc-log": "^4.2.0", - "proggy": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^3.0.1", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^10.0.6", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "8.3.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^3.0.2", - "ci-info": "^4.0.0", - "ini": "^4.1.2", - "nopt": "^7.2.1", - "proc-log": "^4.2.0", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "5.0.7", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^7.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^9.0.0", - "proc-log": "^4.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "2.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "3.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^2.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0", - "read-package-json-fast": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "7.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^18.0.0", - "json-parse-even-better-errors": "^3.0.0", - "pacote": "^18.0.0", - "proc-log": "^4.1.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "5.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^4.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "3.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/redact": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "8.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "proc-log": "^4.0.0", - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/core": { - "version": "1.1.0", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.4", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.2.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/models": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "7.1.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "4.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "read-cmd-shim": "^4.0.0", - "write-file-atomic": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "18.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "4.0.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.1", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.3", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.4", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/diff": { - "version": "5.2.0", - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.1", - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/function-bind": { - "version": "1.1.2", - "inBundle": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.4.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hasown": { - "version": "2.0.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "7.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "7.0.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.4", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "6.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ini": { - "version": "4.1.3", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "6.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/package-json": "^5.0.0", - "npm-package-arg": "^11.0.0", - "promzard": "^1.0.0", - "read": "^3.0.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/ip-address": { - "version": "9.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "5.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.0", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^4.1.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/is-core-module": { - "version": "2.13.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "3.1.2", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/jsbn": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "8.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "6.1.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.3", - "@npmcli/installed-package-contents": "^2.1.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", - "tar": "^6.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "8.1.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.3", - "@npmcli/run-script": "^8.1.0", - "ci-info": "^4.0.0", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", - "proc-log": "^4.2.0", - "read": "^3.0.1", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "5.0.11", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "10.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "6.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "7.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.3", - "@npmcli/run-script": "^8.1.0", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "9.0.9", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^4.0.0", - "normalize-package-data": "^6.0.1", - "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1", - "proc-log": "^4.2.0", - "semver": "^7.3.7", - "sigstore": "^2.2.0", - "ssri": "^10.0.6" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "7.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "6.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "6.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.7", - "@npmcli/run-script": "^8.1.0", - "json-parse-even-better-errors": "^3.0.2", - "proc-log": "^4.2.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "10.2.2", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "7.1.2", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "2.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "3.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-json-stream": { - "version": "1.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "1.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "10.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "7.2.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "6.0.1", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "6.3.0", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "11.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "8.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^6.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "9.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "10.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^17.0.1", - "proc-log": "^4.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "17.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^2.0.0", - "make-fetch-happen": "^13.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "2.0.1", - "inBundle": true, - "license": "BSD-2-Clause", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/pacote": { - "version": "18.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/package-json": "^5.1.0", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^8.0.0", - "cacache": "^18.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^17.0.0", - "proc-log": "^4.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/proggy": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "1.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "^3.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "3.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.6.2", - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "2.3.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.8.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.5.0", - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.18", - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/sprintf-js": { - "version": "1.1.3", - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/npm/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.2.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js": { - "version": "2.2.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "5.0.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/which": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "5.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC" - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", diff --git a/package.json b/package.json index f3b1e6767a..247330b2da 100644 --- a/package.json +++ b/package.json @@ -74,11 +74,9 @@ "events": "^3.3.0", "glob": "^10.3.15", "hi-profiles": "^1.0.6", - "i": "^0.3.7", "i18next": "^23.11.4", "i18next-browser-languagedetector": "^7.2.1", "lodash-es": "^4.17.21", - "npm": "^10.8.1", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", "raviger": "^4.1.2", From 9b2ae1597c2c83c1e1ca0052ae472b9f7be21f43 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Fri, 28 Jun 2024 21:05:48 +0530 Subject: [PATCH 11/79] thread view --- .../ConsultationDoctorNotes/index.tsx | 31 ++++- src/Components/Facility/DoctorNote.tsx | 54 ++++++-- .../Facility/PatientConsultationNotesList.tsx | 3 + src/Components/Facility/PatientNoteCard.tsx | 17 ++- .../Facility/PatientNotesDetailedView.tsx | 121 ++++++++++++++++++ src/Components/Facility/models.tsx | 3 + .../Notifications/NotificationsList.tsx | 2 +- src/Redux/api.tsx | 5 + src/Routers/routes/ConsultationRoutes.tsx | 9 ++ 9 files changed, 224 insertions(+), 21 deletions(-) create mode 100644 src/Components/Facility/PatientNotesDetailedView.tsx diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx index bac946e90e..600d03c306 100644 --- a/src/Components/Facility/ConsultationDoctorNotes/index.tsx +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -16,15 +16,18 @@ import AutoExpandingTextInputFormField from "../../Form/FormFields/AutoExpanding import { PATIENT_NOTES_THREADS } from "../../../Common/constants.js"; import useAuthUser from "../../../Common/hooks/useAuthUser.js"; import DoctorNoteReplyPreviewCard from "../DoctorNoteReplyPreviewCard.js"; +import Switch from "../../../CAREUI/interactive/Switch.js"; +import PatientNotesDetailedView from "../PatientNotesDetailedView.js"; interface ConsultationDoctorNotesProps { patientId: string; facilityId: string; consultationId: string; + noteId?: string; } const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { - const { patientId, facilityId, consultationId } = props; + const { patientId, facilityId, consultationId, noteId } = props; const authUser = useAuthUser(); const [thread, setThread] = useState( @@ -42,6 +45,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { const [reply_to, setReplyTo] = useState( undefined, ); + const [mode, setMode] = useState<"comments" | "replies">("comments"); const initialData: PatientNoteStateType = { notes: [], @@ -116,16 +120,38 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { }, ); + if (noteId) { + return ( + + ); + } + return ( +
+ setMode(tab)} + /> +
{Object.values(PATIENT_NOTES_THREADS).map((current) => ( @@ -155,6 +181,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { setReload={setReload} thread={thread} setReplyTo={setReplyTo} + mode={mode} /> void; disableEdit?: boolean; setReplyTo?: (reply_to: PatientNotesModel | undefined) => void; + mode?: "comments" | "replies"; } const DoctorNote = (props: DoctorNoteProps) => { - const { state, handleNext, setReload, disableEdit, setReplyTo } = props; + const { state, handleNext, setReload, disableEdit, setReplyTo, mode } = props; return (
{ dataLength={state.notes.length} scrollableTarget="patient-notes-list" > - {state.notes.map((note) => ( - - - - ))} + {state.notes.map((note) => { + if (mode === "comments") { + return ( +
+ + {note.replies.length > 0 ? ( +
+ {note.replies.length}{" "} + {note.replies.length > 1 ? "replies" : "reply"} +
+ ) : ( +
+ No replies +
+ )} +
+ ); + } else if (mode === "replies") { + return ( + + + + ); + } + })} ) : (
diff --git a/src/Components/Facility/PatientConsultationNotesList.tsx b/src/Components/Facility/PatientConsultationNotesList.tsx index 15238ff189..43d72180c4 100644 --- a/src/Components/Facility/PatientConsultationNotesList.tsx +++ b/src/Components/Facility/PatientConsultationNotesList.tsx @@ -15,6 +15,7 @@ interface PatientNotesProps { disableEdit?: boolean; thread: PatientNotesModel["thread"]; setReplyTo?: (value: PatientNotesModel | undefined) => void; + mode?: "comments" | "replies"; } const pageSize = RESULTS_PER_PAGE_LIMIT; @@ -28,6 +29,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { disableEdit, thread, setReplyTo, + mode = "replies", } = props; const consultationId = useSlug("consultation") ?? ""; @@ -105,6 +107,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { setReload={setReload} disableEdit={disableEdit} setReplyTo={setReplyTo} + mode={mode} /> ); }; diff --git a/src/Components/Facility/PatientNoteCard.tsx b/src/Components/Facility/PatientNoteCard.tsx index 5a31359577..6092219018 100644 --- a/src/Components/Facility/PatientNoteCard.tsx +++ b/src/Components/Facility/PatientNoteCard.tsx @@ -11,8 +11,9 @@ import DialogModal from "../Common/Dialog"; import { t } from "i18next"; import dayjs from "dayjs"; import Spinner from "../Common/Spinner"; -import useAuthUser from "../../Common/hooks/useAuthUser"; +// import useAuthUser from "../../Common/hooks/useAuthUser"; import useSlug from "../../Common/hooks/useSlug"; +import { navigate } from "raviger"; const PatientNoteCard = ({ note, @@ -30,7 +31,8 @@ const PatientNoteCard = ({ const [noteField, setNoteField] = useState(note.note); const [showEditHistory, setShowEditHistory] = useState(false); const [editHistory, setEditHistory] = useState([]); - const authUser = useAuthUser(); + // const authUser = useAuthUser(); + const currentPath = window.location.pathname; const fetchEditHistory = async () => { const { res, data } = await request(routes.getPatientNoteEditHistory, { @@ -128,7 +130,7 @@ const PatientNoteCard = ({
{!disableEdit && - note.created_by_object.id === authUser.id && + // note.created_by_object.id === authUser.id && !isEditing && (
) : ( -
{noteField}
+
{ + navigate(`${currentPath}/${note.id}`); + }} + className="cursor-pointer text-sm text-gray-700" + > + {noteField} +
)}
} diff --git a/src/Components/Facility/PatientNotesDetailedView.tsx b/src/Components/Facility/PatientNotesDetailedView.tsx new file mode 100644 index 0000000000..1e194ef953 --- /dev/null +++ b/src/Components/Facility/PatientNotesDetailedView.tsx @@ -0,0 +1,121 @@ +import { useEffect, useState } from "react"; +import CircularProgress from "../Common/components/CircularProgress"; +import routes from "../../Redux/api"; +import { PaitentNotesReplyModel, PatientNotesModel } from "./models"; +import request from "../../Utils/request/request"; +import Page from "../Common/components/Page"; +import PatientNoteCard from "./PatientNoteCard"; + +interface Props { + patientId: string; + facilityId: string; + consultationId: string; + noteId: string; + thread: PatientNotesModel["thread"]; +} + +interface PatientNoteWithReplies { + note: string; + replies: PaitentNotesReplyModel[]; +} + +const PatientNotesDetailedView = (props: Props) => { + const { patientId, facilityId, consultationId, noteId, thread } = props; + const [isLoading, setIsLoading] = useState(true); + const [reload, setReload] = useState(false); + const [state, setState] = useState({ + note: "", + replies: [], + }); + const [reply_to, setReplyTo] = useState( + undefined, + ); + console.log(reply_to); + + const fetchNotes = async () => { + setIsLoading(true); + + const { data } = await request(routes.getPatientNote, { + pathParams: { + patientId: patientId, + noteId, + }, + query: { + consultation: consultationId, + thread, + }, + }); + + if (data) { + setState((prevState) => ({ + ...prevState, + note: data.note, + replies: data.replies, + })); + } + setIsLoading(false); + setReload?.(false); + }; + + useEffect(() => { + if (reload) { + fetchNotes(); + } + }, [reload]); + + useEffect(() => { + fetchNotes(); + }, [thread]); + + useEffect(() => { + setReload?.(true); + }, []); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( + +
+ { +
+ + { +
+ {state.replies.length}{" "} + {state.replies.length > 1 ? "replies" : "reply"} +
+ } +

Replies

+ { +
+ {state.replies.map((reply) => ( + + ))} +
+ } +
+ } +
+
+ ); +}; + +export default PatientNotesDetailedView; diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 8bf55273fe..7d7b549910 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -506,6 +506,7 @@ export interface BaseUserModel { last_name: string; user_type: string; last_login: string; + read_profile_image_url: string; } export interface PatientNotesEditModel { @@ -524,6 +525,7 @@ export interface PaitentNotesReplyModel { } export interface PatientNotesModel { + count: number; id: string; note: string; facility: BaseFacilityModel; @@ -534,6 +536,7 @@ export interface PatientNotesModel { last_edited_by?: BaseUserModel; last_edited_date?: string; reply_to_object?: PaitentNotesReplyModel; + replies: PaitentNotesReplyModel[]; } export interface PatientNoteStateType { diff --git a/src/Components/Notifications/NotificationsList.tsx b/src/Components/Notifications/NotificationsList.tsx index c9e6720e6a..50e967cb55 100644 --- a/src/Components/Notifications/NotificationsList.tsx +++ b/src/Components/Notifications/NotificationsList.tsx @@ -73,7 +73,7 @@ const NotificationTile = ({ case "INVESTIGATION_SESSION_CREATED": return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}/investigation/${data.session}`; case "PATIENT_NOTE_ADDED": - return `/facility/${data.facility}/patient/${data.patient}/notes`; + return `/facility/${data.facility}/patient/${data.patient}/consultation/${data.consultation}/notes`; case "MESSAGE": return "/notice_board/"; default: diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 44b32c6a9b..f620003eef 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -794,6 +794,11 @@ const routes = { method: "PUT", TRes: Type(), }, + getPatientNote: { + path: "/api/v1/patient/{patientId}/notes/{noteId}/", + method: "GET", + TRes: Type(), + }, getPatientNoteEditHistory: { path: "/api/v1/patient/{patientId}/notes/{noteId}/edits/", method: "GET", diff --git a/src/Routers/routes/ConsultationRoutes.tsx b/src/Routers/routes/ConsultationRoutes.tsx index 8b75e3f147..e8a828d4d3 100644 --- a/src/Routers/routes/ConsultationRoutes.tsx +++ b/src/Routers/routes/ConsultationRoutes.tsx @@ -150,6 +150,15 @@ export default { consultationId={consultationId} /> ), + "/facility/:facilityId/patient/:patientId/consultation/:consultationId/notes/:noteId": + ({ facilityId, patientId, consultationId, noteId }: any) => ( + + ), "/facility/:facilityId/patient/:patientId/consultation/:consultationId/:tab": ({ facilityId, patientId, consultationId, tab }: any) => ( Date: Wed, 3 Jul 2024 22:42:13 +0530 Subject: [PATCH 12/79] code suggestions --- src/Components/Common/Sidebar/SidebarUserCard.tsx | 2 +- src/Components/Users/UserProfile.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Common/Sidebar/SidebarUserCard.tsx b/src/Components/Common/Sidebar/SidebarUserCard.tsx index 2a12efc7c5..c734bbe95d 100644 --- a/src/Components/Common/Sidebar/SidebarUserCard.tsx +++ b/src/Components/Common/Sidebar/SidebarUserCard.tsx @@ -20,7 +20,7 @@ const SidebarUserCard = ({ shrinked }: { shrinked: boolean }) => { src={user.read_profile_picture_url || "/images/empty_avatar.jpg"} alt="profile" className={classNames( - "mb-3 h-10 w-10 rounded-full object-cover", + "mb-3 size-10 rounded-full object-cover", shrinked && "mb-2 mt-1", )} /> diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index c334309d6a..3532f09cde 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -481,7 +481,7 @@ export default function UserProfile() { onClick={() => setEditProfilePic(!editProfilePic)} > Date: Thu, 4 Jul 2024 21:35:50 +0530 Subject: [PATCH 13/79] removes depricated commands --- src/Components/Common/MarkdownEditor.tsx | 103 ++++++++--------------- 1 file changed, 37 insertions(+), 66 deletions(-) diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index 0293b6b995..8ee6486a59 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -43,17 +43,42 @@ const RichTextEditor: React.FC = () => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; - setIsBoldActive(document.queryCommandState("bold")); - setIsItalicActive(document.queryCommandState("italic")); - setIsQuoteActive( - selection.focusNode?.parentElement?.tagName === "BLOCKQUOTE", - ); + const isBold = isParentTag(selection.focusNode, "STRONG"); + const isItalic = isParentTag(selection.focusNode, "EM"); + const isQuote = isParentTag(selection.focusNode, "BLOCKQUOTE"); + + setIsBoldActive(isBold); + setIsItalicActive(isItalic); + setIsQuoteActive(isQuote); const listNode = findParentNode(selection.anchorNode, ["UL", "OL"]); setIsUnorderedListActive(listNode?.nodeName === "UL" ?? false); setIsOrderedListActive((listNode && listNode.nodeName === "OL") ?? false); }; + const isParentTag = (node: Node | null, tagName: string) => { + while (node) { + if (node.nodeName === tagName) { + return true; + } + node = node.parentNode; + } + return false; + }; + + const findParentNode = ( + node: Node | null, + tagNames: string[], + ): HTMLElement | null => { + while (node && node.parentNode) { + node = node.parentNode; + if (node && tagNames.includes(node.nodeName)) { + return node as HTMLElement; + } + } + return null; + }; + const saveState = () => { if (editorRef.current) { undoStack.current.push(editorRef.current.innerHTML); @@ -137,7 +162,13 @@ const RichTextEditor: React.FC = () => { }; const applyHeading = (level: string) => { - document.execCommand("formatBlock", false, ``); + const selection = window.getSelection(); + if (!selection || !selection.rangeCount) return; + + const range = selection.getRangeAt(0); + const heading = document.createElement(`h${level}`); + heading.appendChild(range.extractContents()); + range.insertNode(heading); saveState(); }; @@ -197,52 +228,6 @@ const RichTextEditor: React.FC = () => { saveState(); }; - const handleLineBreak = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - e.preventDefault(); - const selection = window.getSelection(); - if (!selection) return; - - const range = selection.getRangeAt(0); - const container = range.startContainer.parentNode as HTMLElement; - - if (container && container.tagName === "LI") { - const listNode = container.parentNode as HTMLElement; - if (listNode) { - const newList = document.createElement(listNode.tagName); - const newListItem = document.createElement("li"); - - newListItem.appendChild(range.extractContents()); - newList.appendChild(newListItem); - if (listNode.parentNode) { - listNode.insertBefore(newListItem, container.nextSibling); - } - - range.setStart(newListItem, 0); - range.setEnd(newListItem, 0); - - if ( - container && - container.textContent && - container.textContent.trim() === "" - ) { - if (listNode.parentNode) { - listNode.removeChild(container); - } - } - } - } else { - if (isUnorderedListActive || isOrderedListActive) { - document.execCommand("insertHTML", false, "

"); - } else { - document.execCommand("insertLineBreak"); - } - } - - saveState(); - } - }; - const updatePreview = () => { const turndownService = new TurndownService(); const htmlContent = editorRef.current?.innerHTML || ""; @@ -251,19 +236,6 @@ const RichTextEditor: React.FC = () => { setHtmlCode(htmlContent); }; - const findParentNode = ( - node: Node | null, - tagNames: string[], - ): HTMLElement | null => { - while (node && node.parentNode) { - node = node.parentNode; - if (node && tagNames.includes(node.nodeName)) { - return node as HTMLElement; - } - } - return null; - }; - return (
@@ -367,7 +339,6 @@ const RichTextEditor: React.FC = () => { ref={editorRef} contentEditable className="prose min-h-64 border border-gray-300 p-4 focus:outline-none" - onKeyDown={handleLineBreak} onInput={updatePreview} >
From 16853d1d12c3bc6562b19c07f8a47c9d367b31f0 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Thu, 4 Jul 2024 21:55:55 +0530 Subject: [PATCH 14/79] use usereducer --- src/Components/Common/MarkdownEditor.tsx | 117 ++++++++++++++++------- 1 file changed, 83 insertions(+), 34 deletions(-) diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index 8ee6486a59..f6f64da4b4 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -1,4 +1,4 @@ -import { useRef, useState, useEffect } from "react"; +import { useRef, useReducer, useEffect, useState } from "react"; import { FaBold, FaItalic, @@ -18,19 +18,56 @@ interface RichTextEditorProps { onChange?: (markdown: string, htmlCode: string) => void; } +interface EditorState { + isBoldActive: boolean; + isItalicActive: boolean; + isQuoteActive: boolean; + isUnorderedListActive: boolean; + isOrderedListActive: boolean; +} + +type EditorAction = + | { type: "SET_BOLD_ACTIVE"; payload: boolean } + | { type: "SET_ITALIC_ACTIVE"; payload: boolean } + | { type: "SET_QUOTE_ACTIVE"; payload: boolean } + | { type: "SET_UNORDERED_LIST_ACTIVE"; payload: boolean } + | { type: "SET_ORDERED_LIST_ACTIVE"; payload: boolean } + | { type: "UPDATE_ALL"; payload: Partial }; + +const initialState: EditorState = { + isBoldActive: false, + isItalicActive: false, + isQuoteActive: false, + isUnorderedListActive: false, + isOrderedListActive: false, +}; + +function editorReducer(state: EditorState, action: EditorAction): EditorState { + switch (action.type) { + case "SET_BOLD_ACTIVE": + return { ...state, isBoldActive: action.payload }; + case "SET_ITALIC_ACTIVE": + return { ...state, isItalicActive: action.payload }; + case "SET_QUOTE_ACTIVE": + return { ...state, isQuoteActive: action.payload }; + case "SET_UNORDERED_LIST_ACTIVE": + return { ...state, isUnorderedListActive: action.payload }; + case "SET_ORDERED_LIST_ACTIVE": + return { ...state, isOrderedListActive: action.payload }; + case "UPDATE_ALL": + return { ...state, ...action.payload }; + default: + return state; + } +} + const RichTextEditor: React.FC = () => { const [markdown, setMarkdown] = useState(""); const [htmlCode, setHtmlCode] = useState(""); + const [state, dispatch] = useReducer(editorReducer, initialState); const editorRef = useRef(null); const undoStack = useRef([]); const redoStack = useRef([]); - const [isBoldActive, setIsBoldActive] = useState(false); - const [isItalicActive, setIsItalicActive] = useState(false); - const [isQuoteActive, setIsQuoteActive] = useState(false); - const [isUnorderedListActive, setIsUnorderedListActive] = - useState(false); - const [isOrderedListActive, setIsOrderedListActive] = - useState(false); useEffect(() => { document.addEventListener("selectionchange", handleSelectionChange); @@ -43,17 +80,29 @@ const RichTextEditor: React.FC = () => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; - const isBold = isParentTag(selection.focusNode, "STRONG"); - const isItalic = isParentTag(selection.focusNode, "EM"); + const isBold = + isParentTag(selection.focusNode, "STRONG") || + isParentTag(selection.focusNode, "B"); + const isItalic = + isParentTag(selection.focusNode, "EM") || + isParentTag(selection.focusNode, "I"); const isQuote = isParentTag(selection.focusNode, "BLOCKQUOTE"); - setIsBoldActive(isBold); - setIsItalicActive(isItalic); - setIsQuoteActive(isQuote); - const listNode = findParentNode(selection.anchorNode, ["UL", "OL"]); - setIsUnorderedListActive(listNode?.nodeName === "UL" ?? false); - setIsOrderedListActive((listNode && listNode.nodeName === "OL") ?? false); + const isUnorderedListActive = listNode?.nodeName === "UL" ?? false; + const isOrderedListActive = + (listNode && listNode.nodeName === "OL") ?? false; + + dispatch({ + type: "UPDATE_ALL", + payload: { + isBoldActive: isBold, + isItalicActive: isItalic, + isQuoteActive: isQuote, + isUnorderedListActive, + isOrderedListActive, + }, + }); }; const isParentTag = (node: Node | null, tagName: string) => { @@ -87,6 +136,14 @@ const RichTextEditor: React.FC = () => { } }; + const updatePreview = () => { + const turndownService = new TurndownService(); + const htmlContent = editorRef.current?.innerHTML || ""; + const markdownText = turndownService.turndown(htmlContent); + setMarkdown(markdownText); + setHtmlCode(htmlContent); + }; + const undo = () => { if (undoStack.current.length > 0 && editorRef.current) { redoStack.current.push(editorRef.current.innerHTML); @@ -115,7 +172,7 @@ const RichTextEditor: React.FC = () => { const range = selection.getRangeAt(0); - if (isQuoteActive && (style === "bold" || style === "italic")) return; + if (state.isQuoteActive && (style === "bold" || style === "italic")) return; const tagName = style === "bold" ? "strong" : "em"; const tagNode = document.createElement(tagName); @@ -228,14 +285,6 @@ const RichTextEditor: React.FC = () => { saveState(); }; - const updatePreview = () => { - const turndownService = new TurndownService(); - const htmlContent = editorRef.current?.innerHTML || ""; - const markdownText = turndownService.turndown(htmlContent); - setMarkdown(markdownText); - setHtmlCode(htmlContent); - }; - return (
@@ -244,22 +293,22 @@ const RichTextEditor: React.FC = () => { @@ -269,22 +318,22 @@ const RichTextEditor: React.FC = () => { @@ -293,7 +342,7 @@ const RichTextEditor: React.FC = () => { - -
From e0ee2f5f73219631b52a2a030e09963418fc13d9 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Fri, 5 Jul 2024 00:25:19 +0530 Subject: [PATCH 16/79] support for mentions --- src/Components/Common/MarkdownEditor.tsx | 212 +++++++++++++++++----- src/Components/Common/MentionDropdown.tsx | 35 ++++ 2 files changed, 204 insertions(+), 43 deletions(-) create mode 100644 src/Components/Common/MentionDropdown.tsx diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index c5cffc808c..c41773d951 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -1,4 +1,4 @@ -import { useRef, useReducer, useEffect, useState } from "react"; +import { useRef, useReducer, useEffect, useState, useCallback } from "react"; import { FaBold, FaItalic, @@ -6,10 +6,14 @@ import { FaListUl, FaLink, FaUnlink, + FaStrikethrough, FaQuoteRight, } from "react-icons/fa"; +import { GoMention } from "react-icons/go"; +// import { MdAttachFile } from "react-icons/md"; import TurndownService from "turndown"; import ReactMarkdown from "react-markdown"; +import MentionsDropdown from "./MentionDropdown"; interface RichTextEditorProps { markdown?: string; @@ -19,6 +23,7 @@ interface RichTextEditorProps { interface EditorState { isBoldActive: boolean; isItalicActive: boolean; + isStrikethroughActive: boolean; isQuoteActive: boolean; isUnorderedListActive: boolean; isOrderedListActive: boolean; @@ -27,6 +32,7 @@ interface EditorState { type EditorAction = | { type: "SET_BOLD_ACTIVE"; payload: boolean } | { type: "SET_ITALIC_ACTIVE"; payload: boolean } + | { type: "SET_STRIKETHROUGH_ACTIVE"; payload: boolean } | { type: "SET_QUOTE_ACTIVE"; payload: boolean } | { type: "SET_UNORDERED_LIST_ACTIVE"; payload: boolean } | { type: "SET_ORDERED_LIST_ACTIVE"; payload: boolean } @@ -35,6 +41,7 @@ type EditorAction = const initialState: EditorState = { isBoldActive: false, isItalicActive: false, + isStrikethroughActive: false, isQuoteActive: false, isUnorderedListActive: false, isOrderedListActive: false, @@ -46,6 +53,8 @@ function editorReducer(state: EditorState, action: EditorAction): EditorState { return { ...state, isBoldActive: action.payload }; case "SET_ITALIC_ACTIVE": return { ...state, isItalicActive: action.payload }; + case "SET_STRIKETHROUGH_ACTIVE": + return { ...state, isStrikethroughActive: action.payload }; case "SET_QUOTE_ACTIVE": return { ...state, isQuoteActive: action.payload }; case "SET_UNORDERED_LIST_ACTIVE": @@ -65,6 +74,10 @@ const RichTextEditor: React.FC = () => { const [state, dispatch] = useReducer(editorReducer, initialState); const editorRef = useRef(null); + const [showMentions, setShowMentions] = useState(false); + const [mentionPosition, setMentionPosition] = useState({ top: 0, left: 0 }); + const lastCaretPosition = useRef(null); + useEffect(() => { document.addEventListener("selectionchange", handleSelectionChange); return () => { @@ -88,6 +101,9 @@ const RichTextEditor: React.FC = () => { const isUnorderedListActive = listNode?.nodeName === "UL" ?? false; const isOrderedListActive = (listNode && listNode.nodeName === "OL") ?? false; + const isStrikethrough = + isParentTag(selection.focusNode, "S") || + isParentTag(selection.focusNode, "DEL"); dispatch({ type: "UPDATE_ALL", @@ -97,6 +113,7 @@ const RichTextEditor: React.FC = () => { isQuoteActive: isQuote, isUnorderedListActive, isOrderedListActive, + isStrikethroughActive: isStrikethrough, }, }); }; @@ -124,26 +141,17 @@ const RichTextEditor: React.FC = () => { return null; }; - const saveState = () => { - const turndownService = new TurndownService(); - const htmlContent = editorRef.current?.innerHTML || ""; - const markdownText = turndownService.turndown(htmlContent); - setMarkdown(markdownText); - setHtmlCode(htmlContent); - }; - - const applyStyle = (style: "bold" | "italic") => { + const applyStyle = (style: "bold" | "italic" | "strikethrough") => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; const range = selection.getRangeAt(0); - if (state.isQuoteActive && (style === "bold" || style === "italic")) return; - - const tagName = style === "bold" ? "strong" : "em"; - const tagNode = document.createElement(tagName); - tagNode.appendChild(range.extractContents()); - range.insertNode(tagNode); + const tag = style === "bold" ? "strong" : style === "italic" ? "em" : "s"; + const node = document.createElement(tag); + node.appendChild(range.cloneContents()); + range.deleteContents(); + range.insertNode(node); saveState(); }; @@ -184,17 +192,6 @@ const RichTextEditor: React.FC = () => { saveState(); }; - const applyHeading = (level: string) => { - const selection = window.getSelection(); - if (!selection || !selection.rangeCount) return; - - const range = selection.getRangeAt(0); - const heading = document.createElement(`h${level}`); - heading.appendChild(range.extractContents()); - range.insertNode(heading); - saveState(); - }; - const applyQuote = () => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; @@ -251,6 +248,109 @@ const RichTextEditor: React.FC = () => { saveState(); }; + const handleInput = useCallback((event: React.FormEvent) => { + const target = event.target as HTMLDivElement; + const text = target.textContent || ""; + const lastChar = text[text.length - 1]; + + if (lastChar === "@") { + const selection = window.getSelection(); + if (selection && selection.rangeCount > 0) { + const range = selection.getRangeAt(0); + const rect = range.getBoundingClientRect(); + setMentionPosition({ + top: rect.bottom + window.scrollY, + left: rect.left + window.scrollX, + }); + setShowMentions(true); + lastCaretPosition.current = range.cloneRange(); + } + } else { + setShowMentions(false); + } + + saveState(); + }, []); + + const insertMention = (user: { id: string; username: string }) => { + if (lastCaretPosition.current) { + const range = lastCaretPosition.current; + range.setStart(range.startContainer, range.startOffset - 1); + range.deleteContents(); + + const mentionNode = document.createElement("span"); + mentionNode.contentEditable = "false"; + mentionNode.className = "bg-blue-100 px-1 rounded"; + mentionNode.textContent = `@${user.username}`; + mentionNode.setAttribute("data-user-id", user.id); + + range.insertNode(mentionNode); + + const newRange = document.createRange(); + newRange.setStartAfter(mentionNode); + newRange.collapse(true); + + const selection = window.getSelection(); + if (selection) { + selection.removeAllRanges(); + selection.addRange(newRange); + } + + setShowMentions(false); + saveState(); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Backspace") { + const selection = window.getSelection(); + if (selection && selection.rangeCount > 0) { + const range = selection.getRangeAt(0); + const startContainer = range.startContainer; + + if ( + startContainer.nodeType === Node.TEXT_NODE && + startContainer.textContent === "@" + ) { + const parentNode = startContainer.parentNode; + if ( + parentNode && + parentNode.nodeName === "SPAN" && + parentNode instanceof HTMLElement && + parentNode.hasAttribute("data-user-id") + ) { + event.preventDefault(); + parentNode.parentNode?.removeChild(parentNode); + saveState(); + } + } + } + } + }; + + const saveState = () => { + const turndownService = new TurndownService(); + turndownService.addRule("strikethrough", { + filter: ["del", "s"], + replacement: (content) => `~${content}~`, + }); + turndownService.addRule("mentions", { + filter: (node) => { + return node.nodeName === "SPAN" && node.hasAttribute("data-user-id"); + }, + replacement: (content, node) => { + const userId = (node as HTMLElement).getAttribute("data-user-id"); + const username = content.replace("@", ""); + return `[mention_user](user_id:${userId}, username:${username})`; + }, + }); + + const htmlContent = editorRef.current?.innerHTML || ""; + const markdownText = turndownService.turndown(htmlContent); + setMarkdown(markdownText); + setHtmlCode(htmlContent); + }; + return (
@@ -278,6 +378,17 @@ const RichTextEditor: React.FC = () => { > +
@@ -323,30 +434,45 @@ const RichTextEditor: React.FC = () => {
- -
+ +
+ + {/* */} +
+ + {showMentions && ( + + )}
diff --git a/src/Components/Common/MentionDropdown.tsx b/src/Components/Common/MentionDropdown.tsx new file mode 100644 index 0000000000..344d242111 --- /dev/null +++ b/src/Components/Common/MentionDropdown.tsx @@ -0,0 +1,35 @@ +type User = { + id: string; + username: string; +}; + +const users: User[] = [ + { id: "1", username: "udaysagar" }, + { id: "2", username: "doctordev" }, + { id: "3", username: "dev-districtadmin" }, + { id: "4", username: "staffdev" }, +]; + +const MentionsDropdown: React.FC<{ + onSelect: (user: User) => void; + position: { top: number; left: number }; +}> = ({ onSelect, position }) => { + return ( +
+ {users.map((user) => ( +
onSelect(user)} + > + {user.username} +
+ ))} +
+ ); +}; + +export default MentionsDropdown; From 02ce21582f586abe99479301e65e17a76868c867 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Fri, 5 Jul 2024 19:23:06 +0530 Subject: [PATCH 17/79] mention style and strike through style --- src/Components/Common/MarkdownEditor.tsx | 58 +++++++---------------- src/Components/Common/MarkdownPreview.tsx | 20 ++++++++ 2 files changed, 38 insertions(+), 40 deletions(-) create mode 100644 src/Components/Common/MarkdownPreview.tsx diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index c41773d951..7a5bbdeca3 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -12,8 +12,8 @@ import { import { GoMention } from "react-icons/go"; // import { MdAttachFile } from "react-icons/md"; import TurndownService from "turndown"; -import ReactMarkdown from "react-markdown"; import MentionsDropdown from "./MentionDropdown"; +import MarkdownPreview from "./MarkdownPreview"; interface RichTextEditorProps { markdown?: string; @@ -141,14 +141,13 @@ const RichTextEditor: React.FC = () => { return null; }; - const applyStyle = (style: "bold" | "italic" | "strikethrough") => { + const applyStyle = (style: "b" | "i" | "s") => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; const range = selection.getRangeAt(0); - const tag = style === "bold" ? "strong" : style === "italic" ? "em" : "s"; - const node = document.createElement(tag); + const node = document.createElement(style); node.appendChild(range.cloneContents()); range.deleteContents(); range.insertNode(node); @@ -278,9 +277,10 @@ const RichTextEditor: React.FC = () => { range.setStart(range.startContainer, range.startOffset - 1); range.deleteContents(); - const mentionNode = document.createElement("span"); + const mentionNode = document.createElement("a"); mentionNode.contentEditable = "false"; - mentionNode.className = "bg-blue-100 px-1 rounded"; + mentionNode.className = + "bg-blue-100 px-1 rounded no-underline text-slate-800 font-normal hover:underline"; mentionNode.textContent = `@${user.username}`; mentionNode.setAttribute("data-user-id", user.id); @@ -301,33 +301,6 @@ const RichTextEditor: React.FC = () => { } }; - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === "Backspace") { - const selection = window.getSelection(); - if (selection && selection.rangeCount > 0) { - const range = selection.getRangeAt(0); - const startContainer = range.startContainer; - - if ( - startContainer.nodeType === Node.TEXT_NODE && - startContainer.textContent === "@" - ) { - const parentNode = startContainer.parentNode; - if ( - parentNode && - parentNode.nodeName === "SPAN" && - parentNode instanceof HTMLElement && - parentNode.hasAttribute("data-user-id") - ) { - event.preventDefault(); - parentNode.parentNode?.removeChild(parentNode); - saveState(); - } - } - } - } - }; - const saveState = () => { const turndownService = new TurndownService(); turndownService.addRule("strikethrough", { @@ -336,12 +309,18 @@ const RichTextEditor: React.FC = () => { }); turndownService.addRule("mentions", { filter: (node) => { - return node.nodeName === "SPAN" && node.hasAttribute("data-user-id"); + return node.nodeName === "A" && node.hasAttribute("data-user-id"); }, replacement: (content, node) => { const userId = (node as HTMLElement).getAttribute("data-user-id"); const username = content.replace("@", ""); - return `[mention_user](user_id:${userId}, username:${username})`; + return `![mention_user](user_id:${userId}, username:${username})`; + }, + }); + turndownService.addRule("div", { + filter: "div", + replacement: function (content) { + return content + "\n"; }, }); @@ -357,7 +336,7 @@ const RichTextEditor: React.FC = () => {
{showMentions && ( @@ -477,7 +455,7 @@ const RichTextEditor: React.FC = () => {

Markdown Preview:

- {markdown} +

Markdown Output:

diff --git a/src/Components/Common/MarkdownPreview.tsx b/src/Components/Common/MarkdownPreview.tsx new file mode 100644 index 0000000000..ee7222e193 --- /dev/null +++ b/src/Components/Common/MarkdownPreview.tsx @@ -0,0 +1,20 @@ +import ReactMarkdown from "react-markdown"; +import rehypeRaw from "rehype-raw"; + +const MarkdownPreview = ({ markdown }: { markdown: string }) => { + const processedMarkdown = markdown + .replace( + /!\[mention_user\]\(user_id:(\d+), username:([^)]+)\)/g, + (_, userId, username) => + `@${username}`, + ) + .replace(/~(.*?)~/g, (_, text) => `${text}`); + + return ( + + {processedMarkdown} + + ); +}; + +export default MarkdownPreview; From d5a450ec719a2e1d24623dade2b3c79ed3c519ac Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sat, 6 Jul 2024 03:01:00 +0530 Subject: [PATCH 18/79] file uploads --- src/Components/Common/MarkdownEditor.tsx | 361 ++++++++++++++++++++++- src/Redux/api.tsx | 5 + 2 files changed, 363 insertions(+), 3 deletions(-) diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index 7a5bbdeca3..3e2a63fae6 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -10,10 +10,18 @@ import { FaQuoteRight, } from "react-icons/fa"; import { GoMention } from "react-icons/go"; -// import { MdAttachFile } from "react-icons/md"; +import { MdAttachFile } from "react-icons/md"; import TurndownService from "turndown"; import MentionsDropdown from "./MentionDropdown"; import MarkdownPreview from "./MarkdownPreview"; +import { ExtImage, StateInterface } from "../Patient/FileUpload"; +import imageCompression from "browser-image-compression"; +import { CreateFileResponse, FileUploadModel } from "../Patient/models"; +import uploadFile from "../../Utils/request/uploadFile"; +import * as Notification from "../../Utils/Notifications.js"; +import request from "../../Utils/request/request"; +import routes from "../../Redux/api"; +import FilePreviewDialog from "./FilePreviewDialog"; interface RichTextEditorProps { markdown?: string; @@ -78,6 +86,9 @@ const RichTextEditor: React.FC = () => { const [mentionPosition, setMentionPosition] = useState({ top: 0, left: 0 }); const lastCaretPosition = useRef(null); + const [file, setFile] = useState(null); + const [uploadFileName, setUploadFileName] = useState(""); + useEffect(() => { document.addEventListener("selectionchange", handleSelectionChange); return () => { @@ -330,6 +341,32 @@ const RichTextEditor: React.FC = () => { setHtmlCode(htmlContent); }; + const onFileChange = (e: any): any => { + if (!e.target.files?.length) { + return; + } + const f = e.target.files[0]; + const fileName = f.name; + setFile(e.target.files[0]); + setUploadFileName( + fileName.substring(0, fileName.lastIndexOf(".")) || fileName, + ); + + const ext: string = fileName.split(".")[1]; + + if (ExtImage.includes(ext)) { + const options = { + initialQuality: 0.6, + alwaysKeepResolution: true, + }; + imageCompression(f, options).then((compressedFile: File) => { + setFile(compressedFile); + }); + return; + } + setFile(f); + }; + return (
@@ -432,9 +469,14 @@ const RichTextEditor: React.FC = () => { > - {/* */} + +
@@ -445,6 +487,13 @@ const RichTextEditor: React.FC = () => { onInput={handleInput} >
+ + {showMentions && ( = () => { }; export default RichTextEditor; + +const FileUpload = ({ + file, + setFile, + uploadFileName, + setUploadFileName, +}: { + file: File | null; + setFile: React.Dispatch>; + uploadFileName: string; + setUploadFileName: React.Dispatch>; +}) => { + const [file_state, setFileState] = useState({ + open: false, + isImage: false, + name: "", + extension: "", + zoom: 4, + isZoomInDisabled: false, + isZoomOutDisabled: false, + rotation: 0, + }); + const [fileUrl, setFileUrl] = useState(""); + const [downloadURL, setDownloadURL] = useState(""); + const [uploadStarted, setUploadStarted] = useState(false); + const [uploadPercent, setUploadPercent] = useState(0); + const [uploadFileError, setUploadFileError] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const file_type = "NOTES"; + const [files, setFiles] = useState([]); + const [noteId, setNoteId] = useState( + "40faecc6-6199-48cd-bc2a-dd9e73b920f9", + ); + + const fetchData = useCallback(async () => { + setIsLoading(true); + + const res = await request(routes.viewUpload, { + query: { + file_type: file_type, + associating_id: noteId, + is_archived: false, + limit: 100, + offset: 0, + }, + }); + + if (res.data) { + setFiles(res.data.results); + } + + setIsLoading(false); + }, [noteId]); + + useEffect(() => { + fetchData(); + }, [fetchData]); + + const uploadfile = async (data: CreateFileResponse) => { + const url = data.signed_url; + const internal_name = data.internal_name; + const f = file; + if (!f) return; + const newFile = new File([f], `${internal_name}`); + return new Promise((resolve, reject) => { + uploadFile( + url, + newFile, + "PUT", + { "Content-Type": file?.type }, + (xhr: XMLHttpRequest) => { + if (xhr.status >= 200 && xhr.status < 300) { + setUploadStarted(false); + setFile(null); + setUploadFileName(""); + fetchData(); + Notification.Success({ + msg: "File Uploaded Successfully", + }); + setUploadFileError(""); + resolve(); + } else { + Notification.Error({ + msg: "Error Uploading File: " + xhr.statusText, + }); + setUploadStarted(false); + reject(); + } + }, + setUploadPercent, + () => { + Notification.Error({ + msg: "Error Uploading File: Network Error", + }); + setUploadStarted(false); + reject(); + }, + ); + }); + }; + + const validateFileUpload = () => { + const filenameLength = uploadFileName.trim().length; + const f = file; + if (f === undefined || f === null) { + setUploadFileError("Please choose a file to upload"); + return false; + } + if (filenameLength === 0) { + setUploadFileError("Please give a name !!"); + return false; + } + if (f.size > 10e7) { + setUploadFileError("Maximum size of files is 100 MB"); + return false; + } + return true; + }; + const markUploadComplete = (data: CreateFileResponse) => { + return request(routes.editUpload, { + body: { upload_completed: true }, + pathParams: { + id: data.id, + fileType: file_type, + associatingId: noteId, + }, + }); + }; + + const handleUpload = async () => { + if (!validateFileUpload()) return; + const f = file; + + const category = "UNSPECIFIED"; + const filename = uploadFileName === "" && f ? f.name : uploadFileName; + const name = f?.name; + setUploadStarted(true); + + const { data } = await request(routes.createUpload, { + body: { + original_name: name ?? "", + file_type: file_type, + name: filename, + associating_id: noteId, + file_category: category, + mime_type: f?.type ?? "", + }, + }); + + if (data) { + await uploadfile(data); + await markUploadComplete(data); + await fetchData(); + } + }; + const getExtension = (url: string) => { + const div1 = url.split("?")[0].split("."); + const ext: string = div1[div1.length - 1].toLowerCase(); + return ext; + }; + const downloadFileUrl = (url: string) => { + fetch(url) + .then((res) => res.blob()) + .then((blob) => { + setDownloadURL(URL.createObjectURL(blob)); + }); + }; + + const loadFile = async (id: string) => { + setFileUrl(""); + setFileState({ ...file_state, open: true }); + const { data } = await request(routes.retrieveUpload, { + query: { + file_type: file_type, + associating_id: noteId, + }, + pathParams: { id }, + }); + + if (!data) return; + + const signedUrl = data.read_signed_url as string; + const extension = getExtension(signedUrl); + + setFileState({ + ...file_state, + open: true, + name: data.name as string, + extension, + isImage: ExtImage.includes(extension), + }); + downloadFileUrl(signedUrl); + setFileUrl(signedUrl); + }; + + const handleClose = () => { + setDownloadURL(""); + setFileState({ + ...file_state, + open: false, + zoom: 4, + isZoomInDisabled: false, + isZoomOutDisabled: false, + }); + }; + + return ( +
+ +
+
+

Note Id:

+ setNoteId(e.target.value)} + /> +
+
+ + +
+ {uploadFileError && ( +

{uploadFileError}

+ )} + {uploadStarted && ( +
+
+
+
+

+ {uploadPercent}% uploaded +

+
+ )} +
+
+

Uploaded Files:

+
+ {isLoading ? ( +

Loading...

+ ) : ( + <> +
+ {files.map((file) => ( +
+

{file.name}

+ + +
+ ))} +
+ + )} +
+
+
+ ); +}; diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 8cda2038ec..83a2466ac3 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -1148,6 +1148,11 @@ const routes = { TBody: Type>(), TRes: Type(), }, + deleteUpload: { + path: "/api/v1/files/{id}/?file_type={fileType}&associating_id={associatingId}", + method: "DELETE", + TRes: Type>(), + }, // Investigation listInvestigations: { From ccafa0fcc60c9eabd86c72979fba9ad2f7f7a3ff Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sat, 6 Jul 2024 03:56:06 +0530 Subject: [PATCH 19/79] improved ui --- src/Components/Common/MarkdownEditor.tsx | 133 ++++++++++++----------- 1 file changed, 71 insertions(+), 62 deletions(-) diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index 3e2a63fae6..5e0ed692e4 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -8,7 +8,9 @@ import { FaUnlink, FaStrikethrough, FaQuoteRight, + FaFile, } from "react-icons/fa"; +import { RxCross2 } from "react-icons/rx"; import { GoMention } from "react-icons/go"; import { MdAttachFile } from "react-icons/md"; import TurndownService from "turndown"; @@ -88,6 +90,11 @@ const RichTextEditor: React.FC = () => { const [file, setFile] = useState(null); const [uploadFileName, setUploadFileName] = useState(""); + const fileInputRef = useRef(null); + + const triggerFileInput = () => { + fileInputRef.current?.click(); + }; useEffect(() => { document.addEventListener("selectionchange", handleSelectionChange); @@ -368,10 +375,10 @@ const RichTextEditor: React.FC = () => { }; return ( -
+
-
-
+
+
- +
@@ -742,17 +754,46 @@ const FileUpload = ({ fixedWidth={false} className="h-[80vh] w-full md:h-screen" /> +
+ {isLoading ? ( +

Loading...

+ ) : ( + <> + {files.map((file) => ( +
+ +
loadFile(file.id!)} + > + + + {file.name} + +
+
+ ))} + + )} +
-
-

Note Id:

- setNoteId(e.target.value)} - /> -
)} -
-
-

Uploaded Files:

-
- {isLoading ? ( -

Loading...

- ) : ( - <> -
- {files.map((file) => ( -
-

{file.name}

- - -
- ))} -
- - )} +
+

Note Id:

+ setNoteId(e.target.value)} + />
From c2709a180bbd37336e1105274e835724c39eca3e Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sun, 7 Jul 2024 03:15:59 +0530 Subject: [PATCH 20/79] bug fix for file preview --- src/Components/Common/FilePreviewDialog.tsx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Components/Common/FilePreviewDialog.tsx b/src/Components/Common/FilePreviewDialog.tsx index 3f55621e8c..a8f455bc07 100644 --- a/src/Components/Common/FilePreviewDialog.tsx +++ b/src/Components/Common/FilePreviewDialog.tsx @@ -33,16 +33,17 @@ type FilePreviewProps = { }; const previewExtensions = [ - ".html", - ".htm", - ".pdf", - ".mp4", - ".webm", - ".jpg", - ".jpeg", - ".png", - ".gif", - ".webp", + "html", + "htm", + "pdf", + "mp4", + "mp3", + "webm", + "jpg", + "jpeg", + "png", + "gif", + "webp", ]; const FilePreviewDialog = (props: FilePreviewProps) => { From 704cfba5d409fcf055af6f23bb6ba993dea6f1d5 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Sun, 7 Jul 2024 03:19:30 +0530 Subject: [PATCH 21/79] support for camera captures and audio recordings --- src/Components/Common/MarkdownEditor.tsx | 361 ++++++++++++++++++++++- 1 file changed, 357 insertions(+), 4 deletions(-) diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index 5e0ed692e4..8e8aa38907 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -10,6 +10,8 @@ import { FaQuoteRight, FaFile, } from "react-icons/fa"; +import { FaCamera } from "react-icons/fa6"; +import { AiFillAudio } from "react-icons/ai"; import { RxCross2 } from "react-icons/rx"; import { GoMention } from "react-icons/go"; import { MdAttachFile } from "react-icons/md"; @@ -24,6 +26,12 @@ import * as Notification from "../../Utils/Notifications.js"; import request from "../../Utils/request/request"; import routes from "../../Redux/api"; import FilePreviewDialog from "./FilePreviewDialog"; +import DialogModal from "./Dialog"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import Webcam from "react-webcam"; +import ButtonV2, { Submit } from "./components/ButtonV2"; +import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; +import useRecorder from "../../Utils/useRecorder"; interface RichTextEditorProps { markdown?: string; @@ -92,6 +100,75 @@ const RichTextEditor: React.FC = () => { const [uploadFileName, setUploadFileName] = useState(""); const fileInputRef = useRef(null); + const [audioBlob, setAudioBlob] = useState(); + const [audioBlobExists, setAudioBlobExists] = useState(false); + const [resetAudioRecording, setAudioResetRecording] = useState(false); + const [isMicPermission, setIsMicPermission] = useState(true); + + const [modalOpenForCamera, setModalOpenForCamera] = useState(false); + const [previewImage, setPreviewImage] = useState(null); + const webRef = useRef(null); + const FACING_MODE_USER = "user"; + const FACING_MODE_ENVIRONMENT = { exact: "environment" }; + const [facingMode, setFacingMode] = useState(FACING_MODE_USER); + const { width } = useWindowDimensions(); + const LaptopScreenBreakpoint = 640; + const isLaptopScreen = width >= LaptopScreenBreakpoint ? true : false; + const videoConstraints = { + width: isLaptopScreen ? 1280 : 480, + height: isLaptopScreen ? 720 : 720, + facingMode: "user", + }; + const handleSwitchCamera = useCallback(() => { + setFacingMode((prevState: any) => + prevState === FACING_MODE_USER + ? FACING_MODE_ENVIRONMENT + : FACING_MODE_USER, + ); + }, []); + + const captureImage = () => { + setPreviewImage(webRef.current.getScreenshot()); + const canvas = webRef.current.getCanvas(); + canvas?.toBlob((blob: Blob) => { + const extension = blob.type.split("/").pop(); + const myFile = new File([blob], `image.${extension}`, { + type: blob.type, + }); + setFile(myFile); + }); + }; + + const handleUploadCameraImage = () => { + setFile(file); + setModalOpenForCamera(false); + setUploadFileName("Camera Capture"); + }; + + useEffect(() => { + const checkMicPermission = async () => { + try { + const permissions = await navigator.permissions.query({ + name: "microphone" as PermissionName, + }); + setIsMicPermission(permissions.state === "granted"); + } catch (error) { + setIsMicPermission(false); + } + }; + + checkMicPermission(); + + return () => { + setIsMicPermission(true); + }; + }, []); + + const deleteAudioBlob = () => { + setAudioBlobExists(false); + setAudioResetRecording(true); + }; + const triggerFileInput = () => { fileInputRef.current?.click(); }; @@ -374,8 +451,189 @@ const RichTextEditor: React.FC = () => { setFile(f); }; + const handleAudioUpload = () => { + if (!audioBlob) return; + const f = new File([audioBlob], "audio.mp3", { + type: audioBlob.type, + }); + setFile(f); + setUploadFileName("Audio Recording"); + }; + + const [ + audioURL, + isRecording, + startRecording, + stopRecording, + newBlob, + resetRecording, + ] = useRecorder(setIsMicPermission); + const [time, setTime] = useState(0); + useEffect(() => { + setAudioBlob(newBlob); + let interval: any; + if (isRecording) { + interval = setInterval(() => { + setTime((prevTime) => prevTime + 10); + }, 10); + } else { + clearInterval(interval); + setTime(0); + } + if (resetAudioRecording) { + resetRecording(); + setAudioResetRecording(false); + } + return () => clearInterval(interval); + }, [isRecording, newBlob, resetAudioRecording]); + return (
+ +
+ +
+
+

Camera

+
+
+ } + className="max-w-2xl" + onClose={() => setModalOpenForCamera(false)} + > +
+ {!previewImage ? ( +
+ +
+ ) : ( +
+ +
+ )} +
+ + {/* buttons for mobile screens */} +
+
+ {!previewImage ? ( + + switch + + ) : ( + <> + )} +
+
+ {!previewImage ? ( + <> +
+ { + captureImage(); + }} + className="m-2" + > + capture + +
+ + ) : ( + <> +
+ { + setPreviewImage(null); + }} + className="m-2" + > + retake + + + submit + +
+ + )} +
+
+ { + setPreviewImage(null); + setModalOpenForCamera(false); + }} + className="m-2" + > + close + +
+
+ {/* buttons for laptop screens */} +