preact#RefObject TypeScript Examples

The following examples show how to use preact#RefObject. 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: form.ts    From passwords-fountain with MIT License 6 votes vote down vote up
validateInputField = (
    fieldName: string,
    formRef: RefObject<HTMLFormElement>,
    formValidation: { [key: string]: (val: string) => boolean | string },
    valueSetter: (val: string) => void,
    errorSetter: (errorMsg: string) => void
): InputEventHandler => (event: Event): void => {
    const errors: { [key: string]: any } = validate(
        formRef.current as HTMLFormElement,
        formValidation
    );
    const value = (event.target as HTMLInputElement).value;
    const defaultValue = '';

    valueSetter(value ?? defaultValue);
    errorSetter(errors[fieldName] ?? defaultValue);
}
Example #2
Source File: form.ts    From passwords-fountain with MIT License 6 votes vote down vote up
useInputFormControl = (
    formRef: RefObject<HTMLFormElement>,
    formValidation: { [key: string]: (val: string) => boolean | string },
    fieldName: string,
    defaultValue = ''
): [FormTextInputState, FormTextInputProps] => {
    const [value, setValue] = useState(defaultValue);
    const [errors, setErrors] = useState('');

    return [
        { value, setValue, errors, setErrors },
        {
            name: fieldName,
            value,
            hasError: Boolean(errors),
            onInput: validateInputField(
                fieldName,
                formRef,
                formValidation,
                setValue,
                setErrors
            ),
        },
    ];
}
Example #3
Source File: createMindmap.tsx    From remind with MIT License 6 votes vote down vote up
MindmapApp = forwardRef(
  (props: Partial<MindmapProps>, ref: RefObject<ContributionAPI>) => {
    const {
      value = defaultProps.value,
      theme = defaultTheme,
      locale = defaultProps.locale,
    } = props
    return (
      <ViewModel.Provider>
        <Model.Provider
          initialState={{
            root: value,
          }}
        >
          <ThemeContext.Provider value={theme}>
            <LocaleContext.Provider value={{ locale }}>
              <Mindmap {...defaultProps} {...props} ref={ref} />
            </LocaleContext.Provider>
          </ThemeContext.Provider>
        </Model.Provider>
      </ViewModel.Provider>
    )
  },
)
Example #4
Source File: to.ts    From remind with MIT License 6 votes vote down vote up
function getSVGOuterHTML(view: RefObject<HTMLDivElement>) {
  const svgElement = view.current?.querySelector('svg')
  assert(svgElement, notFound)
  const outerHTML = svgElement.outerHTML.replace(/&nbsp;/g, ' ')
  return {
    svgElement,
    outerHTML,
  }
}
Example #5
Source File: to.ts    From remind with MIT License 6 votes vote down vote up
/**
 * generate svg content
 * @param view
 * @returns
 * @example
 * const { content } = toSVG(instance.current.view)
 * download(content, 'remind.svg')
 */
function toSVG(view: RefObject<HTMLDivElement>): { content: string } & DOMRect {
  const { svgElement, outerHTML } = getSVGOuterHTML(view)
  const svg = URL.createObjectURL(new Blob([head + outerHTML]))

  return {
    content: svg,
    ...svgElement.getBBox(),
  }
}
Example #6
Source File: to.ts    From remind with MIT License 6 votes vote down vote up
/**
 * generate PNG content
 * @param view
 * @returns
 * @example
 * const content = await toPNG(instance.current.view)
 * download(content, 'remind.png')
 */
async function toPNG(view: RefObject<HTMLDivElement>): Promise<string> {
  return new Promise((resolve) => {
    const { svgElement, outerHTML } = getSVGOuterHTML(view)
    const { width, height } = svgElement.getBBox()
    const img = new Image()
    img.src = URL.createObjectURL(
      new Blob([outerHTML], { type: 'image/svg+xml;charset=utf-8' }),
    )

    img.addEventListener('load', () => {
      const canvas = document.createElement('canvas')
      canvas.width = width
      canvas.height = height
      const ctx = canvas.getContext('2d')
      ctx?.drawImage(img, 0, 0, width, height)
      const imgURL = canvas.toDataURL()
      resolve(imgURL)
      canvas.remove()
    })
  })
}
Example #7
Source File: useEventListener.ts    From remind with MIT License 6 votes vote down vote up
function useEventListener<
  K extends keyof HTMLElementEventMap,
  E extends RefObject<HTMLElement>,
