components#Select TypeScript Examples

The following examples show how to use components#Select. 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: multiple.test.tsx    From geist-ui with MIT License 6 votes vote down vote up
it('should trigger event correctly when clicked', async () => {
  const changeHandler = jest.fn()
  const wrapper = mount(
    <Select onChange={changeHandler} multiple initialValue={['1']}>
      <Select.Option value="1">1</Select.Option>
      <Select.Option value="2">Option 2</Select.Option>
    </Select>,
  )
  expect(wrapper.find('.clear-icon').length).toBe(1)
  wrapper.find('.clear-icon').simulate('click', nativeEvent)
  await updateWrapper(wrapper, 350)
  expect(changeHandler).toHaveBeenCalled()
  expect(wrapper.find('.clear-icon').length).toBe(0)
})
Example #2
Source File: events.test.tsx    From geist-ui with MIT License 5 votes vote down vote up
describe('Select Events', () => {
  let container: HTMLDivElement

  beforeEach(() => {
    container = document.createElement('div')
    document.body.append(container)
  })

  it('ref should be able to control the focus correctly', () => {
    const ref = React.createRef<HTMLDivElement>()
    const wrapper = mount(<Select ref={ref} />, { attachTo: container })
    const input = wrapper.find('input').at(0).getDOMNode()
    expect(document.activeElement?.outerHTML).not.toEqual(input.outerHTML)
    ref.current?.focus()
    expect(document.activeElement?.outerHTML).toEqual(input.outerHTML)
    ref.current?.blur()
    expect(document.activeElement?.outerHTML).not.toEqual(input.outerHTML)
  })

  it('should prevent mouse event when click background', async () => {
    let visible = false
    const handler = jest.fn().mockImplementation(next => {
      visible = next
    })
    const wrapper = mount(<Select onDropdownVisibleChange={handler} />, {
      attachTo: container,
    })
    expect(visible).toBe(false)
    expect(handler).not.toBeCalled()
    wrapper.find('.select').simulate('click', nativeEvent)
    await updateWrapper(wrapper, 300)
    expect(visible).toBe(true)
    expect(handler).toBeCalledTimes(1)

    wrapper.find('.dropdown').simulate('click', nativeEvent)
    await updateWrapper(wrapper, 300)
    expect(visible).toBe(true)
    expect(handler).toBeCalledTimes(1)
  })

  it('scrollTo should be work correctly', async () => {
    const ref = React.createRef<HTMLDivElement>()
    const handler = jest.fn()
    window.HTMLElement.prototype.scrollTo = jest.fn().mockImplementation(handler)
    const wrapper = mount(
      <Select ref={ref}>
        <Select.Option value="hello">world</Select.Option>
      </Select>,
      { attachTo: container },
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    await updateWrapper(wrapper, 300)
    ref.current?.scrollTo({ top: 200 })
    expect(handler).toBeCalled()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  afterEach(() => {
    document.body.removeChild(container!)
  })
})
Example #3
Source File: multiple.test.tsx    From geist-ui with MIT License 5 votes vote down vote up
describe('Select Multiple', () => {
  it('should render correctly', () => {
    const wrapper = mount(
      <Select multiple>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    expect(wrapper.html()).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('should render correctly with clearable option', () => {
    const wrapper = mount(
      <Select multiple initialValue={['1']}>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    expect(wrapper.find('.clear-icon').length).toBe(1)
  })

  it('should render correctly without clearable option', () => {
    const wrapper = mount(
      <Select multiple clearable={false} initialValue={['1']}>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    expect(wrapper.find('.clear-icon').length).toBe(0)
  })

  it('should render value with initial-value', () => {
    const wrapper = mount(
      <Select initialValue={['1', '2']} multiple>
        <Select.Option value="1">test-1</Select.Option>
        <Select.Option value="2">test-2</Select.Option>
        <Select.Option value="3">test-3</Select.Option>
      </Select>,
    )
    expect(wrapper.find('.option').length).toBeGreaterThan(1)
    const text = wrapper
      .find('.option')
      .map(item => item.text())
      .reduce((pre, current) => `${pre}${current}`, '')
    expect(text.includes('test-1')).toBeTruthy()
    expect(text.includes('test-2')).toBeTruthy()
    expect(text.includes('test-3')).not.toBeTruthy()
  })

  it('should trigger events when option changed', async () => {
    let value = ''
    const changeHandler = jest.fn().mockImplementation(val => (value = val))
    const wrapper = mount(
      <Select onChange={changeHandler} multiple>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    wrapper.find('.select-dropdown').find('.option').at(0).simulate('click', nativeEvent)
    await updateWrapper(wrapper, 350)
    expect(changeHandler).toHaveBeenCalled()
    expect(Array.isArray(value)).toBeTruthy()
    expect(value.includes('1')).toBeTruthy()

    wrapper.find('.select-dropdown').find('.option').at(0).simulate('click', nativeEvent)
    await updateWrapper(wrapper, 350)
    expect(Array.isArray(value)).toBeTruthy()
    expect(value.includes('1')).not.toBeTruthy()
    changeHandler.mockRestore()
  })
})
Example #4
Source File: EnvironmentFormSection.tsx    From one-platform with MIT License 4 votes vote down vote up
EnvironmentFormSection = ({
  schemaPos,
  handleSchemaValidation,
}: Props): JSX.Element => {
  const [envNames, setEnvNames] = useState(['prod', 'stage', 'qa', 'dev']);
  const { control, watch, getValues, setError, clearErrors, setValue } = useFormContext<FormData>();
  const isGraphqlAPI = watch(`schemas.${schemaPos}.category`) === ApiCategory.GRAPHQL;
  const { fields, append, remove } = useFieldArray({
    control,
    name: `schemas.${schemaPos}.environments`,
  });

  const handleAddNewEnvironment = () => {
    append(
      {
        name: '',
        apiBasePath: '',
        headers: [{ key: '', value: '', id: undefined }],
        schemaEndpoint: '',
        isPublic: false,
      },
      { shouldFocus: false }
    );
  };

  const onEnvNameClear = (onChange: (...event: any[]) => void) => {
    onChange('');
  };

  const onEnvNameSelect = (
    onChange: (...event: any[]) => void,
    event: React.MouseEventHandler,
    selection: string,
    isPlaceholder: boolean
  ) => {
    if (isPlaceholder) onEnvNameClear(onChange);
    else {
      onChange(selection);
    }
  };

  const onEnvNameCreate = (newSelection: string) => {
    if (envNames.findIndex((envName) => envName === newSelection) === -1) {
      setEnvNames((envState) => [...envState, newSelection]);
    }
  };

  const onSetIntrospectionQuery = (envIndex: number) => {
    const selectedEnv = `schemas.${schemaPos}.environments.${envIndex}` as const;
    const value = getValues(selectedEnv);
    setValue(`schemas.${schemaPos}.environments.${envIndex}.schemaEndpoint`, value.apiBasePath);
  };

  const setSchemaEndpointIsInvalid = (envIndex: number) => {
    setError(`schemas.${schemaPos}.environments.${envIndex}.schemaEndpoint`, {
      type: 'custom',
      message: `Failed to get ${isGraphqlAPI ? 'introspection url' : 'api schema'}`,
    });
  };

  const handleSchemaVerification = async (envIndex: number, schemaURL: string) => {
    if (!schemaURL) return;
    const isURL = isValidURL(schemaURL);
    const selectedEnv = `schemas.${schemaPos}.environments.${envIndex}` as const;
    if (isURL) {
      const envData = getValues(selectedEnv) as ApiEnvironmentType;
      const { slug, schemaEndpoint } = envData;
      const category = isGraphqlAPI ? ApiCategory.GRAPHQL : ApiCategory.REST;
      const headers = (envData?.headers || []).filter(({ key, value }) => key && value) as Header[];

      const data = await handleSchemaValidation({
        headers,
        schemaEndpoint,
        envSlug: slug,
        category,
      });
      if (!data?.file) {
        setSchemaEndpointIsInvalid(envIndex);
      } else {
        clearErrors(`schemas.${schemaPos}.environments.${envIndex}.schemaEndpoint`);
      }
    } else {
      setSchemaEndpointIsInvalid(envIndex);
      window.OpNotification.danger({ subject: 'Invalid schema url provided' });
    }
  };

  return (
    <Stack hasGutter className="pf-u-mt-md">
      <StackItem>
        <p className="pf-u-font-weight-bold">Environments</p>
      </StackItem>
      <StackItem>
        <Stack hasGutter>
          {fields.map((field, index) => (
            <StackItem key={field.id}>
              <Card id={field.id}>
                <CardBody>
                  <Grid hasGutter>
                    <GridItem span={3}>
                      <Controller
                        name={`schemas.${schemaPos}.environments.${index}.name`}
                        control={control}
                        rules={{ required: true }}
                        defaultValue=""
                        render={({ field: controllerField, fieldState: { error } }) => (
                          <FormGroup
                            fieldId={`schemas.${schemaPos}.environments.${index}.name`}
                            label="Name"
                            isRequired
                            validated={error ? 'error' : 'success'}
                            helperTextInvalid={error?.message}
                          >
                            <Select
                              variant={SelectVariant.typeahead}
                              typeAheadAriaLabel="Select a state"
                              onSelect={callbackify(onEnvNameSelect, controllerField.onChange)}
                              onClear={callbackify(onEnvNameClear, controllerField.onChange)}
                              selections={controllerField.value}
                              aria-label="env link"
                              placeholder="Enter environment name"
                              isCreatable
                              onCreateOption={onEnvNameCreate}
                              placeholderText="Enter environment name"
                            >
                              {envNames.map((env, envIndex) => (
                                <SelectOption key={`${env}-${envIndex + 1}`} value={env} />
                              ))}
                            </Select>
                          </FormGroup>
                        )}
                      />
                    </GridItem>
                    <GridItem span={8}>
                      <Controller
                        name={`schemas.${schemaPos}.environments.${index}.apiBasePath`}
                        control={control}
                        rules={{ required: true }}
                        defaultValue=""
                        render={({ field: controllerField, fieldState: { error } }) => (
                          <FormGroup
                            fieldId={`schemas.${schemaPos}.environments.${index}.apiBasePath`}
                            label="API Base Path"
                            isRequired
                            validated={error ? 'error' : 'success'}
                            helperTextInvalid={error?.message}
                          >
                            <TextInput
                              aria-label="env link"
                              placeholder="Enter base path for the api"
                              {...controllerField}
                            />
                          </FormGroup>
                        )}
                      />
                    </GridItem>
                    <GridItem
                      span={1}
                      className="pf-u-display-flex pf-u-justify-content-center pf-u-align-items-flex-end"
                    >
                      <Button
                        variant="secondary"
                        aria-label="Remove"
                        onClick={callbackify(remove, index)}
                        className={styles['trash-button']}
                      >
                        <TrashIcon />
                      </Button>
                    </GridItem>
                    <GridItem span={12}>
                      <Controller
                        name={`schemas.${schemaPos}.environments.${index}.schemaEndpoint`}
                        control={control}
                        rules={{ required: true }}
                        defaultValue=""
                        render={({ field: { ...controllerField }, fieldState: { error } }) => (
                          <EnvSchemaField
                            isGraphqlAPI={isGraphqlAPI}
                            isError={Boolean(error)}
                            errorMessage={error?.message}
                            envIndex={index}
                            onCopyValue={() => onSetIntrospectionQuery(index)}
                            onRedoValidation={() =>
                              handleSchemaVerification(index, controllerField.value || '')
                            }
                            {...controllerField}
                          />
                        )}
                      />
                    </GridItem>
                    <GridItem span={12}>
                      <EnvHeaderFormSection schemaPos={schemaPos} envPos={index} />
                    </GridItem>
                    <GridItem span={12}>
                      <Controller
                        name={`schemas.${schemaPos}.environments.${index}.isPublic`}
                        defaultValue={false}
                        render={({ field: controllerField }) => (
                          <Checkbox
                            label="Is this API accessible from public?"
                            description="Tick this option if your environment can be accessed without VPN"
                            isChecked={controllerField.value}
                            id={`api-schema-${schemaPos}-env-${index}-internal`}
                            {...controllerField}
                          />
                        )}
                      />
                    </GridItem>
                  </Grid>
                </CardBody>
              </Card>
            </StackItem>
          ))}
        </Stack>
      </StackItem>
      <StackItem>
        <Button
          variant="link"
          icon={<PlusIcon size="sm" />}
          className="pf-u-p-0 pf-u-mb-lg"
          onClick={handleAddNewEnvironment}
        >
          Add Environment
        </Button>
      </StackItem>
    </Stack>
  );
}
Example #5
Source File: index.test.tsx    From geist-ui with MIT License 4 votes vote down vote up
describe('Select', () => {
  it('should render correctly', () => {
    const wrapper = mount(
      <div>
        <Select />
        <Select scale={2} />
      </div>,
    )
    expect(wrapper.html()).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('should work with different status', () => {
    const wrapper = mount(
      <div>
        <Select type="secondary" />
        <Select type="success" />
        <Select type="warning" />
        <Select type="error" />
      </div>,
    )
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should work correctly with labels', () => {
    const wrapper = mount(
      <Select>
        <Select.Option label>1</Select.Option>
        <Select.Option divider>1</Select.Option>
        <Select.Option divider label>
          1
        </Select.Option>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    expect(wrapper.html()).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('should work with different icons', () => {
    const MockIcon = () => <span>icon</span>
    const pure = render(<Select pure />)
    expect(pure).toMatchSnapshot()

    const icon = render(<Select icon={MockIcon} />)
    expect(icon).toMatchSnapshot()
  })

  it('should render value with initial-value', () => {
    const wrapper = mount(
      <Select initialValue="2">
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    expect(wrapper.find('.value').text()).toContain('Option 2')
  })

  it('should trigger events when option changed', async () => {
    let value = ''
    const changeHandler = jest.fn().mockImplementation(val => (value = val))
    const wrapper = mount(
      <Select onChange={changeHandler}>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    wrapper.find('.select-dropdown').find('.option').at(0).simulate('click', nativeEvent)
    await updateWrapper(wrapper, 350)
    expect(changeHandler).toHaveBeenCalled()
    expect(value).toEqual('1')
    changeHandler.mockRestore()
  })

  it('should ignore events when disabled', async () => {
    const changeHandler = jest.fn()
    const wrapper = mount(
      <Select onChange={changeHandler} disabled>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    expect(wrapper.find('.select-dropdown').length).toBe(0)
    changeHandler.mockRestore()
  })

  it('should ignore option when option disabled', async () => {
    let value = ''
    const changeHandler = jest.fn().mockImplementation(val => (value = val))
    const wrapper = mount(
      <Select onChange={changeHandler}>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2" disabled>
          Option 2
        </Select.Option>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    wrapper.find('.select-dropdown').find('.option').at(1).simulate('click', nativeEvent)
    await updateWrapper(wrapper, 350)
    expect(changeHandler).not.toHaveBeenCalled()
    expect(value).not.toEqual('2')
    changeHandler.mockRestore()
  })

  it('should ignore option when prevent all', async () => {
    let value = ''
    const changeHandler = jest.fn().mockImplementation(val => (value = val))
    const wrapper = mount(
      <Select onChange={changeHandler}>
        <Select.Option value="1">1</Select.Option>
        <Select.Option value="2" preventAllEvents>
          Option 2
        </Select.Option>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)
    wrapper.find('.select-dropdown').find('.option').at(1).simulate('click', nativeEvent)
    await updateWrapper(wrapper, 350)
    expect(changeHandler).not.toHaveBeenCalled()
    expect(value).not.toEqual('2')
    changeHandler.mockRestore()
  })

  it('should be change when value changed', async () => {
    const wrapper = mount(
      <Select>
        <Select.Option value="1">Option 1</Select.Option>
        <Select.Option value="2">Option 2</Select.Option>
      </Select>,
    )

    wrapper.setProps({ value: '2' })
    await updateWrapper(wrapper, 300)
    expect(wrapper.find('.value').text()).toContain('Option 2')

    wrapper.setProps({ value: '1' })
    await updateWrapper(wrapper, 300)
    expect(wrapper.find('.value').text()).toContain('Option 1')
  })

  it('should be wraning when ident value missing', () => {
    let errorMessage = ''
    const errorSpy = jest
      .spyOn(console, 'error')
      .mockImplementation(msg => (errorMessage = msg))
    const SelectOption = Select.Option as any
    const wrapper = mount(
      <Select>
        <SelectOption>1</SelectOption>
      </Select>,
    )
    wrapper.find('.select').simulate('click', nativeEvent)

    expect(errorMessage).toContain('required')
    errorSpy.mockRestore()
  })
})
Example #6
Source File: demo.tsx    From geist-ui with MIT License 4 votes vote down vote up
Demo: React.FC<React.PropsWithChildren<unknown>> = () => {
  const theme = useTheme()
  const { isChinese } = useConfigs()

  return (
    <div className="demo">
      <div className="content">
        {isChinese ? (
          <>
            <Text h2 mb={0} font="13px" type="secondary">
              预览
            </Text>
            <Text>
              这里是你变更主题后的即时预览。此外,当你每次更新主题变量时,整个文档站点也会随之变化。
            </Text>
          </>
        ) : (
          <>
            <Text h2 mb={0} font="13px">
              PREVIEWS
            </Text>
            <Text>
              Here&#39;s a preview of your changes to the Theme. When you set the changes,
              the entire document site will change with the theme.
            </Text>
          </>
        )}

        <Spacer h={1.7} />
        <Text h3 font="13px" type="secondary">
          {isChinese ? '色彩' : 'COLORS'}
        </Text>
        <Colors />

        <Spacer h={1.7} />
        <Text h3 font="13px" type="secondary">
          {isChinese ? '排版' : 'Typography'}
        </Text>
        <Text>
          <Link rel="nofollow" href="https://en.wikipedia.org/wiki/HTTP/2" color>
            HTTP/2
          </Link>{' '}
          allows the server to <Code>push</Code> content, that is, to respond with data
          for more queries than the client requested. This allows the server to supply
          data it knows a web browser will need to render a web page, without waiting for
          the browser to examine the first response, and without the overhead of an
          additional request cycle.
        </Text>
        <Text h6>Heading</Text>
        <Text h5>Heading</Text>
        <Text h4>Heading</Text>
        <Text h3>Heading</Text>

        <Spacer h={1.7} />
        <Text h3 font="13px" type="secondary">
          {isChinese ? '基础组件' : 'Basic Components'}
        </Text>
        <Select width="90%" placeholder="Choose one" initialValue="1">
          <Select.Option value="1">Option 1</Select.Option>
          <Select.Option value="2">Option 2</Select.Option>
        </Select>
        <Spacer h={1} />
        <Grid.Container width="100%">
          <Grid xs={8}>
            <Button disabled auto>
              Action
            </Button>
          </Grid>
          <Grid xs={8}>
            <Button auto>Action</Button>
          </Grid>
          <Grid xs={8}>
            <Button auto type="secondary">
              Action
            </Button>
          </Grid>
        </Grid.Container>
      </div>
      <style jsx>{`
        .demo {
          width: 34%;
          margin-top: calc(${theme.layout.gap} * 2);
          margin-right: ${theme.layout.gap};
          padding-right: ${theme.layout.gapQuarter};
          position: relative;
          border-right: 1px solid ${theme.palette.border};
          height: auto;
          transition: width 200ms ease;
        }

        .content {
          width: 100%;
        }

        @media only screen and (max-width: ${theme.layout.breakpointMobile}) {
          .demo {
            display: none;
          }
        }
      `}</style>
    </div>
  )
}
Example #7
Source File: controls.tsx    From geist-ui with MIT License 4 votes vote down vote up
Controls: React.FC<unknown> = React.memo(() => {
  const theme = useTheme()
  const { themes } = useAllThemes()
  const { switchTheme, updateChineseState } = useConfigs()
  const { pathname } = useRouter()
  const { locale } = useLocale()
  const isChinese = useMemo(() => locale === CHINESE_LANGUAGE_IDENT, [locale])
  const nextLocalePath = useMemo(() => {
    const nextLocale = isChinese ? ENGLISH_LANGUAGE_IDENT : CHINESE_LANGUAGE_IDENT
    return pathname.replace(locale, nextLocale)
  }, [locale, pathname])
  const hasCustomTheme = useMemo(() => Themes.hasUserCustomTheme(themes), [themes])

  const switchThemes = (type: string) => {
    switchTheme(type)
    if (typeof window === 'undefined' || !window.localStorage) return
    window.localStorage.setItem('theme', type)
  }
  const switchLanguages = () => {
    updateChineseState(!isChinese)
    Router.push(nextLocalePath)
  }
  const redirectGithub = () => {
    if (typeof window === 'undefined') return
    window.open(GITHUB_URL)
  }

  return (
    <div className="wrapper">
      <Keyboard
        h="28px"
        command
        font="12px"
        className="shortcuts"
        title="Command + K to search.">
        K
      </Keyboard>
      <Spacer w={0.75} />
      <Button
        w="28px"
        h="28px"
        py={0}
        px={0}
        onClick={switchLanguages}
        title={isChinese ? '切换语言' : 'switch language'}>
        <Text font="13px" style={{ fontWeight: 500 }}>
          {isChinese ? 'En' : '中'}
        </Text>
      </Button>
      <Spacer w={0.75} />
      <Button
        w="28px"
        h="28px"
        py={0}
        px={0}
        icon={<GitHubIcon />}
        onClick={redirectGithub}
        title={isChinese ? '代码仓库' : 'GitHub Repository'}
      />
      <Spacer w={0.75} />
      <Select
        scale={0.5}
        h="28px"
        pure
        onChange={switchThemes}
        value={theme.type}
        title={isChinese ? '切换主题' : 'Switch Themes'}>
        <Select.Option value="light">
          <span className="select-content">
            <SunIcon size={14} /> {isChinese ? '明亮' : 'Light'}
          </span>
        </Select.Option>
        <Select.Option value="dark">
          <span className="select-content">
            <MoonIcon size={14} /> {isChinese ? '暗黑' : 'Dark'}
          </span>
        </Select.Option>
        {hasCustomTheme && (
          <Select.Option value={CUSTOM_THEME_TYPE}>
            <span className="select-content">
              <UserIcon size={14} /> {CUSTOM_THEME_TYPE}
            </span>
          </Select.Option>
        )}
      </Select>
      <style jsx>{`
        .wrapper {
          display: flex;
          align-items: center;
        }
        .wrapper :global(kbd.shortcuts) {
          line-height: 28px !important;
          cursor: help;
          opacity: 0.75;
          border: none;
        }
        .wrapper :global(.select) {
          width: 85px;
          min-width: 85px;
        }
        .select-content {
          width: auto;
          height: 18px;
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
        .select-content :global(svg) {
          margin-right: 10px;
          margin-left: 2px;
        }
      `}</style>
    </div>
  )
})