mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Merge branch 'revamp-estimates' of gurusainath:makeplane/plane into revamp-estimates
This commit is contained in:
commit
f0aea50ee8
@ -22,7 +22,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs/core": "^4.16.3",
|
"@blueprintjs/core": "^4.16.3",
|
||||||
"@blueprintjs/popover2": "^1.13.3",
|
"@blueprintjs/popover2": "^1.13.3",
|
||||||
"@headlessui/react": "^1.7.17",
|
"@headlessui/react": "^2.0.3",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"emoji-picker-react": "^4.5.16",
|
"emoji-picker-react": "^4.5.16",
|
||||||
|
@ -15,3 +15,5 @@ export * from "./toast";
|
|||||||
export * from "./drag-handle";
|
export * from "./drag-handle";
|
||||||
export * from "./typography";
|
export * from "./typography";
|
||||||
export * from "./drop-indicator";
|
export * from "./drop-indicator";
|
||||||
|
export * from "./radio-input";
|
||||||
|
export * from "./sortable";
|
||||||
|
1
packages/ui/src/radio-input/index.tsx
Normal file
1
packages/ui/src/radio-input/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./radio-input";
|
@ -1,19 +1,33 @@
|
|||||||
import { Field, Label, Radio, RadioGroup } from "@headlessui/react";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Field, Label, Radio, RadioGroup } from "@headlessui/react";
|
||||||
|
import { cn } from "../../helpers";
|
||||||
|
// helpers
|
||||||
|
|
||||||
type RadioInputProps = {
|
type RadioInputProps = {
|
||||||
label: string | React.ReactNode | undefined;
|
label: string | React.ReactNode | undefined;
|
||||||
|
labelClassName?: string;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
options: { label: string; value: string; disabled?: boolean }[];
|
options: { label: string; value: string; disabled?: boolean }[];
|
||||||
vertical?: boolean;
|
vertical?: boolean;
|
||||||
selected: string;
|
selected: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RadioInput = ({ label: inputLabel, options, vertical, selected, ariaLabel }: RadioInputProps) => {
|
const RadioInput = ({
|
||||||
|
label: inputLabel,
|
||||||
|
labelClassName: inputLabelClassName,
|
||||||
|
options,
|
||||||
|
vertical,
|
||||||
|
selected,
|
||||||
|
ariaLabel,
|
||||||
|
onChange,
|
||||||
|
className,
|
||||||
|
}: RadioInputProps) => {
|
||||||
const wrapperClass = vertical ? "flex flex-col gap-1" : "flex gap-2";
|
const wrapperClass = vertical ? "flex flex-col gap-1" : "flex gap-2";
|
||||||
|
|
||||||
const setSelected = (value: string) => {
|
const setSelected = (value: string) => {
|
||||||
console.log(value);
|
onChange(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
let aria = ariaLabel ? ariaLabel.toLowerCase().replace(" ", "-") : "";
|
let aria = ariaLabel ? ariaLabel.toLowerCase().replace(" ", "-") : "";
|
||||||
@ -23,19 +37,25 @@ const RadioInput = ({ label: inputLabel, options, vertical, selected, ariaLabel
|
|||||||
aria = "radio-input";
|
aria = "radio-input";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return <h1>Hello</h1>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RadioGroup value={selected} onChange={setSelected} aria-label={aria}>
|
<RadioGroup value={selected} onChange={setSelected} aria-label={aria} className={className}>
|
||||||
<Label className="">{inputLabel}</Label>
|
<Label className={cn(`mb-2`, inputLabelClassName)}>{inputLabel}</Label>
|
||||||
<div className={`${wrapperClass}`}>
|
<div className={`${wrapperClass}`}>
|
||||||
{options.map(({ value, label }) => (
|
{options.map(({ value, label, disabled }) => (
|
||||||
<Field key={label} className="flex items-center gap-2">
|
<Field key={label} className="flex items-center gap-2">
|
||||||
<Radio
|
<Radio
|
||||||
value={value}
|
value={value}
|
||||||
className="group flex size-5 items-center justify-center rounded-full border bg-white data-[checked]:bg-blue-400"
|
className="group flex size-5 items-center justify-center rounded-full border border-custom-border-400 bg-custom-background-500 data-[checked]:bg-custom-primary-200 data-[checked]:border-custom-primary-100 cursor-pointer
|
||||||
|
data-[disabled]:bg-custom-background-200
|
||||||
|
data-[disabled]:border-custom-border-200
|
||||||
|
data-[disabled]:cursor-not-allowed"
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<span className="invisible size-2 rounded-full bg-white group-data-[checked]:visible" />
|
<span className="invisible size-2 rounded-full bg-white group-data-[checked]:visible" />
|
||||||
</Radio>
|
</Radio>
|
||||||
<Label>{label}</Label>
|
<Label className="text-base cursor-pointer">{label}</Label>
|
||||||
</Field>
|
</Field>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
||||||
import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "../../helpers";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
data: any; //@todo make this generic
|
data: any; //@todo make this generic
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
const Draggable = ({ children, data }: Props) => {
|
const Draggable = ({ children, data, className }: Props) => {
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [dragging, setDragging] = useState<boolean>(false); // NEW
|
const [dragging, setDragging] = useState<boolean>(false); // NEW
|
||||||
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
||||||
@ -37,7 +38,7 @@ const Draggable = ({ children, data }: Props) => {
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className={cn(dragging && "opacity-25", isDraggedOver && "bg-red-500")}>
|
<div ref={ref} className={cn(dragging && "opacity-25", isDraggedOver && "bg-custom-background-80", className)}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
2
packages/ui/src/sortable/index.ts
Normal file
2
packages/ui/src/sortable/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./sortable";
|
||||||
|
export * from "./draggable";
|
32
packages/ui/src/sortable/sortable.stories.tsx
Normal file
32
packages/ui/src/sortable/sortable.stories.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import type { Meta, StoryObj } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
import { Draggable } from "./draggable";
|
||||||
|
import { Sortable } from "./sortable";
|
||||||
|
|
||||||
|
const meta: Meta<typeof Sortable> = {
|
||||||
|
title: "Sortable",
|
||||||
|
component: Sortable,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof Sortable>;
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ id: "1", name: "John Doe" },
|
||||||
|
{ id: "2", name: "Jane Doe" },
|
||||||
|
{ id: "3", name: "Alice" },
|
||||||
|
{ id: "4", name: "Bob" },
|
||||||
|
{ id: "5", name: "Charlie" },
|
||||||
|
];
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
data,
|
||||||
|
render: (item: any) => (
|
||||||
|
<Draggable data={item} className="rounded-lg">
|
||||||
|
<div>{item.name}</div>
|
||||||
|
</Draggable>
|
||||||
|
),
|
||||||
|
onChange: (data) => console.log(data),
|
||||||
|
keyExtractor: (item: any) => item.id,
|
||||||
|
},
|
||||||
|
};
|
@ -1,10 +1,10 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
// components
|
// components
|
||||||
import { RadioInput } from "@/components/radio-group";
|
|
||||||
// constants
|
// constants
|
||||||
|
import { RadioInput } from "@plane/ui";
|
||||||
|
import { TEstimateSystemKeys } from "@/components/estimates/types";
|
||||||
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
||||||
// types
|
// types
|
||||||
import { TEstimateSystemKeys } from "@/components/estimates/types";
|
|
||||||
|
|
||||||
type TEstimateCreateStageOne = {
|
type TEstimateCreateStageOne = {
|
||||||
estimateSystem: TEstimateSystemKeys;
|
estimateSystem: TEstimateSystemKeys;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
import { Button } from "@plane/ui";
|
import { Button, Sortable } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { EstimateItem } from "@/components/estimates";
|
import { EstimateItem } from "@/components/estimates";
|
||||||
import {
|
import {
|
||||||
@ -10,7 +10,6 @@ import {
|
|||||||
TEstimateSystemKeyObject,
|
TEstimateSystemKeyObject,
|
||||||
TEstimateSystemKeys,
|
TEstimateSystemKeys,
|
||||||
} from "@/components/estimates/types";
|
} from "@/components/estimates/types";
|
||||||
import { Sortable } from "@/components/sortable/sortable";
|
|
||||||
// constants
|
// constants
|
||||||
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Fragment, useRef, useState } from "react";
|
import { Fragment, useRef, useState } from "react";
|
||||||
import { Check, GripVertical, MoveRight, Pencil, Trash2, X } from "lucide-react";
|
import { Check, GripVertical, MoveRight, Pencil, Trash2, X } from "lucide-react";
|
||||||
import { Select } from "@headlessui/react";
|
import { Select } from "@headlessui/react";
|
||||||
import { Draggable } from "@/components/sortable/draggable";
|
import { Draggable } from "@plane/ui";
|
||||||
import { InlineEdit } from "./inline-editable";
|
import { InlineEdit } from "./inline-editable";
|
||||||
import { TEstimatePointNumeric, TEstimatePointString } from "./types";
|
import { TEstimatePointNumeric, TEstimatePointString } from "./types";
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from "./radio-group";
|
|
@ -1593,7 +1593,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5"
|
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5"
|
||||||
integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==
|
integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==
|
||||||
|
|
||||||
"@headlessui/react@^1.7.13", "@headlessui/react@^1.7.17", "@headlessui/react@^1.7.19":
|
"@headlessui/react@^1.7.13", "@headlessui/react@^1.7.19":
|
||||||
version "1.7.19"
|
version "1.7.19"
|
||||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40"
|
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40"
|
||||||
integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==
|
integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==
|
||||||
@ -4094,7 +4094,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@18.2.48", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.42", "@types/react@^18.2.48":
|
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.42", "@types/react@^18.2.48":
|
||||||
version "18.2.48"
|
version "18.2.48"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1"
|
||||||
integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==
|
integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==
|
||||||
|
Loading…
Reference in New Issue
Block a user