lodash-es#uniq TypeScript Examples

The following examples show how to use lodash-es#uniq. 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: random.spec.ts    From s-libs with MIT License 5 votes vote down vote up
describe('random()', () => {
  const iterations = 1000;

  it('treats the min as 0 when only provided one integer', () => {
    expect(uniq(times(iterations, () => random(2))).sort()).toEqual([0, 1, 2]);
  });

  //
  // stolen from https://github.com/lodash/lodash
  //

  it('should return `0` or `1` when no arguments are given', () => {
    expect(uniq(times(iterations, () => random())).sort()).toEqual([0, 1]);
  });

  it('should support a `min` and `max`', () => {
    for (let i = iterations; --i >= 0; ) {
      const result = random(5, 10);
      expect(result).toBeGreaterThanOrEqual(5);
      expect(result).toBeLessThanOrEqual(10);
    }
  });

  it('should support not providing a `max`', () => {
    for (let i = iterations; --i >= 0; ) {
      const result = random(5);
      expect(result).toBeGreaterThanOrEqual(0);
      expect(result).toBeLessThanOrEqual(5);
    }
  });

  it('should swap `min` and `max` when `min` > `max`', () => {
    const result = uniq(times(iterations, () => random(4, 2))).sort();
    expect(result).toEqual([2, 3, 4]);
  });

  it('should support large integer values', () => {
    const min = 2 ** 31;
    const max = 2 ** 62;
    for (let i = iterations; --i >= 0; ) {
      const result = random(min, max);
      expect(result).toBeGreaterThanOrEqual(min);
      expect(result).toBeLessThanOrEqual(max);
    }
  });

  it('should support floats', () => {
    const result = random(1.5, 1.6);
    expect(result).toBeGreaterThanOrEqual(1.5);
    expect(result).toBeLessThanOrEqual(1.6);
  });

  it('should support providing a `floating`', () => {
    let result: number;

    result = random(true);
    expect(result).toBeGreaterThanOrEqual(0);
    expect(result).toBeLessThanOrEqual(1);
    expect(result % 1).not.toBe(0);

    result = random(2, true);
    expect(result).toBeGreaterThanOrEqual(0);
    expect(result).toBeLessThanOrEqual(2);
    expect(result % 1).not.toBe(0);

    result = random(2, 4, true);
    expect(result).toBeGreaterThanOrEqual(2);
    expect(result).toBeLessThanOrEqual(4);
    expect(result % 1).not.toBe(0);
  });
});
Example #2
Source File: UUICustomizeNode.tsx    From UUI with MIT License 4 votes vote down vote up
export function IntrinsicNode<T extends keyof JSX.IntrinsicElements, N extends string>(tagName: T, nodeName: N, options: NodeCustomizeOptions) {
  const nodeClassName = [options.prefix, options.name, nodeName].join(options.separator)

  const Node = React.forwardRef((innerProps: JSX.IntrinsicElements[T], _ref) => {
    const { customize } = (MemoNode as any)['CustomizeProps'] as Readonly<{ customize?: IntrinsicNodeCustomizeProps }>
    const id = customize?.overrideId || innerProps.id
    const className = (() => {
      if (customize?.overrideClassName) return customize.overrideClassName
      const innerClassName = innerProps.className
      const finalClassName = classNames(nodeClassName, innerClassName, customize?.extendClassName)
      return finalClassName
    })()
    const style = (() => {
      if (customize?.overrideStyle) return customize.overrideStyle
      const innerStyle = innerProps.style
      const finalStyle = merge(innerStyle, customize?.extendStyle)
      return isEmpty(finalStyle) ? undefined : finalStyle
    })()
    const dataAttributes = (() => {
      if (!customize?.dataAttributes) return {}
      /**
       * @reference https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Name
       * TODO: // fix regex for supporting unicode
       */
      const validDataAttributesCharactersRegex = /^([A-Za-z0-9-])*$/
      let result = customize.dataAttributes
      result = pickBy(result, (v, k) => validDataAttributesCharactersRegex.test(k))
      result = mapKeys(result, (v, k) => `data-${k}`)
      return result
    })()
    const children = (() => {
      /**
       * <select><option> only support string type children,
       * if pass Fragments to children, it will show [Object Object] in html.
       */
      if (tagName === 'option') return innerProps.children
      /**
       * <input> <textarea> <hr> is a void element tag and must not have `children`.
       */
      if (['input', 'textarea', 'hr'].includes(tagName)) return undefined
      if (customize?.overrideChildren) return customize.overrideChildren
      return <>{customize?.extendChildrenBefore}{innerProps.children}{customize?.extendChildrenAfter}</>
    })()

    const ariaAttributes = (() => {
      if (!customize?.ariaAttributes) return {}
      return mapKeys(customize.ariaAttributes, (v, k) => `aria-${k}`)
    })()

    /**
     * Merge both customize ref and component inner ref.
     */
    const ref = mergeRefs([customize?.ref, _ref])

    /**
     * Merge both customize functions and component inner onXXX callback functions.
     */
    const mergedCallbackFunctions = (() => {
      const propsObj = innerProps as any
      const customizeObj = (customize || {}) as any

      const data: any = {}
      const attrs = uniq([
        ...Object.keys(propsObj),
        ...Object.keys(customizeObj),
      ])
      for (const attr of attrs) {
        if (attr.startsWith('on')) {
          const propsObjFunctionExist = !!(propsObj[attr] && typeof propsObj[attr] === 'function')
          const customizeObjFunctionExist = !!(customizeObj[attr] && typeof customizeObj[attr] === 'function')

          data[attr] = (...args: any[]) => {
            if (propsObjFunctionExist) {
              propsObj[attr](...args);
            }
            if (customizeObjFunctionExist) {
              customizeObj[attr](...args);
            }
          };
        }
      }
      return data
    })()

    return React.createElement(tagName, {
      ...omit(innerProps, 'children', 'ref', 'className', 'style'),
      ...mergedCallbackFunctions,
      ...dataAttributes,
      ...ariaAttributes,
      ref,
      id, className, style,
    }, children)
  })
  const MemoNode = React.memo(Node)
  MemoNode.type.displayName = `<UUI> [IntrinsicNode] ${nodeName}`
  return MemoNode
}
Example #3
Source File: edit-detail.tsx    From bext with MIT License 4 votes vote down vote up
Content: FC = () => {
  const { draft, setDraft } = useDraft();
  const { tagList } = useMeta();
  const tagOptions = useMemo(
    () =>
      uniq([...tagList.map(({ name }) => name), ...(draft?.tags || [])]).map(
        (tag) => ({
          key: tag,
          text: tag,
        }),
      ),
    [tagList, draft?.tags],
  );

  const [matchInput, setMatchInput] = useState(
    () => draft?.match?.join('@@') || '',
  );
  useEffect(() => {
    setDraft({
      match: matchInput
        ? matchInput.split('@@').filter((rule) => rule)
        : undefined,
    });
  }, [matchInput, setDraft]);

  return (
    <>
      <div className="grid grid-cols-3 gap-3">
        <TextField
          label="脚本ID"
          value={draft?.id || ''}
          onChange={(_, id = '') => setDraft({ id })}
          errorMessage={
            ID_RULE.test(draft?.id || '') ? undefined : '只允许数字 ID'
          }
        />
        <TextField
          label="脚本名称"
          value={draft?.name || ''}
          onChange={(_, name = '') => setDraft({ name })}
        />
        <TextField
          label="版本"
          value={draft?.version || ''}
          onChange={(_, version = '') => setDraft({ version })}
        />
      </div>
      <Dropdown
        className="flex-1"
        label="分类标签"
        multiSelect
        options={tagOptions}
        selectedKeys={draft?.tags || []}
        onChange={(_, item) =>
          setDraft({
            tags: item?.selected
              ? [...(draft?.tags || []), String(item.key)]
              : draft?.tags?.filter((key) => key !== item?.key),
          })
        }
      />
      <TextField
        label="简介"
        multiline
        placeholder="70字以内"
        value={draft?.synopsis || ''}
        onChange={(_, text) => {
          setDraft({ synopsis: text?.slice(0, 70) });
        }}
      />
      <TextField
        label="匹配规则(使用 @@ 分隔,匹配所有请留空)"
        value={matchInput}
        onChange={(_, text) => setMatchInput(text || '')}
        description={`当前将会匹配
        ${
          typeof draft?.match === 'undefined'
            ? '所有网站'
            : `以下网站:${draft.match.join(', ')}`
        }`}
      />
      <Label>详情(支持内联图片,请直接粘贴)</Label>
      <RichEditor
        defaultHtml={draft?.detail}
        onChange={(html) => setDraft({ detail: html })}
      />
      <TextField
        label="附加元信息"
        multiline
        value={draft?.extra?.xMetaComment || ''}
        onChange={(_, text) => {
          setDraft({
            extra: set(cloneDeep(draft?.extra ?? {}), 'xMetaComment', text),
          });
        }}
        description="专用于 X 浏览器和 Top 浏览器的元信息,填写示例:'// @run-at document-start'(去除单引号,保留注释符号),已自动生成无需在这里填写的:name、namespace、version、description、author、match"
      />
    </>
  );
}