react#ForwardRefRenderFunction TypeScript Examples

The following examples show how to use react#ForwardRefRenderFunction. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BaseCurrentTime.tsx    From rewind with MIT License 7 votes vote down vote up
ForwardCurrentTime: ForwardRefRenderFunction<GameCurrentTimeHandle, GameCurrentTimeProps> = (props, ref) => {
  const refMain = useRef<HTMLSpanElement>(null);
  const refMs = useRef<HTMLSpanElement>(null);

  useImperativeHandle(ref, () => ({
    updateTime(timeInMs) {
      const [timeHMS, timeMS] = formatGameTime(timeInMs, true).split(".");
      if (refMain.current) refMain.current.textContent = timeHMS;
      if (refMs.current) refMs.current.textContent = "." + timeMS;
    },
  }));
  return (
    <Typography component={"span"} sx={{ userSelect: "all" }}>
      <span ref={refMain}>0:00</span>

      <Typography component={"span"} sx={{ color: (theme) => darken(theme.palette.text.primary, 0.6) }} ref={refMs}>
        <span ref={refMs}>.000</span>
      </Typography>
    </Typography>
  );
}
Example #2
Source File: FunnelBarGraph.tsx    From posthog-foss with MIT License 6 votes vote down vote up
export function ValueInspectorButton({
    icon,
    onClick,
    children,
    disabled = false,
    style,
    title,
    innerRef: refProp,
}: ValueInspectorButtonProps): JSX.Element {
    const props = {
        type: 'link' as const,
        icon,
        onClick,
        className: 'funnel-inspect-button',
        disabled,
        style,
        title,
        children: <span className="funnel-inspect-label">{children}</span>,
    }
    if (refProp) {
        const InnerComponent: ForwardRefRenderFunction<HTMLElement | null, ButtonProps> = (_, ref) => (
            <Button ref={ref} {...props} />
        )
        const RefComponent = React.forwardRef(InnerComponent)
        return <RefComponent ref={refProp} />
    } else {
        return <Button {...props} />
    }
}
Example #3
Source File: DateConditionConfiguration.tsx    From datart with Apache License 2.0 5 votes vote down vote up
DateConditionConfiguration: ForwardRefRenderFunction<
  FilterOptionForwardRef,
  {
    condition?: ChartFilterCondition;
    onChange: (condition: ChartFilterCondition) => void;
  } & I18NComponentProps
> = ({ i18nPrefix, condition, onChange: onConditionChange }, ref) => {
  const t = useI18NPrefix(i18nPrefix);
  const [type, setType] = useState<string>(() =>
    condition?.type === FilterConditionType.RangeTime
      ? String(FilterConditionType.RangeTime)
      : String(FilterConditionType.RecommendTime),
  );

  useImperativeHandle(ref, () => ({
    onValidate: (args: ChartFilterCondition) => {
      if (isEmpty(args?.operator)) {
        return false;
      }
      if (
        [FilterSqlOperator.Between, FilterSqlOperator.NotBetween].includes(
          args?.operator as FilterSqlOperator,
        )
      ) {
        return !isEmpty(args?.value) && !isEmptyArray(args?.value);
      }
      return false;
    },
  }));

  const clearFilterWhenTypeChange = (type: string) => {
    setType(type);
    const conditionType = Number(type);
    if (conditionType === FilterConditionType.RecommendTime) {
      const filter = new ConditionBuilder(condition)
        .setValue(RECOMMEND_TIME.TODAY)
        .asRecommendTime();
      onConditionChange?.(filter);
    } else if (conditionType === FilterConditionType.RangeTime) {
      const filterRow = new ConditionBuilder(condition)
        .setValue([
          formatTime(moment(), TIME_FORMATTER),
          formatTime(moment(), TIME_FORMATTER),
        ])
        .asRangeTime();
      onConditionChange?.(filterRow);
    }
  };

  return (
    <StyledDateConditionConfiguration
      activeKey={type}
      onChange={clearFilterWhenTypeChange}
      destroyInactiveTabPane={true}
    >
      <Tabs.TabPane
        tab={t('recommend')}
        key={FilterConditionType.RecommendTime}
      >
        <TimeSelector.RecommendRangeTimeSelector
          i18nPrefix={i18nPrefix}
          condition={condition}
          onConditionChange={onConditionChange}
        />
      </Tabs.TabPane>
      <Tabs.TabPane tab={t('manual')} key={FilterConditionType.RangeTime}>
        <TimeSelector.ManualRangeTimeSelector
          i18nPrefix={i18nPrefix}
          condition={condition}
          onConditionChange={onConditionChange}
        />
      </Tabs.TabPane>
    </StyledDateConditionConfiguration>
  );
}
Example #4
Source File: ChartComputedFieldEditor.tsx    From datart with Apache License 2.0 4 votes vote down vote up
ChartComputedFieldEditor: ForwardRefRenderFunction<
  ChartComputedFieldHandle,
  {
    value?: string;
    functionDescriptions?: FunctionDescription[];
    onChange: (expression: string) => void;
  }
