mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Move sortabla and radio input to packages/ui
This commit is contained in:
parent
d6325320e9
commit
3133207c42
@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^4.16.3",
|
||||
"@blueprintjs/popover2": "^1.13.3",
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"@headlessui/react": "^2.0.3",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.0.0",
|
||||
"emoji-picker-react": "^4.5.16",
|
||||
|
@ -15,3 +15,5 @@ export * from "./toast";
|
||||
export * from "./drag-handle";
|
||||
export * from "./typography";
|
||||
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 { Field, Label, Radio, RadioGroup } from "@headlessui/react";
|
||||
import { cn } from "../../helpers";
|
||||
// helpers
|
||||
|
||||
type RadioInputProps = {
|
||||
label: string | React.ReactNode | undefined;
|
||||
labelClassName?: string;
|
||||
ariaLabel?: string;
|
||||
options: { label: string; value: string; disabled?: boolean }[];
|
||||
vertical?: boolean;
|
||||
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 setSelected = (value: string) => {
|
||||
console.log(value);
|
||||
onChange(value);
|
||||
};
|
||||
|
||||
let aria = ariaLabel ? ariaLabel.toLowerCase().replace(" ", "-") : "";
|
||||
@ -23,19 +37,25 @@ const RadioInput = ({ label: inputLabel, options, vertical, selected, ariaLabel
|
||||
aria = "radio-input";
|
||||
}
|
||||
|
||||
// return <h1>Hello</h1>;
|
||||
|
||||
return (
|
||||
<RadioGroup value={selected} onChange={setSelected} aria-label={aria}>
|
||||
<Label className="">{inputLabel}</Label>
|
||||
<RadioGroup value={selected} onChange={setSelected} aria-label={aria} className={className}>
|
||||
<Label className={cn(`mb-2`, inputLabelClassName)}>{inputLabel}</Label>
|
||||
<div className={`${wrapperClass}`}>
|
||||
{options.map(({ value, label }) => (
|
||||
{options.map(({ value, label, disabled }) => (
|
||||
<Field key={label} className="flex items-center gap-2">
|
||||
<Radio
|
||||
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" />
|
||||
</Radio>
|
||||
<Label>{label}</Label>
|
||||
<Label className="text-base cursor-pointer">{label}</Label>
|
||||
</Field>
|
||||
))}
|
||||
</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 { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
||||
import { isEqual } from "lodash";
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { cn } from "../../helpers";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
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 [dragging, setDragging] = useState<boolean>(false); // NEW
|
||||
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
||||
@ -37,7 +38,7 @@ const Draggable = ({ children, data }: Props) => {
|
||||
}, [data]);
|
||||
|
||||
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}
|
||||
</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";
|
||||
// components
|
||||
import { RadioInput } from "@/components/radio-group";
|
||||
// constants
|
||||
import { RadioInput } from "@plane/ui";
|
||||
import { TEstimateSystemKeys } from "@/components/estimates/types";
|
||||
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
||||
// types
|
||||
import { TEstimateSystemKeys } from "@/components/estimates/types";
|
||||
|
||||
type TEstimateCreateStageOne = {
|
||||
estimateSystem: TEstimateSystemKeys;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FC } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, Sortable } from "@plane/ui";
|
||||
// components
|
||||
import { EstimateItem } from "@/components/estimates";
|
||||
import {
|
||||
@ -10,7 +10,6 @@ import {
|
||||
TEstimateSystemKeyObject,
|
||||
TEstimateSystemKeys,
|
||||
} from "@/components/estimates/types";
|
||||
import { Sortable } from "@/components/sortable/sortable";
|
||||
// constants
|
||||
import { ESTIMATE_SYSTEMS } from "@/constants/estimates";
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Fragment, useRef, useState } from "react";
|
||||
import { Check, GripVertical, MoveRight, Pencil, Trash2, X } from "lucide-react";
|
||||
import { Select } from "@headlessui/react";
|
||||
import { Draggable } from "@/components/sortable/draggable";
|
||||
import { Draggable } from "@plane/ui";
|
||||
import { InlineEdit } from "./inline-editable";
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40"
|
||||
integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==
|
||||
@ -4094,7 +4094,7 @@
|
||||
dependencies:
|
||||
"@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"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1"
|
||||
integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==
|
||||
|
Loading…
Reference in New Issue
Block a user