diff --git a/space/components/issues/board-views/block-due-date.tsx b/space/components/issues/board-views/block-due-date.tsx index ecf229562..3b73973e7 100644 --- a/space/components/issues/board-views/block-due-date.tsx +++ b/space/components/issues/board-views/block-due-date.tsx @@ -1,59 +1,32 @@ "use client"; +import { CalendarCheck2 } from "lucide-react"; +// types +import { TStateGroups } from "@plane/types"; // helpers -import { renderFullDate } from "@/helpers/date-time.helper"; +import { cn } from "@/helpers/common.helper"; +import { renderFormattedDate } from "@/helpers/date-time.helper"; +import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper"; -export const dueDateIconDetails = ( - date: string, - stateGroup: string -): { - iconName: string; - className: string; -} => { - let iconName = "calendar_today"; - let className = ""; - - if (!date || ["completed", "cancelled"].includes(stateGroup)) { - iconName = "calendar_today"; - className = ""; - } else { - const today = new Date(); - today.setHours(0, 0, 0, 0); - const targetDate = new Date(date); - targetDate.setHours(0, 0, 0, 0); - - const timeDifference = targetDate.getTime() - today.getTime(); - - if (timeDifference < 0) { - iconName = "event_busy"; - className = "text-red-500"; - } else if (timeDifference === 0) { - iconName = "today"; - className = "text-red-500"; - } else if (timeDifference === 24 * 60 * 60 * 1000) { - iconName = "event"; - className = "text-yellow-500"; - } else { - iconName = "calendar_today"; - className = ""; - } - } - - return { - iconName, - className, - }; +type Props = { + due_date: string; + group: TStateGroups; }; -export const IssueBlockDueDate = ({ due_date, group }: { due_date: string; group: string }) => { - const iconDetails = dueDateIconDetails(due_date, group); +export const IssueBlockDueDate = (props: Props) => { + const { due_date, group } = props; return ( -
- - {iconDetails.iconName} - - {renderFullDate(due_date)} +
+ + {renderFormattedDate(due_date)}
); }; diff --git a/space/components/issues/board-views/block-priority.tsx b/space/components/issues/board-views/block-priority.tsx index 3110930ec..b91d56bb8 100644 --- a/space/components/issues/board-views/block-priority.tsx +++ b/space/components/issues/board-views/block-priority.tsx @@ -1,11 +1,11 @@ "use client"; // types -import { issuePriorityFilter } from "@/constants/issue"; -import { TIssueFilterPriority } from "@/types/issue"; +import { TIssuePriorities } from "@plane/types"; // constants +import { issuePriorityFilter } from "@/constants/issue"; -export const IssueBlockPriority = ({ priority }: { priority: TIssueFilterPriority | null }) => { +export const IssueBlockPriority = ({ priority }: { priority: TIssuePriorities | null }) => { const priority_detail = priority != null ? issuePriorityFilter(priority) : null; if (priority_detail === null) return <>; diff --git a/space/components/issues/board-views/kanban/header.tsx b/space/components/issues/board-views/kanban/header.tsx index baf5612b3..f40812f75 100644 --- a/space/components/issues/board-views/kanban/header.tsx +++ b/space/components/issues/board-views/kanban/header.tsx @@ -1,16 +1,14 @@ "use client"; -// mobx react lite + import { observer } from "mobx-react-lite"; +// types +import { IStateLite } from "@plane/types"; // ui import { StateGroupIcon } from "@plane/ui"; // constants import { issueGroupFilter } from "@/constants/issue"; -// mobx hook -// import { useIssue } from "@/hooks/store"; -// interfaces -import { IIssueState } from "@/types/issue"; -export const IssueKanBanHeader = observer(({ state }: { state: IIssueState }) => { +export const IssueKanBanHeader = observer(({ state }: { state: IStateLite }) => { // const { getCountOfIssuesByState } = useIssue(); const stateGroup = issueGroupFilter(state.group); @@ -21,7 +19,7 @@ export const IssueKanBanHeader = observer(({ state }: { state: IIssueState }) =>
-
{state?.name}
+
{state?.name}
{/* {getCountOfIssuesByState(state.id)} */}
); diff --git a/space/components/issues/board-views/list/header.tsx b/space/components/issues/board-views/list/header.tsx index 2f8f6c018..c7dd6e50d 100644 --- a/space/components/issues/board-views/list/header.tsx +++ b/space/components/issues/board-views/list/header.tsx @@ -1,15 +1,14 @@ "use client"; + import { observer } from "mobx-react-lite"; +// types +import { IStateLite } from "@plane/types"; // ui import { StateGroupIcon } from "@plane/ui"; // constants import { issueGroupFilter } from "@/constants/issue"; -// mobx hook -// import { useIssue } from "@/hooks/store"; -// types -import { IIssueState } from "@/types/issue"; -export const IssueListHeader = observer(({ state }: { state: IIssueState }) => { +export const IssueListHeader = observer(({ state }: { state: IStateLite }) => { // const { getCountOfIssuesByState } = useIssue(); const stateGroup = issueGroupFilter(state.group); // const count = getCountOfIssuesByState(state.id); diff --git a/space/components/issues/filters/applied-filters/filters-list.tsx b/space/components/issues/filters/applied-filters/filters-list.tsx index 83d651f5d..87089c500 100644 --- a/space/components/issues/filters/applied-filters/filters-list.tsx +++ b/space/components/issues/filters/applied-filters/filters-list.tsx @@ -1,10 +1,10 @@ "use client"; -// icons import { observer } from "mobx-react-lite"; import { X } from "lucide-react"; // types -import { IIssueLabel, IIssueState, TFilters } from "@/types/issue"; +import { IStateLite } from "@plane/types"; +import { IIssueLabel, TFilters } from "@/types/issue"; // components import { AppliedPriorityFilters } from "./priority"; import { AppliedStateFilters } from "./state"; @@ -14,7 +14,7 @@ type Props = { handleRemoveAllFilters: () => void; handleRemoveFilter: (key: keyof TFilters, value: string | null) => void; labels?: IIssueLabel[] | undefined; - states?: IIssueState[] | undefined; + states?: IStateLite[] | undefined; }; export const replaceUnderscoreIfSnakeCase = (str: string) => str.replace(/_/g, " "); diff --git a/space/components/issues/filters/applied-filters/root.tsx b/space/components/issues/filters/applied-filters/root.tsx index 5d6a404ed..9b6625d75 100644 --- a/space/components/issues/filters/applied-filters/root.tsx +++ b/space/components/issues/filters/applied-filters/root.tsx @@ -80,7 +80,7 @@ export const IssueAppliedFilters: FC = observer((props) => if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
void; - states: IIssueState[]; + states: IStateLite[]; values: string[]; }; diff --git a/space/components/issues/filters/selection.tsx b/space/components/issues/filters/selection.tsx index a1180b0ee..926fbf5b0 100644 --- a/space/components/issues/filters/selection.tsx +++ b/space/components/issues/filters/selection.tsx @@ -4,7 +4,8 @@ import React, { useState } from "react"; import { observer } from "mobx-react-lite"; import { Search, X } from "lucide-react"; // types -import { IIssueState, IIssueLabel, IIssueFilterOptions, TIssueFilterKeys } from "@/types/issue"; +import { IStateLite } from "@plane/types"; +import { IIssueLabel, IIssueFilterOptions, TIssueFilterKeys } from "@/types/issue"; // components import { FilterPriority, FilterState } from "./"; @@ -13,7 +14,7 @@ type Props = { handleFilters: (key: keyof IIssueFilterOptions, value: string | string[]) => void; layoutDisplayFiltersOptions: TIssueFilterKeys[]; labels?: IIssueLabel[] | undefined; - states?: IIssueState[] | undefined; + states?: IStateLite[] | undefined; }; export const FilterSelection: React.FC = observer((props) => { diff --git a/space/components/issues/filters/state.tsx b/space/components/issues/filters/state.tsx index 24b6bb5c8..f61237eef 100644 --- a/space/components/issues/filters/state.tsx +++ b/space/components/issues/filters/state.tsx @@ -1,17 +1,18 @@ "use client"; import React, { useState } from "react"; +// types +import { IStateLite } from "@plane/types"; +// ui import { Loader, StateGroupIcon } from "@plane/ui"; // components import { FilterHeader, FilterOption } from "@/components/issues/filters/helpers"; -// types -import { IIssueState } from "@/types/issue"; type Props = { appliedFilters: string[] | null; handleUpdate: (val: string) => void; searchQuery: string; - states: IIssueState[] | undefined; + states: IStateLite[] | undefined; }; export const FilterState: React.FC = (props) => { diff --git a/space/components/issues/peek-overview/issue-properties.tsx b/space/components/issues/peek-overview/issue-properties.tsx index 08d22b312..9ec754057 100644 --- a/space/components/issues/peek-overview/issue-properties.tsx +++ b/space/components/issues/peek-overview/issue-properties.tsx @@ -1,16 +1,17 @@ +import { CalendarCheck2 } from "lucide-react"; // ui import { StateGroupIcon, TOAST_TYPE, setToast } from "@plane/ui"; -// icons +// components import { Icon } from "@/components/ui"; // constants import { issueGroupFilter, issuePriorityFilter } from "@/constants/issue"; // helpers -import { renderFullDate } from "@/helpers/date-time.helper"; +import { cn } from "@/helpers/common.helper"; +import { renderFormattedDate } from "@/helpers/date-time.helper"; +import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper"; import { copyTextToClipboard, addSpaceIfCamelCase } from "@/helpers/string.helper"; // types import { IIssue, IPeekMode } from "@/types/issue"; -// components -import { dueDateIconDetails } from "../board-views/block-due-date"; type Props = { issueDetails: IIssue; @@ -23,8 +24,6 @@ export const PeekOverviewIssueProperties: React.FC = ({ issueDetails, mod const priority = issueDetails.priority ? issuePriorityFilter(issueDetails.priority) : null; - const dueDateIcon = dueDateIconDetails(issueDetails.target_date, state.group); - const handleCopyLink = () => { const urlToCopy = window.location.href; @@ -104,11 +103,19 @@ export const PeekOverviewIssueProperties: React.FC = ({ issueDetails, mod
{issueDetails.target_date ? ( -
- - {dueDateIcon.iconName} - - {renderFullDate(issueDetails.target_date)} +
+ + {renderFormattedDate(issueDetails.target_date)}
) : ( Empty diff --git a/space/constants/issue.ts b/space/constants/issue.ts index fb9c78fcd..f96eb3e0e 100644 --- a/space/constants/issue.ts +++ b/space/constants/issue.ts @@ -1,13 +1,13 @@ -// interfaces +// types +import { TIssuePriorities } from "@plane/types"; import { TIssueLayout, TIssueLayoutViews, TIssueFilterKeys, - TIssueFilterPriority, TIssueFilterPriorityObject, TIssueFilterState, TIssueFilterStateObject, -} from "types/issue"; +} from "@/types/issue"; // issue filters export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: { [key in TIssueLayout]: Record<"filters", TIssueFilterKeys[]> } = { @@ -75,7 +75,7 @@ export const issuePriorityFilters: TIssueFilterPriorityObject[] = [ }, ]; -export const issuePriorityFilter = (priorityKey: TIssueFilterPriority): TIssueFilterPriorityObject | undefined => { +export const issuePriorityFilter = (priorityKey: TIssuePriorities): TIssueFilterPriorityObject | undefined => { const currentIssuePriority: TIssueFilterPriorityObject | undefined = issuePriorityFilters && issuePriorityFilters.length > 0 ? issuePriorityFilters.find((_priority) => _priority.key === priorityKey) diff --git a/space/constants/state.ts b/space/constants/state.ts new file mode 100644 index 000000000..b0fd622be --- /dev/null +++ b/space/constants/state.ts @@ -0,0 +1,37 @@ +import { TStateGroups } from "@plane/types"; + +export const STATE_GROUPS: { + [key in TStateGroups]: { + key: TStateGroups; + label: string; + color: string; + }; +} = { + backlog: { + key: "backlog", + label: "Backlog", + color: "#d9d9d9", + }, + unstarted: { + key: "unstarted", + label: "Unstarted", + color: "#3f76ff", + }, + started: { + key: "started", + label: "Started", + color: "#f59e0b", + }, + completed: { + key: "completed", + label: "Completed", + color: "#16a34a", + }, + cancelled: { + key: "cancelled", + label: "Canceled", + color: "#dc2626", + }, +}; + +export const ARCHIVABLE_STATE_GROUPS = [STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key]; diff --git a/space/helpers/date-time.helper.ts b/space/helpers/date-time.helper.ts index f19a5358b..3930bcb83 100644 --- a/space/helpers/date-time.helper.ts +++ b/space/helpers/date-time.helper.ts @@ -1,3 +1,6 @@ +import { format, isValid } from "date-fns"; +import isNumber from "lodash/isNumber"; + export const timeAgo = (time: any) => { switch (typeof time) { case "number": @@ -14,24 +17,43 @@ export const timeAgo = (time: any) => { }; /** - * @description Returns date and month, if date is of the current year - * @description Returns date, month adn year, if date is of a different year than current - * @param {string} date - * @example renderFullDate("2023-01-01") // 1 Jan - * @example renderFullDate("2021-01-01") // 1 Jan, 2021 + * This method returns a date from string of type yyyy-mm-dd + * This method is recommended to use instead of new Date() as this does not introduce any timezone offsets + * @param date + * @returns date or undefined */ +export const getDate = (date: string | Date | undefined | null): Date | undefined => { + try { + if (!date || date === "") return; -export const renderFullDate = (date: string): string => { - if (!date) return ""; + if (typeof date !== "string" && !(date instanceof String)) return date; - const months: string[] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + const [yearString, monthString, dayString] = date.substring(0, 10).split("-"); + const year = parseInt(yearString); + const month = parseInt(monthString); + const day = parseInt(dayString); + if (!isNumber(year) || !isNumber(month) || !isNumber(day)) return; - const currentDate: Date = new Date(); - const [year, month, day]: number[] = date.split("-").map(Number); - - const formattedMonth: string = months[month - 1]; - const formattedDay: string = day < 10 ? `0${day}` : day.toString(); - - if (currentDate.getFullYear() === year) return `${formattedDay} ${formattedMonth}`; - else return `${formattedDay} ${formattedMonth}, ${year}`; + return new Date(year, month - 1, day); + } catch (e) { + return undefined; + } +}; + +/** + * @returns {string | null} formatted date in the format of MMM dd, yyyy + * @description Returns date in the formatted format + * @param {Date | string} date + * @example renderFormattedDate("2024-01-01") // Jan 01, 2024 + */ +export const renderFormattedDate = (date: string | Date | undefined | null): string | null => { + // Parse the date to check if it is valid + const parsedDate = getDate(date); + // return if undefined + if (!parsedDate) return null; + // Check if the parsed date is valid before formatting + if (!isValid(parsedDate)) return null; // Return null for invalid dates + // Format the date in format (MMM dd, yyyy) + const formattedDate = format(parsedDate, "MMM dd, yyyy"); + return formattedDate; }; diff --git a/space/helpers/issue.helper.ts b/space/helpers/issue.helper.ts new file mode 100644 index 000000000..a5159edef --- /dev/null +++ b/space/helpers/issue.helper.ts @@ -0,0 +1,30 @@ +import { differenceInCalendarDays } from "date-fns"; +// types +import { TStateGroups } from "@plane/types"; +// constants +import { STATE_GROUPS } from "@/constants/state"; +// helpers +import { getDate } from "@/helpers/date-time.helper"; + +/** + * @description check if the issue due date should be highlighted + * @param date + * @param stateGroup + * @returns boolean + */ +export const shouldHighlightIssueDueDate = ( + date: string | Date | null, + stateGroup: TStateGroups | undefined +): boolean => { + if (!date || !stateGroup) return false; + // if the issue is completed or cancelled, don't highlight the due date + if ([STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateGroup)) return false; + + const parsedDate = getDate(date); + if (!parsedDate) return false; + + const targetDateDistance = differenceInCalendarDays(parsedDate, new Date()); + + // if the issue is overdue, highlight the due date + return targetDateDistance <= 0; +}; diff --git a/space/package.json b/space/package.json index e3dadbff8..0932d7abf 100644 --- a/space/package.json +++ b/space/package.json @@ -26,6 +26,7 @@ "@sentry/nextjs": "^8", "axios": "^1.3.4", "clsx": "^2.0.0", + "date-fns": "^3.6.0", "dompurify": "^3.0.11", "dotenv": "^16.3.1", "js-cookie": "^3.0.1", diff --git a/space/store/issue.store.ts b/space/store/issue.store.ts index 4595c6a1d..4f2d845b5 100644 --- a/space/store/issue.store.ts +++ b/space/store/issue.store.ts @@ -1,9 +1,11 @@ import { observable, action, makeObservable, runInAction } from "mobx"; import { computedFn } from "mobx-utils"; +// types +import { IStateLite } from "@plane/types"; // services import IssueService from "@/services/issue.service"; // types -import { IIssue, IIssueState, IIssueLabel } from "@/types/issue"; +import { IIssue, IIssueLabel } from "@/types/issue"; // store import { RootStore } from "./root.store"; @@ -12,7 +14,7 @@ export interface IIssueStore { error: any; // observables issues: IIssue[]; - states: IIssueState[]; + states: IStateLite[]; labels: IIssueLabel[]; // filter observables filteredStates: string[]; @@ -29,7 +31,7 @@ export class IssueStore implements IIssueStore { loader: boolean = false; error: any | null = null; // observables - states: IIssueState[] = []; + states: IStateLite[] = []; labels: IIssueLabel[] = []; issues: IIssue[] = []; // filter observables diff --git a/space/store/publish/publish.store.ts b/space/store/publish/publish.store.ts index 066da6390..c90eb5bf9 100644 --- a/space/store/publish/publish.store.ts +++ b/space/store/publish/publish.store.ts @@ -1,8 +1,10 @@ import { observable, makeObservable, computed } from "mobx"; +// types +import { IWorkspaceLite } from "@plane/types"; // store types import { RootStore } from "@/store/root.store"; // types -import { TProjectDetails, TViewDetails, TWorkspaceDetails } from "@/types/project"; +import { TProjectDetails, TViewDetails } from "@/types/project"; import { TPublishEntityType, TPublishSettings } from "@/types/publish"; export interface IPublishStore extends TPublishSettings { @@ -31,7 +33,7 @@ export class PublishStore implements IPublishStore { view_props: TViewDetails | undefined; votes: boolean; workspace: string | undefined; - workspace_detail: TWorkspaceDetails | undefined; + workspace_detail: IWorkspaceLite | undefined; constructor( private store: RootStore, diff --git a/space/types/issue.d.ts b/space/types/issue.d.ts index 00bc740d5..3f2c41451 100644 --- a/space/types/issue.d.ts +++ b/space/types/issue.d.ts @@ -1,14 +1,19 @@ +import { IStateLite, IWorkspaceLite, TIssuePriorities } from "@plane/types"; + export type TIssueLayout = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt"; export type TIssueLayoutOptions = { [key in TIssueLayout]: boolean; }; export type TIssueLayoutViews = { - [key in TIssueLayout]: { title: string; icon: string; className: string }; + [key in TIssueLayout]: { + title: string; + icon: string; + className: string; + }; }; -export type TIssueFilterPriority = "urgent" | "high" | "medium" | "low" | "none"; export type TIssueFilterPriorityObject = { - key: TIssueFilterPriority; + key: TIssuePriorities; title: string; className: string; icon: string; @@ -30,7 +35,7 @@ export type TDisplayFilters = { export type TFilters = { state: TIssueFilterState[]; - priority: TIssueFilterPriority[]; + priority: TIssuePriorities[]; labels: string[]; }; @@ -44,7 +49,7 @@ export type TIssueQueryFilters = Partial; export type TIssueQueryFiltersParams = Partial>; export type TIssuesResponse = { - states: IIssueState[]; + states: IStateLite[]; labels: IIssueLabel[]; issues: IIssue[]; }; @@ -74,13 +79,6 @@ export interface IIssue { export type IPeekMode = "side" | "modal" | "full"; -export interface IIssueState { - id: string; - name: string; - group: TIssueGroupKey; - color: string; -} - export interface IIssueLabel { id: string; name: string; @@ -121,7 +119,7 @@ export interface Comment { updated_at: Date; updated_by: string; workspace: string; - workspace_detail: WorkspaceDetail; + workspace_detail: IWorkspaceLite; } export interface IIssueReaction { @@ -182,52 +180,8 @@ export interface ProjectDetail { description: string; } -export interface WorkspaceDetail { - name: string; - slug: string; - id: string; -} - -export interface IssueDetailType { - [issueId: string]: { - issue: IIssue; - comments: Comment[]; - reactions: any[]; - votes: any[]; - }; -} - -export type TIssueGroupByOptions = "state" | "priority" | "labels" | null; - -export type TIssueParams = "priority" | "state" | "labels"; - export interface IIssueFilterOptions { state?: string[] | null; labels?: string[] | null; priority?: string[] | null; } - -// issues -export interface IGroupedIssues { - [group_id: string]: string[]; -} - -export interface ISubGroupedIssues { - [sub_grouped_id: string]: { - [group_id: string]: string[]; - }; -} - -export type TUnGroupedIssues = string[]; - -export interface IIssueResponse { - [issue_id: string]: IIssue; -} - -export type TLoader = "init-loader" | "mutation" | undefined; - -export interface ViewFlags { - enableQuickAdd: boolean; - enableIssueCreation: boolean; - enableInlineEditing: boolean; -} diff --git a/space/types/project.d.ts b/space/types/project.d.ts index 3ef979c05..c0ae02583 100644 --- a/space/types/project.d.ts +++ b/space/types/project.d.ts @@ -1,11 +1,5 @@ import { TLogoProps } from "@plane/types"; -export type TWorkspaceDetails = { - name: string; - slug: string; - id: string; -}; - export type TViewDetails = { list: boolean; gantt: boolean; diff --git a/space/types/publish.d.ts b/space/types/publish.d.ts index d9c1387c4..726412978 100644 --- a/space/types/publish.d.ts +++ b/space/types/publish.d.ts @@ -1,4 +1,5 @@ -import { TProjectDetails, TViewDetails, TWorkspaceDetails } from "./project"; +import { IWorkspaceLite } from "@plane/types"; +import { TProjectDetails, TViewDetails } from "./project"; export type TPublishEntityType = "project"; @@ -19,5 +20,5 @@ export type TPublishSettings = { view_props: TViewDetails | undefined; votes: boolean; workspace: string | undefined; - workspace_detail: TWorkspaceDetails | undefined; + workspace_detail: IWorkspaceLite | undefined; }; diff --git a/yarn.lock b/yarn.lock index 05aec74bf..a2f58cf6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6281,6 +6281,11 @@ date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" +date-fns@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf" + integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -10681,7 +10686,7 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -"prettier-fallback@npm:prettier@^3": +"prettier-fallback@npm:prettier@^3", prettier@^3.1.1, prettier@^3.2.5, prettier@latest: version "3.3.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== @@ -10708,11 +10713,6 @@ prettier@^2.8.8: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -prettier@^3.1.1, prettier@^3.2.5, prettier@latest: - version "3.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" - integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== - pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" @@ -12112,16 +12112,7 @@ string-argv@~0.3.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -12217,14 +12208,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -13648,16 +13632,7 @@ workbox-window@6.6.1, workbox-window@^6.5.4: "@types/trusted-types" "^2.0.2" workbox-core "6.6.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==