Skip to content

Commit

Permalink
feat: support slider editable (#1006)
Browse files Browse the repository at this point in the history
* refactor: update logic

* feat: click to add

* chore: click to move

* feat: key to delete

* chore: support drag to remove

* chore: drag to delete

* chore: dragable

* chore: editable only

* chore: good for dragging remove check

* chore: fix save

* test: fix test case

* chore: adjust range

* test: add test case

* test: coverage
  • Loading branch information
zombieJ authored Jul 17, 2024
1 parent ddaee15 commit b99fa96
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 131 deletions.
10 changes: 7 additions & 3 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
&-dragging&-dragging&-dragging {
border-color: tint(@primary-color, 20%);
box-shadow: 0 0 0 5px tint(@primary-color, 50%);

&-delete {
opacity: 0;
}
}

&:focus {
Expand Down Expand Up @@ -186,11 +190,11 @@
left: 5px;
width: 4px;
}

&-track-draggable {
border-top:0;
border-bottom: 0;
border-top: 0;
border-right: 5px solid rgba(0, 0, 0, 0);
border-bottom: 0;
border-left: 5px solid rgba(0, 0, 0, 0);
transform: translateX(-5px);
}
Expand Down
8 changes: 8 additions & 0 deletions docs/demo/editable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Multiple
nav:
title: Demo
path: /demo
---

<code src="../examples/editable.tsx"></code>
43 changes: 43 additions & 0 deletions docs/examples/editable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint react/no-multi-comp: 0, no-console: 0 */
import Slider from 'rc-slider';
import React from 'react';
import '../../assets/index.less';

const style: React.CSSProperties = {
width: 400,
margin: 50,
};

export default () => {
const [value, setValue] = React.useState([0, 50, 80]);

return (
<div>
<div style={style}>
<Slider
// range
range={{
editable: true,
}}
track={false}
min={0}
max={100}
value={value}
// defaultValue={null}
onChange={(nextValue) => {
console.error('Change:', nextValue);
setValue(nextValue as any);
}}
onChangeComplete={(nextValue) => {
console.log('Complete', nextValue);
}}
styles={{
rail: {
background: `linear-gradient(to right, blue, red)`,
},
}}
/>
</div>
</div>
);
};
4 changes: 2 additions & 2 deletions docs/examples/multiple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const NodeWrapper = ({ children }: { children: React.ReactElement }) => {
};

export default () => {
const [value, setValue] = React.useState([0, 5, 8]);
const [value, setValue] = React.useState([0, 50, 80]);

return (
<div>
Expand All @@ -27,7 +27,7 @@ export default () => {
// defaultValue={[0, 10, 30]}
// onChange={log}
min={0}
max={10}
max={100}
value={value}
onChange={(nextValue) => {
// console.log('>>>', nextValue);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@testing-library/react": "^12.1.3",
"@types/classnames": "^2.2.9",
"@types/jest": "^29.5.1",
"@types/node": "^20.14.10",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.0.11",
"@umijs/fabric": "^4.0.1",
Expand Down
12 changes: 12 additions & 0 deletions src/Handles/Handle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface RenderProps {
prefixCls: string;
value: number;
dragging: boolean;
draggingDelete: boolean;
}

export interface HandleProps
Expand All @@ -19,7 +20,9 @@ export interface HandleProps
value: number;
valueIndex: number;
dragging: boolean;
draggingDelete: boolean;
onStartMove: OnStartMove;
onDelete: (index: number) => void;
onOffsetChange: (value: number | 'min' | 'max', valueIndex: number) => void;
onFocus: (e: React.FocusEvent<HTMLDivElement>, index: number) => void;
onMouseEnter: (e: React.MouseEvent<HTMLDivElement>, index: number) => void;
Expand All @@ -37,9 +40,11 @@ const Handle = React.forwardRef<HTMLDivElement, HandleProps>((props, ref) => {
value,
valueIndex,
onStartMove,
onDelete,
style,
render,
dragging,
draggingDelete,
onOffsetChange,
onChangeComplete,
onFocus,
Expand Down Expand Up @@ -118,6 +123,11 @@ const Handle = React.forwardRef<HTMLDivElement, HandleProps>((props, ref) => {
case KeyCode.PAGE_DOWN:
offset = -2;
break;

case KeyCode.BACKSPACE:
case KeyCode.DELETE:
onDelete(valueIndex);
break;
}

if (offset !== null) {
Expand Down Expand Up @@ -177,6 +187,7 @@ const Handle = React.forwardRef<HTMLDivElement, HandleProps>((props, ref) => {
{
[`${handlePrefixCls}-${valueIndex + 1}`]: valueIndex !== null && range,
[`${handlePrefixCls}-dragging`]: dragging,
[`${handlePrefixCls}-dragging-delete`]: draggingDelete,
},
classNames.handle,
)}
Expand All @@ -197,6 +208,7 @@ const Handle = React.forwardRef<HTMLDivElement, HandleProps>((props, ref) => {
prefixCls,
value,
dragging,
draggingDelete,
});
}

Expand Down
44 changes: 27 additions & 17 deletions src/Handles/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface HandlesProps {
onOffsetChange: (value: number | 'min' | 'max', valueIndex: number) => void;
onFocus?: (e: React.FocusEvent<HTMLDivElement>) => void;
onBlur?: (e: React.FocusEvent<HTMLDivElement>) => void;
onDelete: (index: number) => void;
handleRender?: HandleProps['render'];
/**
* When config `activeHandleRender`,
Expand All @@ -20,6 +21,7 @@ export interface HandlesProps {
*/
activeHandleRender?: HandleProps['render'];
draggingIndex: number;
draggingDelete: boolean;
onChangeComplete?: () => void;
}

Expand All @@ -37,6 +39,7 @@ const Handles = React.forwardRef<HandlesRef, HandlesProps>((props, ref) => {
handleRender,
activeHandleRender,
draggingIndex,
draggingDelete,
onFocus,
...restProps
} = props;
Expand Down Expand Up @@ -74,31 +77,38 @@ const Handles = React.forwardRef<HandlesRef, HandlesProps>((props, ref) => {

return (
<>
{values.map<React.ReactNode>((value, index) => (
<Handle
ref={(node) => {
if (!node) {
delete handlesRef.current[index];
} else {
handlesRef.current[index] = node;
}
}}
dragging={draggingIndex === index}
style={getIndex(style, index)}
key={index}
value={value}
valueIndex={index}
{...handleProps}
/>
))}
{values.map<React.ReactNode>((value, index) => {
const dragging = draggingIndex === index;

return (
<Handle
ref={(node) => {
if (!node) {
delete handlesRef.current[index];
} else {
handlesRef.current[index] = node;
}
}}
dragging={dragging}
draggingDelete={dragging && draggingDelete}
style={getIndex(style, index)}
key={index}
value={value}
valueIndex={index}
{...handleProps}
/>
);
})}

{/* Used for render tooltip, this is not a real handle */}
{activeHandleRender && (
<Handle
key="a11y"
{...handleProps}
value={values[activeIndex]}
valueIndex={null}
dragging={draggingIndex !== -1}
draggingDelete={draggingDelete}
render={activeHandleRender}
style={{ pointerEvents: 'none' }}
tabIndex={null}
Expand Down
Loading

0 comments on commit b99fa96

Please sign in to comment.