Introduce React-Trello in place of React-Kanban

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-05-09 13:22:58 -04:00
parent f77a16648f
commit f647e1ff11
49 changed files with 2632 additions and 119 deletions

View File

@@ -0,0 +1,12 @@
import React from "react";
import { DelButton, DeleteWrapper } from "../styles/Elements";
const DeleteButton = (props) => {
return (
<DeleteWrapper {...props}>
<DelButton>&#10006;</DelButton>
</DeleteWrapper>
);
};
export default DeleteButton;

View File

@@ -0,0 +1,87 @@
import React from 'react'
import PropTypes from 'prop-types'
class EditableLabel extends React.Component {
constructor({value}) {
super()
this.state = {value: value}
}
getText = el => {
return el.innerText
}
onTextChange = ev => {
const value = this.getText(ev.target)
this.setState({value: value})
}
componentDidMount() {
if (this.props.autoFocus) {
this.refDiv.focus()
}
}
onBlur = () => {
this.props.onChange(this.state.value)
}
onPaste = ev => {
ev.preventDefault()
const value = ev.clipboardData.getData('text')
document.execCommand('insertText', false, value)
}
getClassName = () => {
const placeholder = this.state.value === '' ? 'comPlainTextContentEditable--has-placeholder' : ''
return `comPlainTextContentEditable ${placeholder}`
}
onKeyDown = e => {
if (e.keyCode === 13) {
this.props.onChange(this.state.value)
this.refDiv.blur()
e.preventDefault()
}
if (e.keyCode === 27) {
this.refDiv.value = this.props.value
this.setState({value: this.props.value})
// this.refDiv.blur()
e.preventDefault()
e.stopPropagation()
}
}
render() {
const placeholder = this.props.value.length > 0 ? false : this.props.placeholder
return (
<div
ref={ref => (this.refDiv = ref)}
contentEditable="true"
className={this.getClassName()}
onPaste={this.onPaste}
onBlur={this.onBlur}
onInput={this.onTextChange}
onKeyDown={this.onKeyDown}
placeholder={placeholder}
/>
)
}
}
EditableLabel.propTypes = {
onChange: PropTypes.func,
placeholder: PropTypes.string,
autoFocus: PropTypes.bool,
inline: PropTypes.bool,
value: PropTypes.string
}
EditableLabel.defaultProps = {
onChange: () => {},
placeholder: '',
autoFocus: false,
inline: false,
value: ''
}
export default EditableLabel

View File

@@ -0,0 +1,106 @@
import React, { useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
import { InlineInput } from "../styles/Base";
import autosize from "autosize";
const InlineInputController = ({ onSave, border, placeholder, value, autoFocus, resize, onCancel }) => {
const inputRef = useRef(null);
const [inputValue, setInputValue] = useState(value);
// Effect for autosizing and initial autoFocus
useEffect(() => {
if (inputRef.current && resize !== "none") {
autosize(inputRef.current);
}
if (inputRef.current && autoFocus) {
inputRef.current.focus();
}
}, [resize, autoFocus]);
// Effect to update value when props change
useEffect(() => {
setInputValue(value);
}, [value]);
const handleFocus = (e) => e.target.select();
const handleMouseDown = (e) => {
if (document.activeElement !== e.target) {
e.preventDefault();
inputRef.current.focus();
}
};
const handleBlur = () => {
updateValue();
};
const handleKeyDown = (e) => {
if (e.keyCode === 13) {
// Enter
inputRef.current.blur();
e.preventDefault();
} else if (e.keyCode === 27) {
// Escape
setInputValue(value); // Reset to initial value
inputRef.current.blur();
e.preventDefault();
} else if (e.keyCode === 9) {
// Tab
if (inputValue.length === 0) {
onCancel();
}
inputRef.current.blur();
e.preventDefault();
}
};
const updateValue = () => {
if (inputValue !== value) {
onSave(inputValue);
}
};
return (
<InlineInput
ref={inputRef}
border={border}
onMouseDown={handleMouseDown}
onFocus={handleFocus}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
placeholder={inputValue.length === 0 ? undefined : placeholder}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
dataGramm="false"
rows={1}
autoFocus={autoFocus}
/>
);
};
InlineInputController.propTypes = {
onSave: PropTypes.func,
onCancel: PropTypes.func,
border: PropTypes.bool,
placeholder: PropTypes.string,
value: PropTypes.string,
autoFocus: PropTypes.bool,
resize: PropTypes.oneOf(["none", "vertical", "horizontal"])
};
InlineInputController.defaultProps = {
onSave: () => {},
onCancel: () => {},
placeholder: "",
value: "",
border: false,
autoFocus: false,
resize: "none"
};
export default InlineInputController;

View File

@@ -0,0 +1,94 @@
import React from "react";
import PropTypes from "prop-types";
import { InlineInput } from "../styles/Base";
import autosize from "autosize";
class NewLaneTitleEditor extends React.Component {
onKeyDown = (e) => {
if (e.keyCode === 13) {
this.refInput.blur();
this.props.onSave();
e.preventDefault();
}
if (e.keyCode === 27) {
this.cancel();
e.preventDefault();
}
if (e.keyCode === 9) {
if (this.getValue().length === 0) {
this.cancel();
} else {
this.props.onSave();
}
e.preventDefault();
}
};
cancel = () => {
this.setValue("");
this.props.onCancel();
this.refInput.blur();
};
getValue = () => this.refInput.value;
setValue = (value) => (this.refInput.value = value);
saveValue = () => {
if (this.getValue() !== this.props.value) {
this.props.onSave(this.getValue());
}
};
focus = () => this.refInput.focus();
setRef = (ref) => {
this.refInput = ref;
if (this.props.resize !== "none") {
autosize(this.refInput);
}
};
render() {
const { autoFocus, resize, border, autoResize, value, placeholder } = this.props;
return (
<InlineInput
style={{ resize: resize }}
ref={this.setRef}
border={border}
onKeyDown={this.onKeyDown}
placeholder={value.length === 0 ? undefined : placeholder}
defaultValue={value}
rows={3}
autoResize={autoResize}
autoFocus={autoFocus}
/>
);
}
}
NewLaneTitleEditor.propTypes = {
onSave: PropTypes.func,
onCancel: PropTypes.func,
border: PropTypes.bool,
placeholder: PropTypes.string,
value: PropTypes.string,
autoFocus: PropTypes.bool,
autoResize: PropTypes.bool,
resize: PropTypes.oneOf(["none", "vertical", "horizontal"])
};
NewLaneTitleEditor.defaultProps = {
inputRef: () => {},
onSave: () => {},
onCancel: () => {},
placeholder: "",
value: "",
border: false,
autoFocus: false,
autoResize: false,
resize: "none"
};
export default NewLaneTitleEditor;

View File

@@ -0,0 +1,9 @@
import DeleteButton from "./DeleteButton";
import EditableLabel from "./EditableLabel";
import InlineInput from "./InlineInput";
export default {
DeleteButton,
EditableLabel,
InlineInput
};