> = (props, ref) => {
  const editorRef = useRef<MonacoEditor>(null);
  const [editorText, setEditorText] = useState(props.value);
  const [description, setDescription] = useState<FunctionDescription>();

  useImperativeHandle(ref, () => ({
    insertField: (value, funcDesc) => {
      if (!value) {
        return;
      }
      if (funcDesc) {
        setDescription(funcDesc);
      }
      editorRef?.current?.editor?.trigger('keyboard', 'type', { text: value });
      editorRef?.current?.editor?.focus();
    },
  }));

  const getEditorNewLineCharactor = () => {
    return editorRef?.current?.editor?.getModel()?.getEOL();
  };

  const onChange = debounce(newValue => {
    setEditorText(newValue);

    const removeNewLineCharactor = value =>
      value.replace(getEditorNewLineCharactor(), ' ');
    props.onChange && props.onChange(removeNewLineCharactor(newValue));
  }, 200);

  const handleDescriptionChange = debounce(descKey => {
    if (!descKey) {
      return;
    }
    const funcDesc = props.functionDescriptions?.find(d => d.name === descKey);
    if (!!funcDesc) {
      setDescription(funcDesc);
    }
  }, 200);

  const handleEdtiorWillMount = monacoEditor => {
    monacoEditor.languages.register({ id: 'dql' });
    monacoEditor.languages.setMonarchTokensProvider('dql', {
      ...DatartQueryLanguageSpecification,
      builtinFunctions: (props?.functionDescriptions || []).map(f => f.name),
    });
    monacoEditor.editor.defineTheme(
      'dqlTheme',
      ChartComputedFieldEditorDarkTheme,
    );
  };

  const handleEditorDidMount = (editor, monaco) => {
    const model = editor.getModel();

    editor.onDidChangeCursorPosition(listener => {
      const positionWord = model.getWordAtPosition(listener.position);
      handleDescriptionChange(positionWord?.word);
    });
  };

  const renderFunctionDescriptionInfo = () => {
    if (!description) {
      return '';
    }
    return `${description.description}: ${description.syntax}`;
  };

  return (
    <StyledChartComputedFieldEditor>
      <Row>
        <MonacoEditor
          ref={editorRef}
          theme="dqlTheme"
          language="dql"
          defaultValue={editorText}
          onChange={onChange}
          editorWillMount={handleEdtiorWillMount}
          editorDidMount={handleEditorDidMount}
          overrideServices={
            {
              // onDidChangeCursorPosition: () => console.log('overrideServices |onDidChangeCursorPosition ---->'),
            }
          }
          options={{
            lineDecorationsWidth: 1,
          }}
        />
      </Row>
      <Row>
        <Divider />
        <p>{renderFunctionDescriptionInfo()}</p>
      </Row>
    </StyledChartComputedFieldEditor>
  );
}
Example #5
Source File: CategoryConditionConfiguration.tsx    From datart with Apache License 2.0 4 votes vote down vote up
CategoryConditionConfiguration: ForwardRefRenderFunction<
  FilterOptionForwardRef,
  {
    colName: string;
    dataView?: ChartDataView;
    condition?: ChartFilterCondition;
    onChange: (condition: ChartFilterCondition) => void;
    fetchDataByField?: (fieldId) => Promise<string[]>;
  } & I18NComponentProps