>(
  eventName: K,
  handler: (ev: HTMLElementEventMap[K]) => void,
  options: Options<E>,
): void {
  const targetElement = options.target?.current
  const { target, ...eventOptions } = options

  useEffect(() => {
    if (!targetElement) return
    targetElement.addEventListener(eventName, handler, eventOptions)

    return () => {
      targetElement.removeEventListener(eventName, handler, eventOptions)
    }
  }, [targetElement, handler, eventOptions])
}
Example #8
Source File: createMindmap.test.ts    From remind with MIT License 6 votes vote down vote up
test('should render value', async () => {
  const editorInstance: RefObject<ContributionAPI> = createMindmap(container, {
    value: root,
  })
  expect(editorInstance.current?.model.root).equal(root)
  expect(
    editorInstance.current?.view.current?.innerHTML.includes(root.title),
  ).toBeTruthy()
})
Example #9
Source File: createMindmap.test.ts    From remind with MIT License 6 votes vote down vote up
test('should onChange work', async () => {
  expect.hasAssertions()
  const onChange = fn(() => null)
  const editorInstance: RefObject<ContributionAPI> = createMindmap(container, {
    onChange,
  })
  editorInstance.current?.model.update((model) => {
    model.root.title = 'test'
  })
  await delay(1000)
  expect(onChange.mock.calls.length).toBe(1)
})
Example #10
Source File: IbanInput.tsx    From adyen-web with MIT License 5 votes vote down vote up
private ibanNumber: RefObject<any>;
Example #11
Source File: header.ts    From gridjs with MIT License 5 votes vote down vote up
/**
   * Tries to automatically adjust the width of columns based on:
   *    - Header cell content
   *    - Cell content of the first row
   *    - Cell content of the last row
   *
   * @param config
   */
  adjustWidth(config: Config): this {
    const container: Element = config.container;
    const tableRef: RefObject<Component> = config.tableRef;
    const tempRef: RefObject<HTMLDivElement> = config.tempRef;
    const autoWidth = config.tempRef || true;

    if (!container) {
      // we can't calculate the width because the container
      // is unknown at this stage
      return this;
    }

    // pixels
    const containerWidth = container.clientWidth;

    // let's create a shadow table with the first 10 rows of the data
    // and let the browser to render the table with table-layout: auto
    // no padding, margin or border to get the minimum space required
    // to render columns. One the table is rendered and widths are known,
    // we unmount the shadow table from the DOM and set the correct width
    const shadowTable = createRef();
    let widths = {};

    if (tableRef.current && autoWidth) {
      // render a ShadowTable with the first 10 rows
      const el = h(ShadowTable, {
        tableRef: tableRef,
      });
      el.ref = shadowTable;

      render(el, tempRef.current);

      widths = shadowTable.current.widths();
    }

    for (const column of flatten(Header.tabularFormat(this.columns))) {
      // because we don't want to set the width of parent THs
      if (column.columns && column.columns.length > 0) {
        continue;
      }

      if (!column.width && autoWidth) {
        // tries to find the corresponding cell
        // from the ShadowTable and set the correct width

        if (column.id in widths) {
          // because a column can be hidden, too
          column.width = px(widths[column.id]['width']);
          column.minWidth = px(widths[column.id]['minWidth']);
        }
      } else {
        // column width is already defined
        // sets the column with based on the width of its container
        column.width = px(width(column.width, containerWidth));
      }
    }

    if (tableRef.current && autoWidth) {
      // unmount the shadow table from temp
      render(null, tempRef.current);
    }

    return this;
  }
