diff --git a/src/components/sidebar/PathSelector.tsx b/src/components/sidebar/PathSelector.tsx index fd05f21faa..8bba4e377f 100644 --- a/src/components/sidebar/PathSelector.tsx +++ b/src/components/sidebar/PathSelector.tsx @@ -20,8 +20,11 @@ import { SavingState } from "../../document/UIStateStore"; import SaveInProgress from "../../assets/SaveInProgress"; import { NameIssue } from "../../document/path/NameIsIdentifier"; -type Props = object; - +type Props = { + searchQuery: string; + regexMode: boolean; + sortAlphabetical: boolean; +}; type State = object; type OptionProps = { uuid: string; selected: boolean }; @@ -311,15 +314,34 @@ class PathSelectorOption extends Component { } class PathSelector extends Component { - state = {}; - Option = observer(PathSelectorOption); render() { + let regex: RegExp | null = null; + if (this.props.regexMode) { + try { + regex = new RegExp(this.props.searchQuery, "i"); + } catch { + toast.error("Invalid regular expression: " + this.props.searchQuery); + } + } const activePath = doc.pathlist.activePathUUID; + const filteredPathEntries = Array.from(doc.pathlist.paths.entries()).filter( + ([, path]) => { + const query = this.props.searchQuery.trim(); + if (!query) return true; + return regex == null + ? path.name.toLowerCase().includes(query.toLowerCase()) + : regex.test(path.name); + } + ); + if (this.props.sortAlphabetical) { + filteredPathEntries.sort((a, b) => a[1].name.localeCompare(b[1].name)); + } + return (
- {Array.from(doc.pathlist.paths.keys()).map((uuid) => ( + {filteredPathEntries.map(([uuid]) => ( { + render() { + const { trajSearchQuery, setTrajSearchQuery } = uiState; + + return ( +
+ setTrajSearchQuery(e.target.value)} + fullWidth + slotProps={{ + input: { + startAdornment: ( + + ), + endAdornment: ( + <> + + + Re + + + {trajSearchQuery && ( + setTrajSearchQuery("")} + > + + + )} + + ), + style: { + color: "white", + backgroundColor: "var(--background-light-gray)", + borderRadius: "4px", + height: "32px", + fontSize: "14px" + } + } + }} + sx={{ + "& .MuiOutlinedInput-notchedOutline": { + borderColor: "transparent" + }, + "&:hover .MuiOutlinedInput-notchedOutline": { + borderColor: "var(--divider-gray)" + }, + "&.Mui-focused .MuiOutlinedInput-notchedOutline": { + borderColor: "var(--accent-purple)" + } + }} + /> +
+ ); + } +} + class Sidebar extends Component { state = {}; constructor(props: Props) { super(props); } + startResize = (e: React.MouseEvent) => { + e.preventDefault(); + document.addEventListener("mousemove", this.resize); + document.addEventListener("mouseup", this.stopResize); + }; + + resize = (e: MouseEvent) => { + const newWidth = Math.max(260, Math.min(560, e.clientX)); + document.documentElement.style.setProperty( + "--sidebar-width", + `${newWidth}px` + ); + }; + + stopResize = () => { + document.removeEventListener("mousemove", this.resize); + document.removeEventListener("mouseup", this.stopResize); + }; + + componentWillUnmount() { + this.stopResize(); + } + render() { - const { toggleMainMenu } = uiState; return (
+
{ > - { - toggleMainMenu(); - }} - > + @@ -92,9 +213,28 @@ class Sidebar extends Component {
PATHS + + + + + + + {
- + + +
- +
FEATURES
diff --git a/src/document/UIStateStore.tsx b/src/document/UIStateStore.tsx index 19ada92b31..c47a34b4b2 100644 --- a/src/document/UIStateStore.tsx +++ b/src/document/UIStateStore.tsx @@ -67,7 +67,11 @@ export const UIStateStore = types contextMenuSelectedWaypoint: types.maybe(types.number), contextMenuWaypointType: types.maybe(types.number), - contextMenuMouseSelection: types.maybe(types.array(types.number)) // [clientX, clientY] from `MouseEvent` + contextMenuMouseSelection: types.maybe(types.array(types.number)), // [clientX, clientY] from `MouseEvent` + + trajSearchQuery: types.maybe(types.string), + trajSearchRegex: false, + sortAlphabetical: false }) .views((self: any) => { return { @@ -210,6 +214,15 @@ export const UIStateStore = types self.contextMenuMouseSelection = mouseSelection ? [mouseSelection.clientX, mouseSelection.clientY] : undefined; + }, + setTrajSearchQuery(query: string) { + self.trajSearchQuery = query; + }, + toggleTrajSearchRegex() { + self.trajSearchRegex = !self.trajSearchRegex; + }, + toggleSortAlphabetical() { + self.sortAlphabetical = !self.sortAlphabetical; } })); export type IUIStateStore = Instance;