import React from 'react'; import classNames from 'classnames'; import JsonViewerFoundation, { JsonViewerOptions, JsonViewerAdapter, } from '@douyinfe/semi-foundation/jsonViewer/foundation'; import '@douyinfe/semi-foundation/jsonViewer/jsonViewer.scss'; import { cssClasses } from '@douyinfe/semi-foundation/jsonViewer/constants'; import ButtonGroup from '../button/buttonGroup'; import Button from '../button'; import Input from '../input'; import DragMove from '../dragMove'; import { IconCaseSensitive, IconChevronLeft, IconChevronRight, IconClose, IconRegExp, IconSearch, IconWholeWord, } from '@douyinfe/semi-icons'; import BaseComponent, { BaseProps } from '../_base/baseComponent'; const prefixCls = cssClasses.PREFIX; export type { JsonViewerOptions }; export interface JsonViewerProps extends BaseProps { value: string; width: number; height: number; className?: string; style?: React.CSSProperties; onChange?: (value: string) => void; renderTooltip?: (value: string, el: HTMLElement) => HTMLElement; options?: JsonViewerOptions } export interface JsonViewerState { searchOptions: SearchOptions; showSearchBar: boolean } interface SearchOptions { caseSensitive: boolean; wholeWord: boolean; regex: boolean } class JsonViewerCom extends BaseComponent { static defaultProps: Partial = { width: 400, height: 400, value: '', }; private editorRef: React.RefObject; private searchInputRef: React.RefObject; private replaceInputRef: React.RefObject; foundation: JsonViewerFoundation; constructor(props: JsonViewerProps) { super(props); this.editorRef = React.createRef(); this.searchInputRef = React.createRef(); this.replaceInputRef = React.createRef(); this.foundation = new JsonViewerFoundation(this.adapter); this.state = { searchOptions: { caseSensitive: false, wholeWord: false, regex: false, }, showSearchBar: false, }; } componentDidMount() { this.foundation.init(); } componentDidUpdate(prevProps: JsonViewerProps): void { if (prevProps.options !== this.props.options) { this.foundation.jsonViewer.dispose(); this.foundation.init(); } } get adapter(): JsonViewerAdapter { return { ...super.adapter, getEditorRef: () => this.editorRef.current, getSearchRef: () => this.searchInputRef.current, notifyChange: value => { this.props.onChange?.(value); }, notifyHover: (value, el) => { const res = this.props.renderTooltip?.(value, el); return res; }, setSearchOptions: (key: string) => { this.setState( { searchOptions: { ...this.state.searchOptions, [key]: !this.state.searchOptions[key], }, }, () => { this.searchHandler(); } ); }, showSearchBar: () => { this.setState({ showSearchBar: !this.state.showSearchBar }); }, }; } getValue() { return this.foundation.jsonViewer.getModel().getValue(); } format() { this.foundation.jsonViewer.format(); } getStyle() { const { width, height } = this.props; return { width, height, }; } searchHandler = () => { const value = this.searchInputRef.current?.value; this.foundation.search(value); }; changeSearchOptions = (key: string) => { this.foundation.setSearchOptions(key); }; renderSearchBox() { return (
{this.renderSearchBar()} {this.renderReplaceBar()}
); } renderSearchOptions() { const searchOptionItems = [ { key: 'caseSensitive', icon: IconCaseSensitive, }, { key: 'regex', icon: IconRegExp, }, { key: 'wholeWord', icon: IconWholeWord, }, ]; return (
    {searchOptionItems.map(({ key, icon: Icon }) => (
  • this.changeSearchOptions(key)} />
  • ))}
); } renderSearchBar() { return (
{ e.preventDefault(); this.searchHandler(); this.searchInputRef.current?.focus(); }} ref={this.searchInputRef} /> {this.renderSearchOptions()}
); } renderReplaceBar() { return (
{ e.preventDefault(); }} ref={this.replaceInputRef} />
); } render() { let isDragging = false; const { width, className, style, ...rest } = this.props; return ( <>
{ isDragging = false; }} onMouseMove={() => { isDragging = true; }} >
{!this.state.showSearchBar ? (
); } } export default JsonViewerCom;