Example #12
Source File: Mindmap.tsx    From remind with MIT License 5 votes vote down vote up
Mindmap = forwardRef(
  (props: MindmapProps, ref: RefObject<ContributionAPI>) => {
    const { onChange, contributions, layout, theme } = props
    const model = Model.useContainer()
    const viewModel = ViewModel.useContainer()
    const editorRef = useRef<HTMLDivElement>(null)
    const { root } = model
    const textEditor = useTextEditor()
    const contributionAPI = useContributionAPI({
      view: editorRef,
      layout,
      textEditor,
    })
    const { slots } = useContributions(contributionAPI, contributions)
    const mindmapSlots = slots.filter(
      (slot) => slot?.viewType === ViewType.mindmap,
    )
    const { mindmap: mindmapTheme } = theme

    const { layoutRoot, canvasWidth, canvasHeight } = useMemo(() => {
      return doLayout(root, { layout, theme })
    }, [root, layout, theme])

    debug('layoutRoot', layoutRoot)

    useEffect(() => {
      onChange?.(root)
    }, [root])

    useEffect(() => {
      viewModel.setLayoutRoot(layoutRoot)
    }, [layoutRoot])

    useImperativeHandle(ref, () => contributionAPI, [contributionAPI])

    useEffect(() => {
      try {
        editorRef.current.scrollIntoView({ block: 'center', inline: 'center' })
      } catch {}
    }, [])

    return (
      <div className={styles.container}>
        <div
          className={styles.scrollContainer}
          style={{ background: mindmapTheme.background }}
        >
          <div
            ref={editorRef}
            data-type={ViewType.mindmap}
            className={styles.editor}
            style={{
              width: toPX(canvasWidth),
              height: toPX(canvasHeight),
            }}
            draggable
          >
            <svg
              className={styles.svgCanvas}
              width={canvasWidth}
              height={canvasHeight}
              xmlns="http://www.w3.org/2000/svg"
              // to make generated svg has background color
              style={{ background: mindmapTheme.background }}
            >
              <Links layoutRoot={layoutRoot} layout={layout} />
              <Topics layoutRoot={layoutRoot} />
            </svg>
            {textEditor.editor}
            {mindmapSlots}
          </div>
        </div>
      </div>
    )
  },
)
Example #13
Source File: createMindmap.test.ts    From remind with MIT License 5 votes vote down vote up
test('should render mindmap', async () => {
  const editorInstance: RefObject<ContributionAPI> = createMindmap(container)
  expect(types.isMindmap(editorInstance.current?.view.current)).toBe(true)
})
Example #14
Source File: ColourSwatches.tsx    From revite with GNU Affero General Public License v3.0 5 votes vote down vote up
export default function ColourSwatches({ value, onChange }: Props) {
    const ref = useRef<HTMLInputElement>() as RefObject<HTMLInputElement>;
    const setValue = useDebounceCallback(
        (value) => onChange(value as string),
        [onChange],
        100,
    );

    return (
        <SwatchesBase>
            <input
                type="color"
                value={value}
                ref={ref}
                onChange={(ev) => setValue(ev.currentTarget.value)}
            />
            <Swatch
                colour={value}
                type="large"
                onClick={() => ref.current?.click()}>
                <Palette size={32} />
            </Swatch>

            <div class="overlay">
                <div />
            </div>

            <Rows>
                {presets.map((row, i) => (
                    <div key={i}>
                        {row.map((swatch, i) => (
                            <Swatch
                                colour={swatch}
                                type="small"
                                key={i}
                                onClick={() => onChange(swatch)}>
                                {swatch === value && <Check size={22} />}
                            </Swatch>
                        ))}
                    </div>
                ))}
            </Rows>
        </SwatchesBase>
    );
}
Example #15
Source File: TextAreaAutoSize.tsx    From revite with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function TextAreaAutoSize(props: TextAreaAutoSizeProps) {
    const {
        autoFocus,
        minHeight,
        maxRows,
        value,
        padding,
        lineHeight,
        hideBorder,
        forceFocus,
        onChange,
        ...textAreaProps
    } = props;

    const ref = useRef<HTMLTextAreaElement>() as RefObject<HTMLTextAreaElement>;
    const ghost = useRef<HTMLDivElement>() as RefObject<HTMLDivElement>;

    useLayoutEffect(() => {
        if (ref.current && ghost.current) {
            ref.current.style.height = `${ghost.current.clientHeight}px`;
        }
    }, [ghost, props.value]);

    useEffect(() => {
        if (isTouchscreenDevice) return;
        autoFocus && ref.current && ref.current.focus();
    }, [value, autoFocus]);

    const inputSelected = () =>
        ["TEXTAREA", "INPUT"].includes(document.activeElement?.nodeName ?? "");

    useEffect(() => {
        if (!ref.current) return;
        if (forceFocus) {
            ref.current.focus();
        }

        if (isTouchscreenDevice) return;
        if (autoFocus && !inputSelected()) {
            ref.current.focus();
        }

        // ? if you are wondering what this is
        // ? it is a quick and dirty hack to fix
        // ? value not setting correctly
        // ? I have no clue what's going on
        // ref.current.value = value;
        // * commented out of 30-08-21
        // * hopefully nothing breaks :v

        if (!autoFocus) return;
        function keyDown(e: KeyboardEvent) {
            if ((e.ctrlKey && e.key !== "v") || e.altKey || e.metaKey) return;
            if (e.key.length !== 1) return;
            if (ref && !inputSelected()) {
                ref.current!.focus();
            }
        }

        document.body.addEventListener("keydown", keyDown);
        return () => document.body.removeEventListener("keydown", keyDown);
    }, [ref, autoFocus, forceFocus, value]);

    useEffect(() => {
        if (!ref.current) return;
        function focus(id: string) {
            if (id === props.id) {
                ref.current!.focus();
            }
        }

        return internalSubscribe(
            "TextArea",
            "focus",
            focus as (...args: unknown[]) => void,
        );
    }, [props.id, ref]);

    return (
        <Container>
            <TextArea
                ref={ref}
                value={value}
                padding={padding}
                style={{ minHeight }}
                hideBorder={hideBorder}
                lineHeight={lineHeight}
                onChange={(ev) => {
                    onChange && onChange(ev);
                }}
                {...textAreaProps}
            />
            <Ghost
                lineHeight={lineHeight ?? "var(--textarea-line-height)"}
                maxRows={maxRows ?? 5}>
                <div ref={ghost} style={{ padding }}>
                    {props.value
                        ? props.value
                              .split("\n")
                              .map((x) => `\u200e${x}`)
                              .join("\n")
                        : undefined ?? "‎\n"}
                </div>
            </Ghost>
        </Container>
    );
}