Skip to content

Commit

Permalink
feat: colorpicker, useTableSort hook
Browse files Browse the repository at this point in the history
  • Loading branch information
mvriu5 committed Sep 10, 2024
1 parent a152e88 commit 2f1bcda
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
21 changes: 21 additions & 0 deletions components/colorpicker/ColorPicker.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ColorPicker } from './ColorPicker';
import {Meta, StoryObj} from "@storybook/react";

const meta: Meta<typeof ColorPicker> = {
title: "Components/ColorPicker",
component: ColorPicker,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
};

export default meta;

type Story = StoryObj<typeof ColorPicker>

export const Default: Story = {
args: {
preColors: ["#4A90E2", "#FF6B6B", "#48D1CC", "#FFD700", "#9370DB", "#E17055", "#2ECC71", "#F39C12"],
},
};
53 changes: 53 additions & 0 deletions components/colorpicker/ColorPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, {useEffect, useState} from "react";


interface ColorPickerProps {
initialColor?: string;
onChange: (color: string) => void;
preColors?: string[];
}

const ColorPicker: React.FC<ColorPickerProps> = ({ initialColor, preColors, onChange }) => {
const [color, setColor] = useState<string>(initialColor || "#FFFFFF");

const handleColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setColor(e.target.value);
onChange(e.target.value);
};

return (
<div className={"flex flex-col p-4 space-y-4 rounded-lg bg-zinc-100 dark:bg-dark border border-zinc-300 dark:border-edge"}>
<div className={"grid grid-cols-4 gap-4"}>
{preColors?.map((preColor) => (
<ColorBox
key={preColor}
color={preColor}
onClick={() => setColor(preColor)}
/>
))}
</div>

<div>
<label className={"ml-0.5 block text-xs text-zinc-500 dark:text-gray"}>Selected Color</label>
<input
type="color"
className={"w-full h-12 bg-inherit appearance-none cursor-pointer outline-amber-500"}
value={color}
onChange={e => handleColorChange(e)}
/>
</div>
</div>
);
}

const ColorBox: React.FC<{ color: string, onClick: () => void }> = ({color, onClick}) => {
return (
<div
className={"size-6 rounded-md cursor-pointer"}
style={{backgroundColor: color}}
onClick={onClick}
/>
);
}

export { ColorPicker };
45 changes: 45 additions & 0 deletions hooks/useTableSort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {useMemo, useState} from "react";

type SortDirection = 'asc' | 'desc';

type SortConfig<T> = {
key: keyof T;
direction: SortDirection;
}

type customSort<T> = (a: T, b: T, order: SortDirection) => number;

interface useTableSortProps<T> {
data: T[];
initialSort: SortConfig<T>;
customSort?: Partial<Record<keyof T, customSort<T>>>;
}

export function useTableSort<T extends Record<string, any>>({ data, initialSort, customSort = {} }: useTableSortProps<T>) {
const [sortConfig, setSortConfig] = useState<SortConfig<T>>(initialSort);

const sortedData = useMemo(() => {
const sortableItems = [...data];
const { key, direction } = sortConfig;

return sortableItems.sort((a, b) => {
if (customSort[key]) return customSort[key]!(a, b, direction);

const aValue = a[key];
const bValue = b[key];

if (aValue < bValue) return direction === 'asc' ? -1 : 1;
if (aValue > bValue) return direction === 'asc' ? 1 : -1;
return 0;
});
}, [data, sortConfig, customSort]);

const requestSort = (key: keyof T) => {
setSortConfig((prev) => ({
key: key,
direction: prev.key === key && prev.direction === 'asc' ? 'desc' : 'asc',
}));
}

return { sortedData, requestSort, sortConfig };
}

0 comments on commit 2f1bcda

Please sign in to comment.