> = (
  {
    colName,
    i18nPrefix,
    condition,
    dataView,
    onChange: onConditionChange,
    fetchDataByField,
  },
  ref,
) => {
  const t = useI18NPrefix(i18nPrefix);
  const [curTab, setCurTab] = useState<FilterConditionType>(() => {
    if (
      [
        FilterConditionType.List,
        FilterConditionType.Condition,
        FilterConditionType.Customize,
      ].includes(condition?.type!)
    ) {
      return condition?.type!;
    }
    return FilterConditionType.List;
  });
  const [targetKeys, setTargetKeys] = useState<string[]>(() => {
    let values;
    if (condition?.operator === FilterSqlOperator.In) {
      values = condition?.value;
      if (Array.isArray(condition?.value)) {
        const firstValues =
          (condition?.value as [])?.filter(n => {
            if (IsKeyIn(n as RelationFilterValue, 'key')) {
              return (n as RelationFilterValue).isSelected;
            }
            return false;
          }) || [];
        values = firstValues?.map((n: RelationFilterValue) => n.key);
      }
    }
    return values || [];
  });
  const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
  const [isTree, setIsTree] = useState(isTreeModel(condition?.value));
  const [treeOptions, setTreeOptions] = useState<string[]>([]);
  const [listDatas, setListDatas] = useState<RelationFilterValue[]>([]);
  const [treeDatas, setTreeDatas] = useState<RelationFilterValue[]>([]);

  useImperativeHandle(ref, () => ({
    onValidate: (args: ChartFilterCondition) => {
      if (isEmpty(args?.operator)) {
        return false;
      }
      if (args?.operator === FilterSqlOperator.In) {
        return !isEmptyArray(args?.value);
      } else if (
        [
          FilterSqlOperator.Contain,
          FilterSqlOperator.PrefixContain,
          FilterSqlOperator.SuffixContain,
          FilterSqlOperator.Equal,
          FilterSqlOperator.NotContain,
          FilterSqlOperator.NotPrefixContain,
          FilterSqlOperator.NotSuffixContain,
          FilterSqlOperator.NotEqual,
        ].includes(args?.operator as FilterSqlOperator)
      ) {
        return !isEmpty(args?.value);
      } else if (
        [FilterSqlOperator.Null, FilterSqlOperator.NotNull].includes(
          args?.operator as FilterSqlOperator,
        )
      ) {
        return true;
      }
      return false;
    },
  }));

  useMount(() => {
    if (curTab === FilterConditionType.List) {
      handleFetchData();
    }
  });

  const getDataOptionFields = () => {
    return dataView?.meta || [];
  };

  const isChecked = (selectedKeys, eventKey) =>
    selectedKeys.indexOf(eventKey) !== -1;

  const fetchNewDataset = async (viewId, colName: string) => {
    const fieldDataset = await getDistinctFields(
      viewId,
      [colName],
      undefined,
      undefined,
    );
    return fieldDataset;
  };

  const setListSelectedState = (
    list?: RelationFilterValue[],
    keys?: string[],
  ) => {
    return (list || []).map(c =>
      Object.assign(c, { isSelected: isChecked(keys, c.key) }),
    );
  };

  const setTreeCheckableState = (
    treeList?: RelationFilterValue[],
    keys?: string[],
  ) => {
    return (treeList || []).map(c => {
      c.isSelected = isChecked(keys, c.key);
      c.children = setTreeCheckableState(c.children, keys);
      return c;
    });
  };

  const handleGeneralListChange = async selectedKeys => {
    const items = setListSelectedState(listDatas, selectedKeys);
    setTargetKeys(selectedKeys);
    setListDatas(items);

    const generalTypeItems = items?.filter(i => i.isSelected);
    const filter = new ConditionBuilder(condition)
      .setOperator(FilterSqlOperator.In)
      .setValue(generalTypeItems)
      .asGeneral();
    onConditionChange(filter);
  };

  const filterGeneralListOptions = useCallback(
    (inputValue, option) => option.label?.includes(inputValue) || false,
    [],
  );

  const handleGeneralTreeChange = async treeSelectedKeys => {
    const selectedKeys = treeSelectedKeys.checked;
    const treeItems = setTreeCheckableState(treeDatas, selectedKeys);
    setTargetKeys(selectedKeys);
    setTreeDatas(treeItems);
    const filter = new ConditionBuilder(condition)
      .setOperator(FilterSqlOperator.In)
      .setValue(treeItems)
      .asTree();
    onConditionChange(filter);
  };

  const onSelectChange = (
    sourceSelectedKeys: string[],
    targetSelectedKeys: string[],
  ) => {
    const newSelectedKeys = [...sourceSelectedKeys, ...targetSelectedKeys];
    setSelectedKeys(newSelectedKeys);
  };

  const handleTreeOptionChange = (
    associateField: string,
    labelField: string,
  ) => {
    setTreeOptions([associateField, labelField]);
  };

  const handleFetchData = () => {
    fetchNewDataset?.(dataView?.id, colName).then(dataset => {
      if (isTree) {
        // setTreeDatas(convertToTree(dataset?.columns, selectedKeys));
        // setListDatas(convertToList(dataset?.columns, selectedKeys));
      } else {
        setListDatas(convertToList(dataset?.rows, selectedKeys));
      }
    });
  };

  const convertToList = (collection, selectedKeys) => {
    const items: string[] = (collection || []).flatMap(c => c);
    const uniqueKeys = Array.from(new Set(items));
    return uniqueKeys.map(item => ({
      key: item,
      label: item,
      isSelected: selectedKeys.includes(item),
    }));
  };

  const convertToTree = (collection, selectedKeys) => {
    const associateField = treeOptions?.[0];
    const labelField = treeOptions?.[1];

    if (!associateField || !labelField) {
      return [];
    }

    const associateKeys = Array.from(
      new Set(collection?.map(c => c[associateField])),
    );
    const treeNodes = associateKeys
      .map(key => {
        const associateItem = collection?.find(c => c[colName] === key);
        if (!associateItem) {
          return null;
        }
        const associateChildren = collection
          .filter(c => c[associateField] === key)
          .map(c => {
            const itemKey = c[labelField];
            return {
              key: itemKey,
              label: itemKey,
              isSelected: isChecked(selectedKeys, itemKey),
            };
          });
        const itemKey = associateItem?.[colName];
        return {
          key: itemKey,
          label: itemKey,
          isSelected: isChecked(selectedKeys, itemKey),
          children: associateChildren,
        };
      })
      .filter(i => Boolean(i)) as RelationFilterValue[];
    return treeNodes;
  };

  const handleTabChange = (activeKey: string) => {
    const conditionType = +activeKey;
    setCurTab(conditionType);
    const filter = new ConditionBuilder(condition)
      .setOperator(null!)
      .setValue(null)
      .asFilter(conditionType);
    setTreeDatas([]);
    setTargetKeys([]);
    setListDatas([]);
    onConditionChange(filter);
  };

  return (
    <StyledTabs activeKey={curTab.toString()} onChange={handleTabChange}>
      <Tabs.TabPane
        tab={t('general')}
        key={FilterConditionType.List.toString()}
      >
        <Row>
          <Space>
            <Button type="primary" onClick={handleFetchData}>
              {t('load')}
            </Button>
            {/* <Checkbox
                checked={isTree}
                disabled
                onChange={e => setIsTree(e.target.checked)}
              >
                {t('useTree')}
              </Checkbox> */}
          </Space>
        </Row>
        <Row>
          <Space>
            {isTree && (
              <>
                {t('associateField')}
                <Select
                  value={treeOptions?.[0]}
                  options={getDataOptionFields()?.map(f => ({
                    label: f.name,
                    value: f.id,
                  }))}
                  onChange={value =>
                    handleTreeOptionChange(value, treeOptions?.[1])
                  }
                />
                {t('labelField')}
                <Select
                  value={treeOptions?.[1]}
                  options={getDataOptionFields()?.map(f => ({
                    label: f.name,
                    value: f.id,
                  }))}
                  onChange={value =>
                    handleTreeOptionChange(treeOptions?.[0], value)
                  }
                />
              </>
            )}
          </Space>
        </Row>
        {isTree && (
          <Tree
            blockNode
            checkable
            checkStrictly
            defaultExpandAll
            checkedKeys={targetKeys}
            treeData={treeDatas}
            onCheck={handleGeneralTreeChange}
            onSelect={handleGeneralTreeChange}
          />
        )}
        {!isTree && (
          <Transfer
            operations={[t('moveToRight'), t('moveToLeft')]}
            dataSource={listDatas}
            titles={[`${t('sourceList')}`, `${t('targetList')}`]}
            targetKeys={targetKeys}
            selectedKeys={selectedKeys}
            onChange={handleGeneralListChange}
            onSelectChange={onSelectChange}
            render={item => item.label}
            filterOption={filterGeneralListOptions}
            showSearch
            pagination
          />
        )}
      </Tabs.TabPane>
      <Tabs.TabPane
        tab={t('customize')}
        key={FilterConditionType.Customize.toString()}
      >
        <CategoryConditionEditableTable
          dataView={dataView}
          i18nPrefix={i18nPrefix}
          condition={condition}
          onConditionChange={onConditionChange}
          fetchDataByField={fetchDataByField}
        />
      </Tabs.TabPane>
      <Tabs.TabPane
        tab={t('condition')}
        key={FilterConditionType.Condition.toString()}
      >
        <CategoryConditionRelationSelector
          condition={condition}
          onConditionChange={onConditionChange}
        />
      </Tabs.TabPane>
    </StyledTabs>
  );
}
Example #6
Source File: ValueConditionConfiguration.tsx    From datart with Apache License 2.0 4 votes vote down vote up
ValueConditionConfiguration: ForwardRefRenderFunction<
  FilterOptionForwardRef,
  {
    condition?: ChartFilterCondition;
    onChange: (condition: ChartFilterCondition) => void;
  } & I18NComponentProps
