[WEB-4841] chore: calendar component migration UI to propel (#7730)
* chore: move calendar components and dependencies * chore: update package configurations * chore: calendar import updated * chore: propel config updated * chore: propel calendar code refactor * chore: code refactor * fix: build error
This commit is contained in:
parent
9ab3143a73
commit
498613284e
16 changed files with 156 additions and 164 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import type { Preview } from "@storybook/react-vite";
|
||||
import "@plane/tailwind-config/global.css";
|
||||
import "../src/styles/react-day-picker.css";
|
||||
|
||||
const parameters: Preview["parameters"] = {
|
||||
controls: {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
"exports": {
|
||||
"./accordion": "./dist/accordion/index.js",
|
||||
"./avatar": "./dist/avatar/index.js",
|
||||
"./calendar": "./dist/calendar/index.js",
|
||||
"./card": "./dist/card/index.js",
|
||||
"./charts/*": "./dist/charts/*/index.js",
|
||||
"./collapsible": "./dist/collapsible/index.js",
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
"./scrollarea": "./dist/scrollarea/index.js",
|
||||
"./skeleton": "./dist/skeleton/index.js",
|
||||
"./styles/fonts": "./dist/styles/fonts/index.css",
|
||||
"./styles/react-day-picker": "./dist/styles/react-day-picker.css",
|
||||
"./switch": "./dist/switch/index.js",
|
||||
"./table": "./dist/table/index.js",
|
||||
"./tabs": "./dist/tabs/index.js",
|
||||
|
|
@ -50,6 +52,7 @@
|
|||
"frimousse": "^0.3.0",
|
||||
"lucide-react": "catalog:",
|
||||
"react": "catalog:",
|
||||
"react-day-picker": "9.5.0",
|
||||
"react-dom": "catalog:",
|
||||
"recharts": "^2.15.1",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
|
|
|
|||
32
packages/propel/src/calendar/calendar.stories.tsx
Normal file
32
packages/propel/src/calendar/calendar.stories.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { ComponentProps, useState } from "react";
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { Calendar } from "./root";
|
||||
|
||||
type CalendarProps = ComponentProps<typeof Calendar>;
|
||||
|
||||
const meta: Meta<CalendarProps> = {
|
||||
title: "Components/Calendar",
|
||||
component: Calendar,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
args: {
|
||||
showOutsideDays: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<CalendarProps>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
render: (args: CalendarProps) => {
|
||||
const [date, setDate] = useState<Date | undefined>(new Date());
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<Calendar {...args} mode="single" selected={date} onSelect={setDate} className="rounded-md border" />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
2
packages/propel/src/calendar/index.ts
Normal file
2
packages/propel/src/calendar/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./root";
|
||||
export type { Matcher, DateRange } from "react-day-picker";
|
||||
38
packages/propel/src/calendar/root.tsx
Normal file
38
packages/propel/src/calendar/root.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { ChevronLeft } from "lucide-react";
|
||||
import { DayPicker } from "react-day-picker";
|
||||
|
||||
import { cn } from "../utils";
|
||||
|
||||
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
||||
|
||||
export const Calendar = ({ className, showOutsideDays = true, ...props }: CalendarProps) => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const thirtyYearsAgoFirstDay = new Date(currentYear - 30, 0, 1);
|
||||
const thirtyYearsFromNowFirstDay = new Date(currentYear + 30, 11, 31);
|
||||
|
||||
return (
|
||||
<DayPicker
|
||||
showOutsideDays={showOutsideDays}
|
||||
className={cn("p-3", className)}
|
||||
weekStartsOn={props.weekStartsOn}
|
||||
components={{
|
||||
Chevron: ({ className, ...props }) => (
|
||||
<ChevronLeft
|
||||
className={cn(
|
||||
"size-4",
|
||||
{ "rotate-180": props.orientation === "right", "-rotate-90": props.orientation === "down" },
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
startMonth={thirtyYearsAgoFirstDay}
|
||||
endMonth={thirtyYearsFromNowFirstDay}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
311
packages/propel/src/styles/react-day-picker.css
Normal file
311
packages/propel/src/styles/react-day-picker.css
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
.rdp-root {
|
||||
font-size: 12px;
|
||||
|
||||
--rdp-cell-size: 40px;
|
||||
/* Size of the day cells. */
|
||||
--rdp-caption-font-size: 1rem;
|
||||
/* Font size for the caption labels. */
|
||||
--rdp-caption-navigation-size: 1.25rem;
|
||||
/* Font size for the caption labels. */
|
||||
--rdp-accent-color: rgba(var(--color-primary-100));
|
||||
/* Accent color for the background of selected days. */
|
||||
--rdp-background-color: rgba(var(--color-primary-100), 0.5);
|
||||
/* Background color for the hovered/focused elements. */
|
||||
--rdp-dark-background-color: rgba(var(--color-primary-300));
|
||||
/* Background color for the hovered/focused, already selected elements. */
|
||||
--rdp-outline: 2px solid var(--rdp-accent-color);
|
||||
/* Outline border for focused elements */
|
||||
--rdp-selected-color: #ffffff;
|
||||
/* Color of selected day text */
|
||||
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.rdp-root {
|
||||
position: relative; /* Required to position the nav. */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
/* Day Buttons */
|
||||
/* ----------- */
|
||||
|
||||
.rdp-day_button {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
width: var(--rdp-cell-size);
|
||||
max-width: var(--rdp-cell-size);
|
||||
height: var(--rdp-cell-size);
|
||||
margin: 0;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.rdp-day.rdp-outside:not(.rdp-selected) .rdp-day_button {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.rdp-day.rdp-disabled:not(.rdp-selected) .rdp-day_button {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.rdp-day:not(.rdp-disabled) .rdp-day_button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rdp-day:not(.rdp-selected, .rdp-disabled) .rdp-day_button:focus-visible {
|
||||
color: inherit;
|
||||
background-color: var(--rdp-background-color);
|
||||
}
|
||||
|
||||
.rdp-selected:not(.rdp-range_middle, .rdp-disabled) .rdp-day_button:focus-visible {
|
||||
outline: var(--rdp-outline);
|
||||
outline-offset: 2px;
|
||||
background-color: var(--rdp-dark-background-color);
|
||||
outline-width: thin;
|
||||
}
|
||||
|
||||
.rdp-day:not(.rdp-disabled) .rdp-day_button:hover {
|
||||
background-color: var(--rdp-background-color);
|
||||
}
|
||||
|
||||
.rdp-selected .rdp-day_button {
|
||||
background-color: var(--rdp-accent-color);
|
||||
border-radius: 50%;
|
||||
color: var(--rdp-selected-color);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rdp-selected .rdp-day_button:hover:not(.rdp-disabled) {
|
||||
background-color: var(--rdp-dark-background-color);
|
||||
}
|
||||
|
||||
.rdp-week {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rdp-today:not(.rdp-outside) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rdp-today:not(.rdp-outside)::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 2px;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
background-color: var(--rdp-background-color);
|
||||
border-radius: 100%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.rdp-selected .rdp-day_button:focus-visible,
|
||||
.rdp-selected .rdp-day_button:hover {
|
||||
color: var(--rdp-selected-color);
|
||||
opacity: 1;
|
||||
background-color: var(--rdp-accent-color);
|
||||
}
|
||||
|
||||
.rdp-weekday {
|
||||
vertical-align: middle;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
font-size: 0.75em;
|
||||
height: var(--rdp-cell-size);
|
||||
padding: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
/* Top Nav */
|
||||
/* ---------- */
|
||||
|
||||
.rdp-nav {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
padding: inherit;
|
||||
|
||||
top: 1.2em;
|
||||
right: 1em;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rdp-button_next,
|
||||
.rdp-button_previous {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
appearance: none;
|
||||
width: var(--rdp-caption-navigation-size);
|
||||
height: var(--rdp-caption-navigation-size);
|
||||
padding: 0.25em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.rdp-chevron {
|
||||
fill: rgba(var(--color-text-200));
|
||||
height: 0.75rem;
|
||||
width: 0.75rem;
|
||||
}
|
||||
|
||||
.rdp-button_next:hover,
|
||||
.rdp-button_previous:hover,
|
||||
.rdp-button_next:focus-visible,
|
||||
.rdp-button_previous:focus-visible {
|
||||
background-color: rgba(var(--color-background-80)) !important;
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
/* Dropdowns */
|
||||
/* ---------- */
|
||||
|
||||
.rdp-dropdowns {
|
||||
position: relative;
|
||||
/* width: 100%; */
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rdp-dropdown {
|
||||
appearance: none;
|
||||
--webkit-appearance: none;
|
||||
--moz-appearance: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-size: 1rem;
|
||||
line-height: inherit;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(var(--color-background-80)) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.rdp-dropdown_root {
|
||||
margin: 0;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rdp-months_dropdown {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.rdp-dropdown[data-disabled="true"] {
|
||||
opacity: unset;
|
||||
color: unset;
|
||||
}
|
||||
|
||||
.rdp-caption_label {
|
||||
z-index: 1;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
margin: 0;
|
||||
padding: 0 0.25em;
|
||||
white-space: nowrap;
|
||||
color: currentColor;
|
||||
border: 0;
|
||||
border: 2px solid transparent;
|
||||
font-family: inherit;
|
||||
font-size: var(--rdp-caption-font-size);
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.rdp-dropdown:not([data-disabled="true"]) {
|
||||
&:focus-visible + .rdp-caption_label {
|
||||
border: var(--rdp-outline);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
& + .rdp-caption_label {
|
||||
background-color: rgba(var(--color-background-80)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rdp-dropdown_icon {
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
/* Range selection */
|
||||
/* --------------- */
|
||||
|
||||
.rdp-range_start,
|
||||
.rdp-range_middle,
|
||||
.rdp-range_end {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rdp-range_start::before,
|
||||
.rdp-range_middle::before,
|
||||
.rdp-range_end::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: var(--rdp-background-color);
|
||||
top: 50%;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
transform: translate(0, -50%);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.rdp-range_start::before {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.rdp-range_middle::before {
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.rdp-range_end::before {
|
||||
right: 50%;
|
||||
}
|
||||
|
||||
.rdp-range_start.rdp-range_end::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rdp-range_middle .rdp-day_button {
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.rdp-day.rdp-range_middle .rdp-day_button:hover,
|
||||
.rdp-day.rdp-range_middle .rdp-day_button:focus-visible {
|
||||
background-color: var(--rdp-background-color);
|
||||
color: inherit;
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ export default defineConfig({
|
|||
entry: [
|
||||
"src/accordion/index.ts",
|
||||
"src/avatar/index.ts",
|
||||
"src/calendar/index.ts",
|
||||
"src/card/index.ts",
|
||||
"src/charts/*/index.ts",
|
||||
"src/collapsible/index.ts",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue