From 7a898680bf92b2fa2a0c2220177845d0aee30ee2 Mon Sep 17 00:00:00 2001 From: sriramveeraghanta Date: Mon, 31 Aug 2026 20:00:55 +0530 Subject: [PATCH] refactor(space): migrate from @plane/propel to @makeplane/propel - Drop the @plane/propel workspace dependency from apps/space - Buttons/tooltips/toast switched to @makeplane/propel APIs (label-based Button, label/side Tooltip, manager-based toast adapter mirroring admin) - Simple icons renamed to @makeplane/propel/icons equivalents - Domain icons (StateGroup/Priority/CycleGroup) and Plane brand assets vendored into apps/space/components/icons - Emoji reactions reimplemented locally on frimousse + propel popover (apps/space/components/emoji); animated counter dropped - Remove dead react-day-picker stylesheet import from space globals - Clean stale @plane/propel comments in admin --- apps/admin/components/common/skeleton.tsx | 3 +- apps/admin/providers/toast.tsx | 3 +- apps/space/app/error.tsx | 9 +- .../account/auth-forms/auth-banner.tsx | 4 +- .../components/account/auth-forms/email.tsx | 16 +- .../account/auth-forms/password.tsx | 43 +++--- .../account/auth-forms/unique-code.tsx | 16 +- .../components/account/user-logged-in.tsx | 2 +- apps/space/components/common/powered-by.tsx | 4 +- apps/space/components/editor/toolbar.tsx | 21 +-- .../emoji/emoji-reaction-picker.tsx | 141 ++++++++++++++++++ .../space/components/emoji/emoji-reaction.tsx | 110 ++++++++++++++ apps/space/components/emoji/helpers.ts | 38 +++++ apps/space/components/emoji/index.ts | 10 ++ .../components/icons/brand/plane-lockup.tsx | 51 +++++++ .../components/icons/brand/plane-logo.tsx | 27 ++++ .../icons/cycle/circle-dot-full-icon.tsx | 24 +++ .../icons/cycle/cycle-group-icon.tsx | 39 +++++ apps/space/components/icons/cycle/helper.tsx | 33 ++++ apps/space/components/icons/icon-wrapper.tsx | 50 +++++++ apps/space/components/icons/index.ts | 15 ++ apps/space/components/icons/priority-icon.tsx | 84 +++++++++++ .../components/icons/project/cycle-icon.tsx | 27 ++++ .../icons/state/backlog-group-icon.tsx | 28 ++++ .../icons/state/cancelled-group-icon.tsx | 35 +++++ .../icons/state/completed-group-icon.tsx | 35 +++++ .../components/icons/state/dashed-circle.tsx | 46 ++++++ apps/space/components/icons/state/helper.tsx | 48 ++++++ .../icons/state/progress-circle.tsx | 33 ++++ .../icons/state/started-group-icon.tsx | 71 +++++++++ .../icons/state/state-group-icon.tsx | 44 ++++++ .../icons/state/unstarted-group-icon.tsx | 57 +++++++ apps/space/components/icons/type.ts | 10 ++ .../instance/instance-failure-view.tsx | 6 +- .../filters/applied-filters/filters-list.tsx | 6 +- .../issues/filters/applied-filters/label.tsx | 4 +- .../filters/applied-filters/priority.tsx | 7 +- .../issues/filters/applied-filters/state.tsx | 6 +- .../issues/filters/helpers/dropdown.tsx | 8 +- .../issues/filters/helpers/filter-header.tsx | 4 +- .../issues/filters/helpers/filter-option.tsx | 4 +- .../components/issues/filters/priority.tsx | 3 +- .../components/issues/filters/selection.tsx | 6 +- .../space/components/issues/filters/state.tsx | 3 +- .../issues/issue-layouts/kanban/block.tsx | 4 +- .../kanban/headers/sub-group-by-card.tsx | 8 +- .../issues/issue-layouts/list/block.tsx | 4 +- .../properties/all-properties.tsx | 14 +- .../issues/issue-layouts/properties/cycle.tsx | 8 +- .../issue-layouts/properties/due-date.tsx | 8 +- .../issue-layouts/properties/labels.tsx | 12 +- .../issue-layouts/properties/member.tsx | 4 +- .../issue-layouts/properties/modules.tsx | 8 +- .../issue-layouts/properties/priority.tsx | 7 +- .../issues/issue-layouts/properties/state.tsx | 7 +- .../components/issues/issue-layouts/utils.tsx | 9 +- .../components/issues/navbar/layout-icon.tsx | 8 +- .../issues/navbar/layout-selection.tsx | 4 +- apps/space/components/issues/navbar/root.tsx | 4 +- .../components/issues/navbar/user-avatar.tsx | 4 +- .../peek-overview/comment/add-comment.tsx | 2 +- .../comment/comment-detail-card.tsx | 6 +- .../comment/comment-reactions.tsx | 5 +- .../issues/peek-overview/header.tsx | 14 +- .../issues/peek-overview/issue-activity.tsx | 4 +- .../issues/peek-overview/issue-properties.tsx | 19 +-- .../reactions/issue-emoji-reactions.tsx | 5 +- .../issues/reactions/issue-vote-reactions.tsx | 46 +++--- apps/space/components/views/header.tsx | 3 +- apps/space/lib/instance-provider.tsx | 2 +- apps/space/lib/toast-provider.tsx | 10 +- apps/space/package.json | 3 +- apps/space/providers/toast.tsx | 52 +++++++ apps/space/styles/globals.css | 5 +- pnpm-lock.yaml | 9 +- 75 files changed, 1316 insertions(+), 216 deletions(-) create mode 100644 apps/space/components/emoji/emoji-reaction-picker.tsx create mode 100644 apps/space/components/emoji/emoji-reaction.tsx create mode 100644 apps/space/components/emoji/helpers.ts create mode 100644 apps/space/components/emoji/index.ts create mode 100644 apps/space/components/icons/brand/plane-lockup.tsx create mode 100644 apps/space/components/icons/brand/plane-logo.tsx create mode 100644 apps/space/components/icons/cycle/circle-dot-full-icon.tsx create mode 100644 apps/space/components/icons/cycle/cycle-group-icon.tsx create mode 100644 apps/space/components/icons/cycle/helper.tsx create mode 100644 apps/space/components/icons/icon-wrapper.tsx create mode 100644 apps/space/components/icons/index.ts create mode 100644 apps/space/components/icons/priority-icon.tsx create mode 100644 apps/space/components/icons/project/cycle-icon.tsx create mode 100644 apps/space/components/icons/state/backlog-group-icon.tsx create mode 100644 apps/space/components/icons/state/cancelled-group-icon.tsx create mode 100644 apps/space/components/icons/state/completed-group-icon.tsx create mode 100644 apps/space/components/icons/state/dashed-circle.tsx create mode 100644 apps/space/components/icons/state/helper.tsx create mode 100644 apps/space/components/icons/state/progress-circle.tsx create mode 100644 apps/space/components/icons/state/started-group-icon.tsx create mode 100644 apps/space/components/icons/state/state-group-icon.tsx create mode 100644 apps/space/components/icons/state/unstarted-group-icon.tsx create mode 100644 apps/space/components/icons/type.ts create mode 100644 apps/space/providers/toast.tsx diff --git a/apps/admin/components/common/skeleton.tsx b/apps/admin/components/common/skeleton.tsx index 8652a3fefb..527a1f2028 100644 --- a/apps/admin/components/common/skeleton.tsx +++ b/apps/admin/components/common/skeleton.tsx @@ -8,8 +8,7 @@ import React from "react"; // helpers import { cn } from "@plane/utils"; -// Loading-placeholder skeleton. @makeplane/propel has no skeleton component yet; -// this matches the API the workspace @plane/propel skeleton exposed. +// Loading-placeholder skeleton. @makeplane/propel has no skeleton component yet, so it is kept local. type SkeletonProps = { children: React.ReactNode; diff --git a/apps/admin/providers/toast.tsx b/apps/admin/providers/toast.tsx index 1042dd90bd..941efc9dd1 100644 --- a/apps/admin/providers/toast.tsx +++ b/apps/admin/providers/toast.tsx @@ -10,8 +10,7 @@ import { IconButton } from "@makeplane/propel/components/icon-button"; import { Icon } from "@makeplane/propel/components/icon"; import { CloseOutline } from "@makeplane/propel/icons"; -// Keep the call-site API the workspace @plane/propel toast exposed, backed by -// @makeplane/propel's toast manager, so consumers only change their import path. +// Thin wrapper over @makeplane/propel's toast manager to keep the call-site API stable. export enum TOAST_TYPE { SUCCESS = "success", ERROR = "error", diff --git a/apps/space/app/error.tsx b/apps/space/app/error.tsx index 87aa8dc199..dea70d30b0 100644 --- a/apps/space/app/error.tsx +++ b/apps/space/app/error.tsx @@ -5,7 +5,7 @@ */ // ui -import { Button } from "@plane/propel/button"; +import { Button } from "@makeplane/propel/components/button"; function ErrorPage() { const handleRetry = () => { @@ -31,12 +31,7 @@ function ErrorPage() {

