筛选组件开发
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import './index.scss';
|
||||
import BubbleItem from './BubbleItem';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import styles from "./index.module.scss";
|
||||
import BubbleItem from "./BubbleItem";
|
||||
|
||||
export interface BubbleOption {
|
||||
id: string | number;
|
||||
@@ -14,12 +14,16 @@ export interface BubbleOption {
|
||||
export interface BubbleProps {
|
||||
options: BubbleOption[];
|
||||
value?: string | number | (string | number)[];
|
||||
onChange?: (value: string | number | (string | number)[], option: BubbleOption | BubbleOption[]) => void;
|
||||
onChange?: (
|
||||
value: string | number | (string | number)[],
|
||||
option: BubbleOption | BubbleOption[]
|
||||
) => void;
|
||||
multiple?: boolean;
|
||||
layout?: 'horizontal' | 'vertical' | 'grid';
|
||||
layout?: "horizontal" | "vertical" | "grid";
|
||||
columns?: number;
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
size?: "small" | "medium" | "large";
|
||||
className?: string;
|
||||
itemClassName?: string;
|
||||
style?: React.CSSProperties;
|
||||
disabled?: boolean;
|
||||
}
|
||||
@@ -29,12 +33,13 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
multiple = false,
|
||||
layout = 'horizontal',
|
||||
layout = "horizontal",
|
||||
columns = 3,
|
||||
size = 'small',
|
||||
className = '',
|
||||
size = "small",
|
||||
className = "",
|
||||
itemClassName = "",
|
||||
style = {},
|
||||
disabled = false
|
||||
disabled = false,
|
||||
}) => {
|
||||
const [selectedValues, setSelectedValues] = useState<(string | number)[]>([]);
|
||||
|
||||
@@ -53,7 +58,7 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
|
||||
if (multiple) {
|
||||
if (selectedValues.includes(option.value)) {
|
||||
newSelectedValues = selectedValues.filter(v => v !== option.value);
|
||||
newSelectedValues = selectedValues.filter((v) => v !== option.value);
|
||||
} else {
|
||||
newSelectedValues = [...selectedValues, option.value];
|
||||
}
|
||||
@@ -62,11 +67,13 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
}
|
||||
|
||||
setSelectedValues(newSelectedValues);
|
||||
|
||||
|
||||
// 调用onChange回调,传递选中的值和对应的选项
|
||||
if (onChange) {
|
||||
if (multiple) {
|
||||
const selectedOptions = options.filter(opt => newSelectedValues.includes(opt.value));
|
||||
const selectedOptions = options.filter((opt) =>
|
||||
newSelectedValues.includes(opt.value)
|
||||
);
|
||||
onChange(newSelectedValues, selectedOptions);
|
||||
} else {
|
||||
onChange(option.value, option);
|
||||
@@ -79,7 +86,7 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
};
|
||||
|
||||
const renderHorizontalLayout = () => (
|
||||
<div className="bubble-horizontal">
|
||||
<div className={styles.bubbleHorizontal}>
|
||||
{options.map((option) => (
|
||||
<BubbleItem
|
||||
key={option.id}
|
||||
@@ -88,13 +95,14 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
size={size}
|
||||
disabled={disabled}
|
||||
onClick={handleOptionClick}
|
||||
itemClassName={itemClassName}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderVerticalLayout = () => (
|
||||
<div className="bubble-vertical">
|
||||
<div className={styles.bubbleVertical}>
|
||||
{options.map((option) => (
|
||||
<BubbleItem
|
||||
key={option.id}
|
||||
@@ -103,17 +111,18 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
size={size}
|
||||
disabled={disabled}
|
||||
onClick={handleOptionClick}
|
||||
itemClassName={itemClassName}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderGridLayout = () => (
|
||||
<div
|
||||
className="bubble-grid"
|
||||
style={{
|
||||
<div
|
||||
className={styles.bubbleGrid}
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${columns}, 1fr)`,
|
||||
gap: size === 'small' ? '8px' : size === 'large' ? '16px' : '12px'
|
||||
gap: size === "small" ? "8px" : size === "large" ? "16px" : "12px",
|
||||
}}
|
||||
>
|
||||
{options.map((option) => (
|
||||
@@ -124,6 +133,7 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
size={size}
|
||||
disabled={disabled}
|
||||
onClick={handleOptionClick}
|
||||
itemClassName={itemClassName}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -131,11 +141,11 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
|
||||
const renderLayout = () => {
|
||||
switch (layout) {
|
||||
case 'horizontal':
|
||||
case "horizontal":
|
||||
return renderHorizontalLayout();
|
||||
case 'vertical':
|
||||
case "vertical":
|
||||
return renderVerticalLayout();
|
||||
case 'grid':
|
||||
case "grid":
|
||||
return renderGridLayout();
|
||||
default:
|
||||
return renderHorizontalLayout();
|
||||
@@ -143,7 +153,7 @@ const Bubble: React.FC<BubbleProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`bubble-container ${className}`} style={style}>
|
||||
<div className={`${styles.bubbleContainer} ${className}`} style={style}>
|
||||
{renderLayout()}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user