> = ({ i18nPrefix, condition, onChange: onConditionChange }, ref) => {
  const [curFilter, setCurFilter] = useState<ChartFilterCondition>(
    new ConditionBuilder(condition).asSelf(),
  );

  useImperativeHandle(ref, () => ({
    onValidate: (args: ChartFilterCondition) => {
      if (isEmpty(args?.operator)) {
        return false;
      }
      if (
        [FilterSqlOperator.Between, FilterSqlOperator.NotBetween].includes(
          args?.operator as FilterSqlOperator,
        )
      ) {
        return args?.value?.filter(v => !isEmpty(v))?.length === 2;
      } else if (
        [
          FilterSqlOperator.Equal,
          FilterSqlOperator.NotEqual,
          FilterSqlOperator.GreaterThanOrEqual,
          FilterSqlOperator.LessThanOrEqual,
          FilterSqlOperator.LessThan,
          FilterSqlOperator.GreaterThan,
        ].includes(args?.operator as FilterSqlOperator)
      ) {
        return (
          !isEmpty(args?.value) &&
          !isEmptyArray(args?.value?.filter(v => !isEmpty(v)))
        );
      } else if (
        [FilterSqlOperator.Null, FilterSqlOperator.NotNull].includes(
          args?.operator as FilterSqlOperator,
        )
      ) {
        return true;
      }
      return false;
    },
  }));

  const handleFilterChanged = (filter: ChartFilterCondition) => {
    setCurFilter(filter);
    onConditionChange && onConditionChange(filter);
  };

  const handleAddBrotherFilter = () => {
    const filter = curFilter;
    filter.appendChild();
    setCurFilter(filter);
    handleFilterChanged(filter);
  };

  const handleDeleteSelfFilter = () => {
    let newFilter = new ConditionBuilder(curFilter).asFilter();
    handleFilterChanged(newFilter);
  };

  const renderFilters = () => {
    if (curFilter?.type === FilterConditionType.Relation) {
      return (
        <MultiFilterRow
          rowName={'root'}
          condition={curFilter}
          onConditionChange={handleFilterChanged}
        />
      );
    }
    return (
      <SingleFilterRow
        rowName={'root'}
        condition={curFilter}
        onAddBrotherFilter={handleAddBrotherFilter}
        onDeleteSelfFilter={handleDeleteSelfFilter}
        onConditionChange={handleFilterChanged}
      />
    );
  };

  return renderFilters();
}