- - {/* */} +
diff --git a/apps/space/components/account/auth-forms/auth-banner.tsx b/apps/space/components/account/auth-forms/auth-banner.tsx index 4a9c517b7d..1eb9da083a 100644 --- a/apps/space/components/account/auth-forms/auth-banner.tsx +++ b/apps/space/components/account/auth-forms/auth-banner.tsx @@ -5,7 +5,7 @@ */ import { Info } from "lucide-react"; -import { CloseIcon } from "@plane/propel/icons"; +import { CloseOutline } from "@makeplane/propel/icons"; // helpers import type { TAuthErrorInfo } from "@/helpers/authentication.helper"; @@ -28,7 +28,7 @@ export function AuthBanner(props: TAuthBanner) { className="relative ml-auto flex h-6 w-6 cursor-pointer items-center justify-center rounded-xs text-accent-primary/80 transition-all hover:bg-accent-primary/20" onClick={() => handleBannerData && handleBannerData(undefined)} > - + ); diff --git a/apps/space/components/account/auth-forms/email.tsx b/apps/space/components/account/auth-forms/email.tsx index 303f9038e6..5aafecdfba 100644 --- a/apps/space/components/account/auth-forms/email.tsx +++ b/apps/space/components/account/auth-forms/email.tsx @@ -10,10 +10,10 @@ import { observer } from "mobx-react"; // icons import { CircleAlert, XCircle } from "lucide-react"; // types -import { Button } from "@plane/propel/button"; +import { Button } from "@makeplane/propel/components/button"; import type { IEmailCheckData } from "@plane/types"; // ui -import { Input, Spinner } from "@plane/ui"; +import { Input } from "@plane/ui"; // helpers import { cn } from "@plane/utils"; import { checkEmailValidity } from "@/helpers/string.helper"; @@ -100,9 +100,15 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo

)} - + + + size="lg" + stretch="full" + label="Sign in with unique code" + /> )} ) : ( - + + + /> )} diff --git a/apps/space/components/emoji/emoji-reaction-picker.tsx b/apps/space/components/emoji/emoji-reaction-picker.tsx new file mode 100644 index 0000000000..8b63a1a5d8 --- /dev/null +++ b/apps/space/components/emoji/emoji-reaction-picker.tsx @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; +import { useCallback, useEffect, useMemo, useRef } from "react"; +import { EmojiPicker } from "frimousse"; +import { Popover, PopoverContent, PopoverTrigger } from "@makeplane/propel/components/popover"; +// plane imports +import { cn } from "@plane/utils"; +// local imports +import { emojiToString } from "./helpers"; + +type EmojiRootProps = { + onChange: (value: string) => void; + searchPlaceholder?: string; +}; + +function EmojiRoot(props: EmojiRootProps) { + const { onChange, searchPlaceholder = "Search" } = props; + const searchWrapperRef = useRef(null); + + useEffect(() => { + const inputElement = searchWrapperRef.current?.querySelector("input"); + if (inputElement) { + inputElement.removeAttribute("disabled"); + inputElement.focus(); + } + }, []); + + return ( + onChange(val.emoji)} + > +
+
+ +
+
+ + ( +
+ {category.label} +
+ ), + Row: ({ children, ...props }) => ( +
+ {children} +
+ ), + Emoji: ({ emoji, ...props }) => ( + + ), + }} + /> +
+
+ ); +} + +type TPlacement = "top" | "right" | "bottom" | "left" | `${"top" | "right" | "bottom" | "left"}-${"start" | "end"}`; + +export interface EmojiReactionPickerProps { + isOpen: boolean; + handleToggle: (value: boolean) => void; + buttonClassName?: string; + closeOnSelect?: boolean; + disabled?: boolean; + dropdownClassName?: string; + label: React.ReactNode; + onChange: (emoji: string) => void; + placement?: TPlacement; + searchPlaceholder?: string; +} + +export function EmojiReactionPicker(props: EmojiReactionPickerProps) { + const { + isOpen, + handleToggle, + buttonClassName, + closeOnSelect = true, + disabled = false, + dropdownClassName, + label, + onChange, + placement = "bottom-start", + searchPlaceholder = "Search", + } = props; + + const { side, align } = useMemo(() => { + const [rawSide, rawAlign] = placement.split("-") as ["top" | "right" | "bottom" | "left", ("start" | "end")?]; + return { side: rawSide, align: rawAlign ?? "start" }; + }, [placement]); + + const handleEmojiChange = useCallback( + (value: string) => { + onChange(emojiToString(value)); + if (closeOnSelect) handleToggle(false); + }, + [onChange, closeOnSelect, handleToggle] + ); + + return ( + + } + > + {label} + + + {/* bleed past the propel popup's default padding so the picker fills the panel */} +
+ +
+
+
+ ); +} diff --git a/apps/space/components/emoji/emoji-reaction.tsx b/apps/space/components/emoji/emoji-reaction.tsx new file mode 100644 index 0000000000..fbd9b7da1c --- /dev/null +++ b/apps/space/components/emoji/emoji-reaction.tsx @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; +import { ReactionOutline } from "@makeplane/propel/icons"; +// plane imports +import { cn } from "@plane/utils"; + +export interface EmojiReactionType { + emoji: string; + count: number; + reacted?: boolean; + users?: string[]; +} + +interface EmojiReactionProps { + emoji: string; + count: number; + reacted?: boolean; + users?: string[]; + onReactionClick?: (emoji: string) => void; + className?: string; +} + +const MAX_DISPLAY_USERS = 5; + +const EmojiReaction = React.forwardRef(function EmojiReaction( + props: EmojiReactionProps, + ref: React.ForwardedRef +) { + const { emoji, count, reacted = false, users = [], onReactionClick, className } = props; + + const handleClick = () => { + onReactionClick?.(emoji); + }; + + const button = ( + + ); + + if (users.length === 0) return button; + + const displayUsers = users.slice(0, MAX_DISPLAY_USERS); + const remainingCount = users.length - displayUsers.length; + const tooltipLabel = `${emoji} ${displayUsers.join(", ")}${remainingCount > 0 ? ` and ${remainingCount} more` : ""}`; + + return {button}; +}); + +export interface EmojiReactionGroupProps { + reactions: EmojiReactionType[]; + onReactionClick?: (emoji: string) => void; + onAddReaction?: () => void; + showAddButton?: boolean; + className?: string; +} + +export const EmojiReactionGroup = React.forwardRef(function EmojiReactionGroup( + props: EmojiReactionGroupProps, + ref: React.ForwardedRef +) { + const { reactions, onReactionClick, onAddReaction, showAddButton = true, className } = props; + + return ( +
+ {reactions.map((reaction, index) => ( + + ))} + {showAddButton && ( + + + + )} +
+ ); +}); + +EmojiReaction.displayName = "EmojiReaction"; +EmojiReactionGroup.displayName = "EmojiReactionGroup"; diff --git a/apps/space/components/emoji/helpers.ts b/apps/space/components/emoji/helpers.ts new file mode 100644 index 0000000000..2c47db0580 --- /dev/null +++ b/apps/space/components/emoji/helpers.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +/** + * Converts an emoji to a dash-separated string of decimal Unicode code points. + * Handles multi-byte characters and emoji sequences (including skin tone modifiers). + * @param emoji - The emoji string to convert + * @returns Dash-separated string of decimal code points (e.g. "128077-127999") + */ +export function emojiToString(emoji: string): string { + const codePoints: number[] = []; + for (const char of Array.from(emoji)) { + const codePoint = char.codePointAt(0); + if (codePoint !== undefined) codePoints.push(codePoint); + } + return codePoints.join("-"); +} + +/** + * Converts a dash-separated string of decimal Unicode code points back to the emoji character. + * @param emojiString - Dash-separated string of decimal code points (e.g. "128077-127999") + * @returns The reconstructed emoji string, or "" on failure + */ +export function stringToEmoji(emojiString: string): string { + if (!emojiString) return ""; + const decimals = emojiString + .split("-") + .map((s) => Number(s.trim())) + .filter((n) => Number.isFinite(n) && n >= 0 && n <= 0x10ffff); + try { + return decimals.map((decimal) => String.fromCodePoint(decimal)).join(""); + } catch { + return ""; + } +} diff --git a/apps/space/components/emoji/index.ts b/apps/space/components/emoji/index.ts new file mode 100644 index 0000000000..0c0f71b8e5 --- /dev/null +++ b/apps/space/components/emoji/index.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +export { stringToEmoji, emojiToString } from "./helpers"; +export { EmojiReactionGroup } from "./emoji-reaction"; +export type { EmojiReactionType } from "./emoji-reaction"; +export { EmojiReactionPicker } from "./emoji-reaction-picker"; diff --git a/apps/space/components/icons/brand/plane-lockup.tsx b/apps/space/components/icons/brand/plane-lockup.tsx new file mode 100644 index 0000000000..0caf46cffc --- /dev/null +++ b/apps/space/components/icons/brand/plane-lockup.tsx @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; + +export function PlaneLockup({ width = "253", height = "53", className, color = "currentColor" }: ISvgIcons) { + return ( + + + + + + + + + + + + + + + + ); +} diff --git a/apps/space/components/icons/brand/plane-logo.tsx b/apps/space/components/icons/brand/plane-logo.tsx new file mode 100644 index 0000000000..3b6f8f30c7 --- /dev/null +++ b/apps/space/components/icons/brand/plane-logo.tsx @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; + +export function PlaneLogo({ width = "85", height = "52", className, color = "currentColor" }: ISvgIcons) { + return ( + + + + ); +} diff --git a/apps/space/components/icons/cycle/circle-dot-full-icon.tsx b/apps/space/components/icons/cycle/circle-dot-full-icon.tsx new file mode 100644 index 0000000000..f6ac49b596 --- /dev/null +++ b/apps/space/components/icons/cycle/circle-dot-full-icon.tsx @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; + +export function CircleDotFullIcon({ className = "text-current", ...rest }: ISvgIcons) { + return ( + + + + + ); +} diff --git a/apps/space/components/icons/cycle/cycle-group-icon.tsx b/apps/space/components/icons/cycle/cycle-group-icon.tsx new file mode 100644 index 0000000000..6545d1a0c8 --- /dev/null +++ b/apps/space/components/icons/cycle/cycle-group-icon.tsx @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; +import { CircleDotDashed, Circle } from "lucide-react"; + +import { CycleIcon } from "../project/cycle-icon"; +import { CircleDotFullIcon } from "./circle-dot-full-icon"; +import type { ICycleGroupIcon } from "./helper"; +import { CYCLE_GROUP_COLORS } from "./helper"; + +const iconComponents = { + current: CycleIcon, + upcoming: CircleDotDashed, + completed: CircleDotFullIcon, + draft: Circle, +}; + +export function CycleGroupIcon({ + className = "", + color, + cycleGroup, + height = "12px", + width = "12px", +}: ICycleGroupIcon) { + const CycleIconComponent = iconComponents[cycleGroup] || CycleIcon; + + return ( + + ); +} diff --git a/apps/space/components/icons/cycle/helper.tsx b/apps/space/components/icons/cycle/helper.tsx new file mode 100644 index 0000000000..d2019ffe5e --- /dev/null +++ b/apps/space/components/icons/cycle/helper.tsx @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +export interface ICycleGroupIcon { + className?: string; + color?: string; + cycleGroup: TCycleGroups; + height?: string; + width?: string; +} + +export type TCycleGroups = "current" | "upcoming" | "completed" | "draft"; + +export const CYCLE_GROUP_COLORS: { + [key in TCycleGroups]: string; +} = { + current: "#F59E0B", + upcoming: "#3F76FF", + completed: "#16A34A", + draft: "#525252", +}; + +export const CYCLE_GROUP_I18N_LABELS: { + [key in TCycleGroups]: string; +} = { + current: "current", + upcoming: "common.upcoming", + completed: "common.completed", + draft: "project_cycles.status.draft", +}; diff --git a/apps/space/components/icons/icon-wrapper.tsx b/apps/space/components/icons/icon-wrapper.tsx new file mode 100644 index 0000000000..e7129e58e4 --- /dev/null +++ b/apps/space/components/icons/icon-wrapper.tsx @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "./type"; + +interface IIconWrapper extends ISvgIcons { + children: React.ReactNode; + clipPathId?: string; + viewBox?: string; +} + +export function IconWrapper({ + width = "16", + height = "16", + className = "text-current", + children, + clipPathId, + viewBox = "0 0 16 16", + ...rest +}: IIconWrapper) { + return ( + + {clipPathId ? ( + <> + {children} + + + + + + + ) : ( + children + )} + + ); +} diff --git a/apps/space/components/icons/index.ts b/apps/space/components/icons/index.ts new file mode 100644 index 0000000000..b189a777cc --- /dev/null +++ b/apps/space/components/icons/index.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +// Domain and brand icons vendored from the workspace @plane/propel icon set — +// @makeplane/propel has no equivalents for these. +export { StateGroupIcon } from "./state/state-group-icon"; +export { PriorityIcon } from "./priority-icon"; +export type { TIssuePriorities } from "./priority-icon"; +export { CycleGroupIcon } from "./cycle/cycle-group-icon"; +export { PlaneLogo } from "./brand/plane-logo"; +export { PlaneLockup } from "./brand/plane-lockup"; +export type { ISvgIcons } from "./type"; diff --git a/apps/space/components/icons/priority-icon.tsx b/apps/space/components/icons/priority-icon.tsx new file mode 100644 index 0000000000..5aa39cb0af --- /dev/null +++ b/apps/space/components/icons/priority-icon.tsx @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; +import { AlertCircle, Ban, SignalHigh, SignalLow, SignalMedium } from "lucide-react"; +import { cn } from "@plane/utils"; + +export type TIssuePriorities = "urgent" | "high" | "medium" | "low" | "none"; + +interface IPriorityIcon { + className?: string; + containerClassName?: string; + priority: TIssuePriorities | undefined | null; + size?: number; + withContainer?: boolean; +} + +export function PriorityIcon(props: IPriorityIcon) { + const { priority, className = "", containerClassName = "", size = 14, withContainer = false } = props; + + const priorityClasses = { + urgent: "bg-layer-2 text-priority-urgent border-priority-urgent", + high: "bg-layer-2 text-priority-high border-priority-high", + medium: "bg-layer-2 text-priority-medium border-priority-medium", + low: "bg-layer-2 text-priority-low border-priority-low", + none: "bg-layer-2 text-priority-none border-priority-none", + }; + + // get priority icon + const icons = { + urgent: AlertCircle, + high: SignalHigh, + medium: SignalMedium, + low: SignalLow, + none: Ban, + }; + const Icon = icons[priority ?? "none"]; + + if (!Icon) return null; + + return ( + <> + {withContainer ? ( +
+ +
+ ) : ( + + )} + + ); +} diff --git a/apps/space/components/icons/project/cycle-icon.tsx b/apps/space/components/icons/project/cycle-icon.tsx new file mode 100644 index 0000000000..afba0fedf1 --- /dev/null +++ b/apps/space/components/icons/project/cycle-icon.tsx @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import { IconWrapper } from "../icon-wrapper"; +import type { ISvgIcons } from "../type"; + +export function CycleIcon({ color = "currentColor", ...rest }: ISvgIcons) { + const clipPathId = React.useId(); + + return ( + + + + + ); +} diff --git a/apps/space/components/icons/state/backlog-group-icon.tsx b/apps/space/components/icons/state/backlog-group-icon.tsx new file mode 100644 index 0000000000..a42e24f7f0 --- /dev/null +++ b/apps/space/components/icons/state/backlog-group-icon.tsx @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; +import { DashedCircle } from "./dashed-circle"; + +export function BacklogGroupIcon({ width = "20", height = "20", className, color = "#60646C" }: ISvgIcons) { + // SVG parameters + const viewBoxSize = 16; + const center = viewBoxSize / 2; + const radius = 6; + return ( + + + + ); +} diff --git a/apps/space/components/icons/state/cancelled-group-icon.tsx b/apps/space/components/icons/state/cancelled-group-icon.tsx new file mode 100644 index 0000000000..4ce8c7d303 --- /dev/null +++ b/apps/space/components/icons/state/cancelled-group-icon.tsx @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; + +export function CancelledGroupIcon({ + className = "", + color = "#9AA4BC", + height = "20", + width = "20", + ...rest +}: ISvgIcons) { + return ( + + + + ); +} diff --git a/apps/space/components/icons/state/completed-group-icon.tsx b/apps/space/components/icons/state/completed-group-icon.tsx new file mode 100644 index 0000000000..1d97af67c6 --- /dev/null +++ b/apps/space/components/icons/state/completed-group-icon.tsx @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; + +export function CompletedGroupIcon({ + className = "", + color = "#46A758", + height = "20", + width = "20", + ...rest +}: ISvgIcons) { + return ( + + + + ); +} diff --git a/apps/space/components/icons/state/dashed-circle.tsx b/apps/space/components/icons/state/dashed-circle.tsx new file mode 100644 index 0000000000..3cba92d6bd --- /dev/null +++ b/apps/space/components/icons/state/dashed-circle.tsx @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +interface DashedCircleProps { + center: number; + radius: number; + color: string; + percentage: number; + totalSegments?: number; +} + +export function DashedCircle({ center, color, percentage, totalSegments = 15 }: DashedCircleProps) { + // Ensure percentage is between 0 and 100 + const validPercentage = Math.max(0, Math.min(100, percentage)); + + // Generate dashed segments for the circle + const generateDashedCircle = () => { + const segments = []; + const angleIncrement = 360 / totalSegments; + + for (let i = 0; i < totalSegments; i++) { + // Calculate the angle for this segment (starting from top/12 o'clock position) + const angle = i * angleIncrement - 90; // -90 adjusts to start from top center + + // Calculate if this segment should be hidden based on percentage + const segmentStartPercentage = (i / totalSegments) * 100; + const isSegmentVisible = segmentStartPercentage >= validPercentage; + + if (isSegmentVisible) { + segments.push( + + + + ); + } + } + return segments; + }; + + return {generateDashedCircle()}; +} diff --git a/apps/space/components/icons/state/helper.tsx b/apps/space/components/icons/state/helper.tsx new file mode 100644 index 0000000000..2ceb3c7fe8 --- /dev/null +++ b/apps/space/components/icons/state/helper.tsx @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import { EIconSize } from "@plane/constants"; +import type { TIntakeStateGroups } from "@plane/types"; + +export interface IStateGroupIcon { + className?: string; + color?: string; + stateGroup: TStateGroups; + size?: EIconSize; + percentage?: number; +} + +export interface IIntakeStateGroupIcon { + className?: string; + color?: string; + stateGroup: TIntakeStateGroups; + size?: EIconSize; + percentage?: number; +} + +export type TStateGroups = "backlog" | "unstarted" | "started" | "completed" | "cancelled"; + +export const STATE_GROUP_COLORS: { + [key in TStateGroups]: string; +} = { + backlog: "#60646C", + unstarted: "#60646C", + started: "#F59E0B", + completed: "#46A758", + cancelled: "#9AA4BC", +}; + +export const INTAKE_STATE_GROUP_COLORS: { [key in TIntakeStateGroups]: string } = { triage: "#4E5355" }; + +export const STATE_GROUP_SIZES: { + [key in EIconSize]: string; +} = { + [EIconSize.XS]: "10px", + [EIconSize.SM]: "12px", + [EIconSize.MD]: "14px", + [EIconSize.LG]: "16px", + [EIconSize.XL]: "18px", +}; diff --git a/apps/space/components/icons/state/progress-circle.tsx b/apps/space/components/icons/state/progress-circle.tsx new file mode 100644 index 0000000000..e0f9663d4c --- /dev/null +++ b/apps/space/components/icons/state/progress-circle.tsx @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +interface ProgressCircleProps { + center: number; + radius: number; + color: string; + strokeWidth: number; + circumference: number; + dashOffset: number; +} + +export function ProgressCircle({ center, radius, color, strokeWidth, circumference, dashOffset }: ProgressCircleProps) { + return ( + + ); +} diff --git a/apps/space/components/icons/state/started-group-icon.tsx b/apps/space/components/icons/state/started-group-icon.tsx new file mode 100644 index 0000000000..cf8e6eafa8 --- /dev/null +++ b/apps/space/components/icons/state/started-group-icon.tsx @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; +import { DashedCircle } from "./dashed-circle"; +import { ProgressCircle } from "./progress-circle"; + +// StateIcon component implementation +export function StartedGroupIcon({ + width = "20", + height = "20", + className, + color = "#F59E0B", + percentage = 100, +}: ISvgIcons) { + // Ensure percentage is between 0 and 100 + const normalized = + typeof percentage === "number" + ? percentage <= 1 + ? percentage * 100 // treat 0-1 as fraction + : percentage // already 0-100 + : 100; // fallback + const validPercentage = Math.max(0, Math.min(100, normalized)); + + // SVG parameters + const viewBoxSize = 16; + const center = viewBoxSize / 2; + const radius = 6; + const strokeWidth = 1.5; + + // Calculate the circumference of the circle + const circumference = 2 * Math.PI * radius; + const dashOffset = circumference * (1 - validPercentage / 100); + const dashOffsetSmall = circumference * (1 - 100 / 100); + + return ( + + {/* Dashed background circle with segments that disappear with progress */} + + + {/* render smaller circle in the middle */} + + + {/* Solid progress circle */} + + + ); +} diff --git a/apps/space/components/icons/state/state-group-icon.tsx b/apps/space/components/icons/state/state-group-icon.tsx new file mode 100644 index 0000000000..e6f1a51cf6 --- /dev/null +++ b/apps/space/components/icons/state/state-group-icon.tsx @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import { EIconSize } from "@plane/constants"; +import { BacklogGroupIcon } from "./backlog-group-icon"; +import { CancelledGroupIcon } from "./cancelled-group-icon"; +import { CompletedGroupIcon } from "./completed-group-icon"; +import type { IStateGroupIcon } from "./helper"; +import { STATE_GROUP_COLORS, STATE_GROUP_SIZES } from "./helper"; +import { StartedGroupIcon } from "./started-group-icon"; +import { UnstartedGroupIcon } from "./unstarted-group-icon"; + +const iconComponents = { + backlog: BacklogGroupIcon, + cancelled: CancelledGroupIcon, + completed: CompletedGroupIcon, + started: StartedGroupIcon, + unstarted: UnstartedGroupIcon, +}; + +export function StateGroupIcon({ + className = "", + color, + stateGroup, + size = EIconSize.SM, + percentage, +}: IStateGroupIcon) { + const StateIconComponent = iconComponents[stateGroup] || UnstartedGroupIcon; + + return ( + + ); +} diff --git a/apps/space/components/icons/state/unstarted-group-icon.tsx b/apps/space/components/icons/state/unstarted-group-icon.tsx new file mode 100644 index 0000000000..4229699927 --- /dev/null +++ b/apps/space/components/icons/state/unstarted-group-icon.tsx @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import * as React from "react"; + +import type { ISvgIcons } from "../type"; +import { DashedCircle } from "./dashed-circle"; +import { ProgressCircle } from "./progress-circle"; + +// StateIcon component implementation +export function UnstartedGroupIcon({ + width = "20", + height = "20", + className, + color = "#F59E0B", + percentage = 100, +}: ISvgIcons) { + // Ensure percentage is between 0 and 100 + const normalized = + typeof percentage === "number" + ? percentage <= 1 + ? percentage * 100 // treat 0-1 as fraction + : percentage // already 0-100 + : 100; // fallback + const validPercentage = Math.max(0, Math.min(100, normalized)); + + // SVG parameters + const viewBoxSize = 16; + const center = viewBoxSize / 2; + const radius = 6; + const strokeWidth = 1.5; + + // Calculate the circumference of the circle + const circumference = 2 * Math.PI * radius; + + // Calculate the dash offset based on percentage + const dashOffset = circumference * (1 - validPercentage / 100); + + return ( + + + + {/* Solid progress circle */} + + + ); +} diff --git a/apps/space/components/icons/type.ts b/apps/space/components/icons/type.ts new file mode 100644 index 0000000000..e5bdc10050 --- /dev/null +++ b/apps/space/components/icons/type.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +export interface ISvgIcons extends React.SVGAttributes { + className?: string | undefined; + percentage?: number; +} diff --git a/apps/space/components/instance/instance-failure-view.tsx b/apps/space/components/instance/instance-failure-view.tsx index 2bf810e9d0..defc8a3350 100644 --- a/apps/space/components/instance/instance-failure-view.tsx +++ b/apps/space/components/instance/instance-failure-view.tsx @@ -5,7 +5,7 @@ */ import { useTheme } from "next-themes"; -import { Button } from "@plane/propel/button"; +import { Button } from "@makeplane/propel/components/button"; // assets import InstanceFailureDarkImage from "@/app/assets/instance/instance-failure-dark.svg?url"; import InstanceFailureImage from "@/app/assets/instance/instance-failure.svg?url"; @@ -31,9 +31,7 @@ export function InstanceFailureView() {

- +
diff --git a/apps/space/components/issues/filters/applied-filters/filters-list.tsx b/apps/space/components/issues/filters/applied-filters/filters-list.tsx index 6c64e1e395..c456f1c43b 100644 --- a/apps/space/components/issues/filters/applied-filters/filters-list.tsx +++ b/apps/space/components/issues/filters/applied-filters/filters-list.tsx @@ -6,7 +6,7 @@ import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; -import { CloseIcon } from "@plane/propel/icons"; +import { CloseOutline } from "@makeplane/propel/icons"; // types import type { TFilters } from "@/types/issue"; // components @@ -59,7 +59,7 @@ export const AppliedFiltersList = observer(function AppliedFiltersList(props: Pr className="grid place-items-center text-tertiary hover:text-secondary" onClick={() => handleRemoveFilter(filterKey, null)} > - + @@ -71,7 +71,7 @@ export const AppliedFiltersList = observer(function AppliedFiltersList(props: Pr className="flex items-center gap-2 rounded-md border border-subtle px-2 py-1 text-11 text-tertiary hover:text-secondary" > {t("common.clear_all")} - + ); diff --git a/apps/space/components/issues/filters/applied-filters/label.tsx b/apps/space/components/issues/filters/applied-filters/label.tsx index fce3799e58..70f20266c2 100644 --- a/apps/space/components/issues/filters/applied-filters/label.tsx +++ b/apps/space/components/issues/filters/applied-filters/label.tsx @@ -4,7 +4,7 @@ * See the LICENSE file for details. */ -import { CloseIcon } from "@plane/propel/icons"; +import { CloseOutline } from "@makeplane/propel/icons"; // types import type { IIssueLabel } from "@/types/issue"; @@ -38,7 +38,7 @@ export function AppliedLabelsFilters(props: Props) { className="grid place-items-center text-tertiary hover:text-secondary" onClick={() => handleRemove(labelId)} > - + ); diff --git a/apps/space/components/issues/filters/applied-filters/priority.tsx b/apps/space/components/issues/filters/applied-filters/priority.tsx index e28be1262f..9c6efca243 100644 --- a/apps/space/components/issues/filters/applied-filters/priority.tsx +++ b/apps/space/components/issues/filters/applied-filters/priority.tsx @@ -4,8 +4,9 @@ * See the LICENSE file for details. */ -import { CloseIcon, PriorityIcon } from "@plane/propel/icons"; -import type { TIssuePriorities } from "@plane/propel/icons"; +import { CloseOutline } from "@makeplane/propel/icons"; +import { PriorityIcon } from "@/components/icons"; +import type { TIssuePriorities } from "@/components/icons"; type Props = { handleRemove: (val: string) => void; @@ -26,7 +27,7 @@ export function AppliedPriorityFilters(props: Props) { className="grid place-items-center text-tertiary hover:text-secondary" onClick={() => handleRemove(priority)} > - + ))} diff --git a/apps/space/components/issues/filters/applied-filters/state.tsx b/apps/space/components/issues/filters/applied-filters/state.tsx index 4acadbac3c..7af9a08e3a 100644 --- a/apps/space/components/issues/filters/applied-filters/state.tsx +++ b/apps/space/components/issues/filters/applied-filters/state.tsx @@ -7,7 +7,9 @@ import { observer } from "mobx-react"; // plane imports import { EIconSize } from "@plane/constants"; -import { CloseIcon, StateGroupIcon } from "@plane/propel/icons"; +import { CloseOutline } from "@makeplane/propel/icons"; +// components +import { StateGroupIcon } from "@/components/icons"; // hooks import { useStates } from "@/hooks/store/use-state"; @@ -37,7 +39,7 @@ export const AppliedStateFilters = observer(function AppliedStateFilters(props: className="grid place-items-center text-tertiary hover:text-secondary" onClick={() => handleRemove(stateId)} > - + ); diff --git a/apps/space/components/issues/filters/helpers/dropdown.tsx b/apps/space/components/issues/filters/helpers/dropdown.tsx index 17f7ca66b8..332d7fcded 100644 --- a/apps/space/components/issues/filters/helpers/dropdown.tsx +++ b/apps/space/components/issues/filters/helpers/dropdown.tsx @@ -9,7 +9,7 @@ import type { Placement } from "@popperjs/core"; import { usePopper } from "react-popper"; import { Popover, Transition } from "@headlessui/react"; // ui -import { Button } from "@plane/propel/button"; +import { Button } from "@makeplane/propel/components/button"; type Props = { children: React.ReactNode; @@ -35,11 +35,7 @@ export function FiltersDropdown(props: Props) { return ( <> - + ); diff --git a/apps/space/components/issues/filters/helpers/filter-option.tsx b/apps/space/components/issues/filters/helpers/filter-option.tsx index b16948f4cc..23be05e1b0 100644 --- a/apps/space/components/issues/filters/helpers/filter-option.tsx +++ b/apps/space/components/issues/filters/helpers/filter-option.tsx @@ -6,7 +6,7 @@ import React from "react"; // plane imports -import { CheckIcon } from "@plane/propel/icons"; +import { TickOutline } from "@makeplane/propel/icons"; type Props = { icon?: React.ReactNode; @@ -30,7 +30,7 @@ export function FilterOption(props: Props) { isChecked ? "border-accent-strong bg-accent-primary text-on-color" : "border-strong" } ${multiple ? "rounded-xs" : "rounded-full"}`} > - {isChecked && } + {isChecked && }
{icon &&
{icon}
} diff --git a/apps/space/components/issues/filters/priority.tsx b/apps/space/components/issues/filters/priority.tsx index 06e4a532a8..160a6694aa 100644 --- a/apps/space/components/issues/filters/priority.tsx +++ b/apps/space/components/issues/filters/priority.tsx @@ -9,7 +9,8 @@ import { observer } from "mobx-react"; // plane imports import { ISSUE_PRIORITY_FILTERS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { PriorityIcon } from "@plane/propel/icons"; +// components +import { PriorityIcon } from "@/components/icons"; // local imports import { FilterHeader } from "./helpers/filter-header"; import { FilterOption } from "./helpers/filter-option"; diff --git a/apps/space/components/issues/filters/selection.tsx b/apps/space/components/issues/filters/selection.tsx index c8f7e4e216..c0c2e873dd 100644 --- a/apps/space/components/issues/filters/selection.tsx +++ b/apps/space/components/issues/filters/selection.tsx @@ -6,7 +6,7 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; -import { SearchIcon, CloseIcon } from "@plane/propel/icons"; +import { SearchOutline, CloseOutline } from "@makeplane/propel/icons"; // types import type { IIssueFilterOptions, TIssueFilterKeys } from "@/types/issue"; // local imports @@ -30,7 +30,7 @@ export const FilterSelection = observer(function FilterSelection(props: Props) {
- + {filtersSearchQuery !== "" && ( )}
diff --git a/apps/space/components/issues/filters/state.tsx b/apps/space/components/issues/filters/state.tsx index f9275a2d24..23e8a7c7e7 100644 --- a/apps/space/components/issues/filters/state.tsx +++ b/apps/space/components/issues/filters/state.tsx @@ -8,8 +8,9 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; // ui import { EIconSize } from "@plane/constants"; -import { StateGroupIcon } from "@plane/propel/icons"; import { Loader } from "@plane/ui"; +// components +import { StateGroupIcon } from "@/components/icons"; // hooks import { useStates } from "@/hooks/store/use-state"; // local imports diff --git a/apps/space/components/issues/issue-layouts/kanban/block.tsx b/apps/space/components/issues/issue-layouts/kanban/block.tsx index 3ad4c71917..ee7f9bbe13 100644 --- a/apps/space/components/issues/issue-layouts/kanban/block.tsx +++ b/apps/space/components/issues/issue-layouts/kanban/block.tsx @@ -9,7 +9,7 @@ import { observer } from "mobx-react"; import { Link } from "react-router"; import { useParams, useSearchParams } from "next/navigation"; // plane types -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import type { IIssueDisplayProperties } from "@plane/types"; // plane ui // plane utils @@ -57,7 +57,7 @@ const KanbanIssueDetailsBlock = observer(function KanbanIssueDetailsBlock(props:
- + {issue.name}
diff --git a/apps/space/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx b/apps/space/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx index 6f429aeb86..46645c3900 100644 --- a/apps/space/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx +++ b/apps/space/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx @@ -6,7 +6,7 @@ import { observer } from "mobx-react"; import { Circle } from "lucide-react"; -import { ChevronDownIcon, ChevronUpIcon } from "@plane/propel/icons"; +import { ChevronDownOutline, ChevronUpOutline } from "@makeplane/propel/icons"; // mobx interface IHeaderSubGroupByCard { @@ -25,7 +25,11 @@ export const HeaderSubGroupByCard = observer(function HeaderSubGroupByCard(props onClick={() => toggleExpanded()} >
- {isExpanded ? : } + {isExpanded ? ( + + ) : ( + + )}
diff --git a/apps/space/components/issues/issue-layouts/list/block.tsx b/apps/space/components/issues/issue-layouts/list/block.tsx index 24fc5f27e8..98af524db2 100644 --- a/apps/space/components/issues/issue-layouts/list/block.tsx +++ b/apps/space/components/issues/issue-layouts/list/block.tsx @@ -9,7 +9,7 @@ import { observer } from "mobx-react"; import { Link } from "react-router"; import { useParams, useSearchParams } from "next/navigation"; // plane types -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import type { IIssueDisplayProperties } from "@plane/types"; // plane ui // plane utils @@ -79,7 +79,7 @@ export const IssueBlock = observer(function IssueBlock(props: IssueBlockProps) { onClick={handleIssuePeekOverview} className="w-full cursor-pointer truncate text-13 text-primary" > - +

{issue.name}

diff --git a/apps/space/components/issues/issue-layouts/properties/all-properties.tsx b/apps/space/components/issues/issue-layouts/properties/all-properties.tsx index 9d9c9dace5..b7de39cb57 100644 --- a/apps/space/components/issues/issue-layouts/properties/all-properties.tsx +++ b/apps/space/components/issues/issue-layouts/properties/all-properties.tsx @@ -6,9 +6,9 @@ import { observer } from "mobx-react"; import { Paperclip } from "lucide-react"; -import { LinkIcon, ViewsIcon } from "@plane/propel/icons"; +import { LinkOutline, ViewsOutline } from "@makeplane/propel/icons"; // plane imports -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import type { IIssueDisplayProperties } from "@plane/types"; import { cn } from "@plane/utils"; // components @@ -138,7 +138,7 @@ export const IssueProperties = observer(function IssueProperties(props: IIssuePr displayPropertyKey="sub_issue_count" shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!issue.sub_issues_count} > - +
- +
{issue.sub_issues_count}
@@ -159,7 +159,7 @@ export const IssueProperties = observer(function IssueProperties(props: IIssuePr displayPropertyKey="attachment_count" shouldRenderProperty={(properties) => !!properties.attachment_count && !!issue.attachment_count} > - +
{issue.attachment_count}
@@ -173,9 +173,9 @@ export const IssueProperties = observer(function IssueProperties(props: IIssuePr displayPropertyKey="link" shouldRenderProperty={(properties) => !!properties.link && !!issue.link_count} > - +
- +
{issue.link_count}
diff --git a/apps/space/components/issues/issue-layouts/properties/cycle.tsx b/apps/space/components/issues/issue-layouts/properties/cycle.tsx index 4f70bac2a5..14a535e17b 100644 --- a/apps/space/components/issues/issue-layouts/properties/cycle.tsx +++ b/apps/space/components/issues/issue-layouts/properties/cycle.tsx @@ -6,8 +6,8 @@ import { observer } from "mobx-react"; // plane ui -import { CycleIcon } from "@plane/propel/icons"; -import { Tooltip } from "@plane/propel/tooltip"; +import { CyclesOutline } from "@makeplane/propel/icons"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; // plane utils import { cn } from "@plane/utils"; //hooks @@ -24,7 +24,7 @@ export const IssueBlockCycle = observer(function IssueBlockCycle({ cycleId, shou const cycle = getCycleById(cycleId); return ( - +
- +
{cycle?.name ?? "No Cycle"}
diff --git a/apps/space/components/issues/issue-layouts/properties/due-date.tsx b/apps/space/components/issues/issue-layouts/properties/due-date.tsx index 7fa853b448..7aefce12dc 100644 --- a/apps/space/components/issues/issue-layouts/properties/due-date.tsx +++ b/apps/space/components/issues/issue-layouts/properties/due-date.tsx @@ -5,8 +5,8 @@ */ import { observer } from "mobx-react"; -import { DueDatePropertyIcon } from "@plane/propel/icons"; -import { Tooltip } from "@plane/propel/tooltip"; +import { DueDateOutline } from "@makeplane/propel/icons"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import { cn } from "@plane/utils"; // helpers import { renderFormattedDate } from "@/helpers/date-time.helper"; @@ -30,14 +30,14 @@ export const IssueBlockDate = observer(function IssueBlockDate(props: Props) { const formattedDate = renderFormattedDate(due_date); return ( - +
- + {formattedDate ? formattedDate : "No Date"}
diff --git a/apps/space/components/issues/issue-layouts/properties/labels.tsx b/apps/space/components/issues/issue-layouts/properties/labels.tsx index 4a6d1ab0a0..236f19020d 100644 --- a/apps/space/components/issues/issue-layouts/properties/labels.tsx +++ b/apps/space/components/issues/issue-layouts/properties/labels.tsx @@ -5,9 +5,9 @@ */ import { observer } from "mobx-react"; -import { LabelPropertyIcon } from "@plane/propel/icons"; +import { LabelsOutline } from "@makeplane/propel/icons"; // plane imports -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; // hooks import { useLabel } from "@/hooks/store/use-label"; @@ -25,11 +25,11 @@ export const IssueBlockLabels = observer(function IssueBlockLabels({ labelIds, s if (labels.length <= 0) return ( - +
- + {shouldShowLabel && No Labels}
@@ -40,7 +40,7 @@ export const IssueBlockLabels = observer(function IssueBlockLabels({ labelIds, s {labels.length <= 2 ? ( <> {labels.map((label) => ( - +
- +
{`${labels.length} Labels`} diff --git a/apps/space/components/issues/issue-layouts/properties/member.tsx b/apps/space/components/issues/issue-layouts/properties/member.tsx index c24f115932..c6c5cc3561 100644 --- a/apps/space/components/issues/issue-layouts/properties/member.tsx +++ b/apps/space/components/issues/issue-layouts/properties/member.tsx @@ -7,7 +7,7 @@ import { observer } from "mobx-react"; // icons import type { LucideIcon } from "lucide-react"; -import { MembersPropertyIcon } from "@plane/propel/icons"; +import { MembersOutline } from "@makeplane/propel/icons"; // plane ui import { Avatar, AvatarGroup } from "@plane/ui"; // plane utils @@ -56,7 +56,7 @@ export const ButtonAvatars = observer(function ButtonAvatars(props: AvatarProps) return Icon ? ( ) : ( - + ); }); diff --git a/apps/space/components/issues/issue-layouts/properties/modules.tsx b/apps/space/components/issues/issue-layouts/properties/modules.tsx index 5e80222063..b7a67f258e 100644 --- a/apps/space/components/issues/issue-layouts/properties/modules.tsx +++ b/apps/space/components/issues/issue-layouts/properties/modules.tsx @@ -6,8 +6,8 @@ import { observer } from "mobx-react"; // plane ui -import { ModuleIcon } from "@plane/propel/icons"; -import { Tooltip } from "@plane/propel/tooltip"; +import { ModuleOutline } from "@makeplane/propel/icons"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; // plane utils import { cn } from "@plane/utils"; // hooks @@ -27,7 +27,7 @@ export const IssueBlockModules = observer(function IssueBlockModules({ moduleIds return (
- + {modules.length <= 1 ? (
- +
{modules?.[0]?.name ?? "No Modules"}
diff --git a/apps/space/components/issues/issue-layouts/properties/priority.tsx b/apps/space/components/issues/issue-layouts/properties/priority.tsx index 9b4dc3d017..4601bc0c3c 100644 --- a/apps/space/components/issues/issue-layouts/properties/priority.tsx +++ b/apps/space/components/issues/issue-layouts/properties/priority.tsx @@ -7,11 +7,12 @@ import { SignalHigh } from "lucide-react"; import { useTranslation } from "@plane/i18n"; // types -import { PriorityIcon } from "@plane/propel/icons"; -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import type { TIssuePriorities } from "@plane/types"; // constants import { cn, getIssuePriorityFilters } from "@plane/utils"; +// components +import { PriorityIcon } from "@/components/icons"; export function IssueBlockPriority({ priority, @@ -35,7 +36,7 @@ export function IssueBlockPriority({ if (priority_detail === null) return <>; return ( - +
+
, + icon: , payload: { cycle_id: null }, }); @@ -98,14 +99,14 @@ const getModuleColumns = (moduleStore: IIssueModuleStore): IGroupByColumn[] | un moduleGroups.push({ id: moduleInfo.id, name: moduleInfo.name, - icon: , + icon: , payload: { module_ids: [moduleInfo.id] }, }); }) as any; moduleGroups.push({ id: "None", name: "None", - icon: , + icon: , payload: { module_ids: [] }, }); diff --git a/apps/space/components/issues/navbar/layout-icon.tsx b/apps/space/components/issues/navbar/layout-icon.tsx index 79f8f39e61..5fb3ec2c3e 100644 --- a/apps/space/components/issues/navbar/layout-icon.tsx +++ b/apps/space/components/issues/navbar/layout-icon.tsx @@ -5,8 +5,8 @@ */ import type { TIssueLayout } from "@plane/constants"; -import { ListLayoutIcon, BoardLayoutIcon } from "@plane/propel/icons"; -import type { ISvgIcons } from "@plane/propel/icons"; +import { ListOutline, BoardOutline } from "@makeplane/propel/icons"; +import type { ISvgIcons } from "@/components/icons"; export function IssueLayoutIcon({ layout, @@ -20,9 +20,9 @@ export function IssueLayoutIcon({ switch (layout) { case "list": - return ; + return ; case "kanban": - return ; + return ; default: return null; } diff --git a/apps/space/components/issues/navbar/layout-selection.tsx b/apps/space/components/issues/navbar/layout-selection.tsx index 927fd7d13c..985dbd6bb9 100644 --- a/apps/space/components/issues/navbar/layout-selection.tsx +++ b/apps/space/components/issues/navbar/layout-selection.tsx @@ -10,7 +10,7 @@ import { useRouter, useSearchParams } from "next/navigation"; import { SITES_ISSUE_LAYOUTS } from "@plane/constants"; // plane i18n import { useTranslation } from "@plane/i18n"; -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; // helpers import { queryParamGenerator } from "@/helpers/query-param-generator"; // hooks @@ -53,7 +53,7 @@ export const IssuesLayoutSelection = observer(function IssuesLayoutSelection(pro if (!layoutOptions[layout.key]) return; return ( - + +
)} diff --git a/apps/space/components/issues/peek-overview/comment/add-comment.tsx b/apps/space/components/issues/peek-overview/comment/add-comment.tsx index acd86cdd5c..99de46d09d 100644 --- a/apps/space/components/issues/peek-overview/comment/add-comment.tsx +++ b/apps/space/components/issues/peek-overview/comment/add-comment.tsx @@ -9,7 +9,7 @@ import { observer } from "mobx-react"; import { useForm, Controller } from "react-hook-form"; // plane imports import type { EditorRefApi } from "@plane/editor"; -import { TOAST_TYPE, setToast } from "@plane/propel/toast"; +import { TOAST_TYPE, setToast } from "@/providers/toast"; import { SitesFileService } from "@plane/services"; import type { TIssuePublicComment } from "@plane/types"; // editor components diff --git a/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx b/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx index 27506d837b..495481fc0d 100644 --- a/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx +++ b/apps/space/components/issues/peek-overview/comment/comment-detail-card.tsx @@ -11,7 +11,7 @@ import { MessageSquare, MoreVertical } from "lucide-react"; import { Menu, Transition } from "@headlessui/react"; // plane imports import type { EditorRefApi } from "@plane/editor"; -import { CheckIcon, CloseIcon } from "@plane/propel/icons"; +import { TickOutline, CloseOutline } from "@makeplane/propel/icons"; import type { TIssuePublicComment } from "@plane/types"; import { getFileURL } from "@plane/utils"; // components @@ -140,14 +140,14 @@ export const CommentCard = observer(function CommentCard(props: Props) { disabled={isSubmitting} className="group shadow-md rounded-sm border border-success-strong bg-success-primary p-2 duration-300 hover:bg-success-primary" > - +
diff --git a/apps/space/components/issues/peek-overview/comment/comment-reactions.tsx b/apps/space/components/issues/peek-overview/comment/comment-reactions.tsx index be6a6fb48b..f22ac7562f 100644 --- a/apps/space/components/issues/peek-overview/comment/comment-reactions.tsx +++ b/apps/space/components/issues/peek-overview/comment/comment-reactions.tsx @@ -8,9 +8,8 @@ import React, { useMemo, useState } from "react"; import { observer } from "mobx-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; // plane imports -import { stringToEmoji } from "@plane/propel/emoji-icon-picker"; -import { EmojiReactionGroup, EmojiReactionPicker } from "@plane/propel/emoji-reaction"; -import type { EmojiReactionType } from "@plane/propel/emoji-reaction"; +import { stringToEmoji, EmojiReactionGroup, EmojiReactionPicker } from "@/components/emoji"; +import type { EmojiReactionType } from "@/components/emoji"; // helpers import { groupReactions } from "@/helpers/emoji.helper"; import { queryParamGenerator } from "@/helpers/query-param-generator"; diff --git a/apps/space/components/issues/peek-overview/header.tsx b/apps/space/components/issues/peek-overview/header.tsx index 0883e9b439..2f1a6ed555 100644 --- a/apps/space/components/issues/peek-overview/header.tsx +++ b/apps/space/components/issues/peek-overview/header.tsx @@ -9,8 +9,8 @@ import { observer } from "mobx-react"; import { MoveRight } from "lucide-react"; import { Listbox, Transition } from "@headlessui/react"; // ui -import { LinkIcon, CenterPanelIcon, FullScreenPanelIcon, SidePanelIcon } from "@plane/propel/icons"; -import { TOAST_TYPE, setToast } from "@plane/propel/toast"; +import { LinkOutline, ModalPeekOutline, FullScreenPeekOutline, RightSidePaneOutline } from "@makeplane/propel/icons"; +import { TOAST_TYPE, setToast } from "@/providers/toast"; // helpers import { copyTextToClipboard } from "@/helpers/string.helper"; // hooks @@ -29,15 +29,15 @@ const PEEK_MODES: { icon: any; label: string; }[] = [ - { key: "side", icon: SidePanelIcon, label: "Side Peek" }, + { key: "side", icon: RightSidePaneOutline, label: "Side Peek" }, { key: "modal", - icon: CenterPanelIcon, + icon: ModalPeekOutline, label: "Modal", }, { key: "full", - icon: FullScreenPanelIcon, + icon: FullScreenPeekOutline, label: "Full Screen", }, ]; @@ -60,7 +60,7 @@ export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Pr }); }; - const Icon = PEEK_MODES.find((m) => m.key === peekMode)?.icon ?? SidePanelIcon; + const Icon = PEEK_MODES.find((m) => m.key === peekMode)?.icon ?? RightSidePaneOutline; return ( <> @@ -126,7 +126,7 @@ export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Pr className="shrink-0 text-tertiary hover:text-secondary focus:outline-none" tabIndex={1} > - + )}
diff --git a/apps/space/components/issues/peek-overview/issue-activity.tsx b/apps/space/components/issues/peek-overview/issue-activity.tsx index 4e725c2b8c..04a2d381ec 100644 --- a/apps/space/components/issues/peek-overview/issue-activity.tsx +++ b/apps/space/components/issues/peek-overview/issue-activity.tsx @@ -9,7 +9,7 @@ import { Link } from "react-router"; import { usePathname } from "next/navigation"; import { Lock } from "lucide-react"; // plane imports -import { Button } from "@plane/propel/button"; +import { Button } from "@makeplane/propel/components/button"; // components import { AddComment } from "@/components/issues/peek-overview/comment/add-comment"; import { CommentCard } from "@/components/issues/peek-overview/comment/comment-detail-card"; @@ -63,7 +63,7 @@ export const PeekOverviewIssueActivity = observer(function PeekOverviewIssueActi Sign in to add your comment

- +
))} diff --git a/apps/space/components/issues/peek-overview/issue-properties.tsx b/apps/space/components/issues/peek-overview/issue-properties.tsx index 1c010ddafa..565d534b93 100644 --- a/apps/space/components/issues/peek-overview/issue-properties.tsx +++ b/apps/space/components/issues/peek-overview/issue-properties.tsx @@ -9,14 +9,9 @@ import { useParams } from "next/navigation"; import { LinkIcon } from "lucide-react"; // plane imports import { useTranslation } from "@plane/i18n"; -import { - StatePropertyIcon, - StateGroupIcon, - PriorityPropertyIcon, - DueDatePropertyIcon, - PriorityIcon, -} from "@plane/propel/icons"; -import { TOAST_TYPE, setToast } from "@plane/propel/toast"; +import { StateOutline, PriorityOutline, DueDateOutline } from "@makeplane/propel/icons"; +import { StateGroupIcon, PriorityIcon } from "@/components/icons"; +import { TOAST_TYPE, setToast } from "@/providers/toast"; import { cn, getIssuePriorityFilters } from "@plane/utils"; // helpers import { renderFormattedDate } from "@/helpers/date-time.helper"; @@ -77,7 +72,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr
- + State
@@ -88,7 +83,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr
- + Priority
@@ -113,7 +108,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr
- + Due date
@@ -123,7 +118,7 @@ export const PeekOverviewIssueProperties = observer(function PeekOverviewIssuePr "text-danger-primary": shouldHighlightIssueDueDate(issueDetails.target_date, state?.group), })} > - + {renderFormattedDate(issueDetails.target_date)}
) : ( diff --git a/apps/space/components/issues/reactions/issue-emoji-reactions.tsx b/apps/space/components/issues/reactions/issue-emoji-reactions.tsx index 7727ec90bd..e376ddaa9a 100644 --- a/apps/space/components/issues/reactions/issue-emoji-reactions.tsx +++ b/apps/space/components/issues/reactions/issue-emoji-reactions.tsx @@ -8,9 +8,8 @@ import { useMemo, useState } from "react"; import { observer } from "mobx-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; // lib -import { stringToEmoji } from "@plane/propel/emoji-icon-picker"; -import { EmojiReactionGroup, EmojiReactionPicker } from "@plane/propel/emoji-reaction"; -import type { EmojiReactionType } from "@plane/propel/emoji-reaction"; +import { stringToEmoji, EmojiReactionGroup, EmojiReactionPicker } from "@/components/emoji"; +import type { EmojiReactionType } from "@/components/emoji"; // helpers import { groupReactions } from "@/helpers/emoji.helper"; import { queryParamGenerator } from "@/helpers/query-param-generator"; diff --git a/apps/space/components/issues/reactions/issue-vote-reactions.tsx b/apps/space/components/issues/reactions/issue-vote-reactions.tsx index c41609317f..7e1ac33e3c 100644 --- a/apps/space/components/issues/reactions/issue-vote-reactions.tsx +++ b/apps/space/components/issues/reactions/issue-vote-reactions.tsx @@ -9,7 +9,7 @@ import { ArrowDown, ArrowUp } from "lucide-react"; import { observer } from "mobx-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; // plane imports -import { Tooltip } from "@plane/propel/tooltip"; +import { Tooltip } from "@makeplane/propel/components/tooltip"; import { cn } from "@plane/utils"; // helpers import { queryParamGenerator } from "@/helpers/query-param-generator"; @@ -81,20 +81,13 @@ export const IssueVotes = observer(function IssueVotes(props: TIssueVotes) {
{/* upvote button 👇 */} - {allUpVotes.length > 0 ? ( - <> - {allUpVotes - .map((r) => r.actor_details?.display_name) - .splice(0, VOTES_LIMIT) - .join(", ")} - {allUpVotes.length > VOTES_LIMIT && " and " + (allUpVotes.length - VOTES_LIMIT) + " more"} - - ) : ( - "No upvotes yet" - )} -
+ label={ + allUpVotes.length > 0 + ? `${allUpVotes + .map((r) => r.actor_details?.display_name) + .splice(0, VOTES_LIMIT) + .join(", ")}${allUpVotes.length > VOTES_LIMIT ? ` and ${allUpVotes.length - VOTES_LIMIT} more` : ""}` + : "No upvotes yet" } >
+ label={ + allDownVotes.length > 0 + ? `${allDownVotes + .map((r) => r.actor_details.display_name) + .splice(0, VOTES_LIMIT) + .join( + ", " + )}${allDownVotes.length > VOTES_LIMIT ? ` and ${allDownVotes.length - VOTES_LIMIT} more` : ""}` + : "No downvotes yet" } >