<commit_before>/**
 * This file contains an runtime version of `styled` component. Responsibilities of the component are:
 * - returns ReactElement based on HTML tag used with `styled` or custom React Component
 * - injects classNames for the returned component
 * - injects CSS variables used to define dynamic styles based on props
 */
import React from 'react';
import validAttr from '@emotion/is-prop-valid';
import { cx } from '@linaria/core';
import type { CSSProperties, StyledMeta } from '@linaria/core';

export type NoInfer<A extends any> = [A][A extends any ? 0 : never];

type Options = {
  name: string;
  class: string;
  vars?: {
    [key: string]: [
      string | number | ((props: unknown) => string | number),
      string | void
    ];
  };
};

interface CustomOmit {
  <T extends object, K extends [...(keyof T)[]]>(obj: T, keys: K): {
    [K2 in Exclude<keyof T, K[number]>]: T[K2];
  };
}

// Workaround for rest operator
export const restOp: CustomOmit = (obj, keys) => {
  const res = {} as { [K in keyof typeof obj]: typeof obj[K] };
  let key: keyof typeof obj;
  for (key in obj) {
    if (keys.indexOf(key) === -1) {
      res[key] = obj[key];
    }
  }
  return res;
};

const warnIfInvalid = (value: any, componentName: string) => {
  if (process.env.NODE_ENV !== 'production') {
    if (
      typeof value === 'string' ||
      // eslint-disable-next-line no-self-compare
      (typeof value === 'number' && isFinite(value))
    ) {
      return;
    }

    const stringified =
      typeof value === 'object' ? JSON.stringify(value) : String(value);

    // eslint-disable-next-line no-console
    console.warn(
      `An interpolation evaluated to '${stringified}' in the component '${componentName}', which is probably a mistake. You should explicitly cast or transform the value to a string.`
    );
  }
};

interface IProps {
  className?: string;
  style?: Record<string, string>;
  [props: string]: unknown;
}

// If styled wraps custom component, that component should have className property
function styled<TConstructor extends React.FunctionComponent<any>>(
  tag: TConstructor extends React.FunctionComponent<infer T>
    ? [T] extends [{ className?: string | undefined }]
      ? TConstructor
      : never
    : never
): ComponentStyledTag<TConstructor>;
function styled<T>(
  tag: [T] extends [{ className?: string | undefined }]
    ? React.ComponentType<T>
    : never
): ComponentStyledTag<T>;
function styled<TName extends keyof JSX.IntrinsicElements>(
  tag: TName
): HtmlStyledTag<TName>;
function styled(tag: any): any {
  return (options: Options) => {
    if (process.env.NODE_ENV !== 'production') {
      if (Array.isArray(options)) {
        // We received a strings array since it's used as a tag
        throw new Error(
          'Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly. See https://github.com/callstack/linaria#setup'<commit_msg>fix(react): fixed types for supporting class components (fixes #730) (#877)<commit_after>/**
 * This file contains an runtime version of `styled` component. Responsibilities of the component are:
 * - returns ReactElement based on HTML tag used with `styled` or custom React Component
 * - injects classNames for the returned component
 * - injects CSS variables used to define dynamic styles based on props
 */
import React from 'react';
import validAttr from '@emotion/is-prop-valid';
import { cx } from '@linaria/core';
import type { CSSProperties, StyledMeta } from '@linaria/core';

export type NoInfer<A extends any> = [A][A extends any ? 0 : never];

type Options = {
  name: string;
  class: string;
  vars?: {
    [key: string]: [
      string | number | ((props: unknown) => string | number),
      string | void
    ];
  };
};

interface CustomOmit {
  <T extends object, K extends [...(keyof T)[]]>(obj: T, keys: K): {
    [K2 in Exclude<keyof T, K[number]>]: T[K2];
  };
}

// Workaround for rest operator
export const restOp: CustomOmit = (obj, keys) => {
  const res = {} as { [K in keyof typeof obj]: typeof obj[K] };
  let key: keyof typeof obj;
  for (key in obj) {
    if (keys.indexOf(key) === -1) {
      res[key] = obj[key];
    }
  }
  return res;
};

const warnIfInvalid = (value: any, componentName: string) => {
  if (process.env.NODE_ENV !== 'production') {
    if (
      typeof value === 'string' ||
      // eslint-disable-next-line no-self-compare
      (typeof value === 'number' && isFinite(value))
    ) {
      return;
    }

    const stringified =
      typeof value === 'object' ? JSON.stringify(value) : String(value);

    // eslint-disable-next-line no-console
    console.warn(
      `An interpolation evaluated to '${stringified}' in the component '${componentName}', which is probably a mistake. You should explicitly cast or transform the value to a string.`
    );
  }
};

interface IProps {
  className?: string;
  style?: Record<string, string>;
  [props: string]: unknown;
}

// If styled wraps custom component, that component should have className property
function styled<TConstructor extends React.ComponentType<any>>(
  tag: TConstructor extends React.ComponentType<infer T>
    ? [T] extends [{ className?: string | undefined }]
      ? TConstructor
      : never
    : never
): ComponentStyledTag<TConstructor>;
function styled<T>(
  tag: [T] extends [{ className?: string | undefined }]
    ? React.ComponentType<T>
    : never
): ComponentStyledTag<T>;
function styled<TName extends keyof JSX.IntrinsicElements>(
  tag: TName
): HtmlStyledTag<TName>;
function styled(tag: any): any {
  return (options: Options) => {
    if (process.env.NODE_ENV !== 'production') {
      if (Array.isArray(options)) {
        // We received a strings array since it's used as a tag
        throw new Error(
          'Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly. See https://github.com/callstack/linaria#setup'
{'fraction_non_alphanumeric': 0.13010716677829873, 'fraction_numerical': 0.002344273275284662, 'mean_word_length': 3.4178994082840237, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4497045', 'n_tokens_mistral': 1794, 'n_tokens_neox': 1765, 'n_words': 616}