ronantakizawa/codereview-bench huggingface dataset:
Repository: lucide-icons/lucide
File: packages/lucide-react/src/types.ts (TypeScript)

Code before:
import type { SVGElementType, SVGProps, ForwardRefExoticComponent, RefAttributes } from 'react';

export type IconNode = [elementName: SVGElementType, attrs: Record<string, string>][];

export type SVGAttributes = Partial<SVGProps<SVGSVGElement>>;
type ElementAttributes = RefAttributes<SVGSVGElement> & SVGAttributes;

export interface LucideProps extends ElementAttributes {
  size?: string | number;
  absoluteStrokeWidth?: boolean;
}

export type LucideIcon = ForwardRefExoticComponent<
  Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>
>;


Review comment (suggestion):
```suggestion
type ElementName =
  'circle'
  | 'ellipse'
  | 'g'
  | 'line'
  | 'path'
  | 'polygon'
  | 'polyline'
  | 'rect';

export type IconNode = [elementName: ElementName, attrs: Record<string, string>][];
```

Code after:
import type { SVGProps, ForwardRefExoticComponent, RefAttributes } from 'react';

/**
 * A reduced version of `SVGElementType` from @types/react. This type was added
 * with the release of React 19, and is included here in order to support usage
 * with older versions.
 */
type SVGElementType =
  | 'circle'
  | 'ellipse'
  | 'g'
  | 'line'
  | 'path'
  | 'polygon'
  | 'polyline'
  | 'rect';

export type IconNode = [elementName: SVGElementType, attrs: Record<string, string>][];

export type SVGAttributes = Partial<SVGProps<SVGSVGElement>>;
type ElementAttributes = RefAttributes<SVGSVGElement> & SVGAttributes;

export interface LucideProps extends ElementAttributes {
  size?: string | number;
  absoluteStrokeWidth?: boolean;
}

export type LucideIcon = ForwardRefExoticComponent<
  Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>
>;
Repository: lucide-icons/lucide
File: packages/lucide-react/src/types.ts (TypeScript)

Code before:
import type { SVGElementType, SVGProps, ForwardRefExoticComponent, RefAttributes } from 'react';

export type IconNode = [elementName: SVGElementType, attrs: Record<string, string>][];

export type SVGAttributes = Partial<SVGProps<SVGSVGElement>>;
type ElementAttributes = RefAttributes<SVGSVGElement> & SVGAttributes;

export interface LucideProps extends ElementAttributes {
  size?: string | number;
  absoluteStrokeWidth?: boolean;
}

export type LucideIcon = ForwardRefExoticComponent<
  Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>
>;


Review comment (suggestion):
```suggestion
import type { SVGProps, ForwardRefExoticComponent, RefAttributes } from 'react';
```

Code after:
import type { SVGProps, ForwardRefExoticComponent, RefAttributes } from 'react';

/**
 * A reduced version of `SVGElementType` from @types/react. This type was added
 * with the release of React 19, and is included here in order to support usage
 * with older versions.
 */
type SVGElementType =
  | 'circle'
  | 'ellipse'
  | 'g'
  | 'line'
  | 'path'
  | 'polygon'
  | 'polyline'
  | 'rect';

export type IconNode = [elementName: SVGElementType, attrs: Record<string, string>][];

export type SVGAttributes = Partial<SVGProps<SVGSVGElement>>;
type ElementAttributes = RefAttributes<SVGSVGElement> & SVGAttributes;

export interface LucideProps extends ElementAttributes {
  size?: string | number;
  absoluteStrokeWidth?: boolean;
}
Repository: lucide-icons/lucide
File: packages/lucide-preact/src/createLucideIcon.ts (TypeScript)

Code before:
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';

/**
 * Create a Lucide icon component
 * @param {string} componentName
 * @param {array} iconNode
 * @param {string} iconName
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (
  componentName: string,
  iconNode: IconNode,
  iconName: string,
): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(componentName)}`,
          `lucide-${iconName}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = `${componentName}`;

  return Component;
};

export default createLucideIcon;


Review comment (suggestion):
This is a breaking change, what you could do is make the third parameter optional.
People use `createLucideIcon`, it's not only used internally.

Code after:
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase, toPascalCase } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';

/**
 * Create a Lucide icon component
 * @param {string} iconName
 * @param {array} iconNode
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(toPascalCase(iconName))}`,
          `lucide-${toKebabCase(iconName)}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = toPascalCase(iconName);

  return Component;
};

export default createLucideIcon;
Repository: lucide-icons/lucide
File: packages/lucide-preact/src/createLucideIcon.ts (TypeScript)

Code before:
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';

/**
 * Create a Lucide icon component
 * @param {string} componentName
 * @param {array} iconNode
 * @param {string} iconName
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (
  componentName: string,
  iconNode: IconNode,
  iconName: string,
): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(componentName)}`,
          `lucide-${iconName}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = `${componentName}`;

  return Component;
};

export default createLucideIcon;


Review comment (suggestion):
Alternatively we could make it, so the first argument is the actual iconName in kebabCase.
```suggestion
          `lucide-${toKebabCase(toPascalCase(iconName))}`,
          `lucide-${toKebabCase(iconName)}`
```

Code after:
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase, toPascalCase } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';

/**
 * Create a Lucide icon component
 * @param {string} iconName
 * @param {array} iconNode
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(toPascalCase(iconName))}`,
          `lucide-${toKebabCase(iconName)}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = toPascalCase(iconName);

  return Component;
};

export default createLucideIcon;
Repository: lucide-icons/lucide
File: packages/lucide-preact/src/createLucideIcon.ts (TypeScript)

Code before:
 * @param {string} componentName
 * @param {array} iconNode
 * @param {string} iconName
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (
  componentName: string,
  iconNode: IconNode,
  iconName: string,
): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(componentName)}`,
          `lucide-${iconName}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = `${componentName}`;

  return Component;
};

export default createLucideIcon;


Review comment (suggestion):
You would have to change quite a few more places tho.
```suggestion
  Component.displayName = toPascalCase(iconName);
```

Code after:
 * @param {string} iconName
 * @param {array} iconNode
 * @returns {FunctionComponent} LucideIcon
 */
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
  const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
    h(
      Icon,
      {
        ...props,
        iconNode,
        class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
          `lucide-${toKebabCase(toPascalCase(iconName))}`,
          `lucide-${toKebabCase(iconName)}`,
          classes,
        ),
      },
      children,
    );

  Component.displayName = toPascalCase(iconName);

  return Component;
};

export default createLucideIcon;
Repository: lucide-icons/lucide
File: packages/lucide-preact/tests/createLucideIcon.spec.tsx (TypeScript)

Code before:
import { describe, it, expect } from 'vitest';
import { createLucideIcon } from '../src/lucide-preact';
import { airVent } from './testIconNodes';
import { render } from '@testing-library/preact';

describe('Using createLucideIcon', () => {
  it('should create a component from an iconNode', () => {
    const AirVent = createLucideIcon('air-vent', airVent);

    const { container } = render(<AirVent />);

    expect(container.firstChild).toMatchSnapshot();
    expect(container.firstChild).toBeDefined();
  });
});


Review comment (suggestion):
I think the test here should stay the same.
```suggestion
    const AirVent = createLucideIcon('AirVent', airVent);
```

You can add a second test for `air-vent` and `layout-2`.

Code after:
import { describe, it, expect } from 'vitest';
import { createLucideIcon } from '../src/lucide-preact';
import { airVent } from './testIconNodes';
import { render } from '@testing-library/preact';

describe('Using createLucideIcon', () => {
  it('should create a component from an iconNode', () => {
    const AirVent = createLucideIcon('AirVent', airVent);

    const { container } = render(<AirVent />);

    expect(container.firstChild).toMatchSnapshot();
    expect(container.firstChild).toBeDefined();
  });

  it('should create a component from an iconNode with iconName', () => {
    const AirVent = createLucideIcon('air-vent', airVent);

    const { container } = render(<AirVent />);

    expect(container.firstChild).toMatchSnapshot();
    expect(container.firstChild).toBeDefined();
  });

  it('should include backwards compatible className', () => {
    const Layout2 = createLucideIcon('layout-2', airVent);

    const { container } = render(<Layout2 />);

    expect(container.firstChild).toMatchSnapshot();
    expect(container.firstChild).toBeDefined();
  });
});
Repository: lucide-icons/lucide
File: docs/.vitepress/theme/components/icons/SidebarIconCustomizer.vue (Vue)

Code before:
  props.rootEl?.value ?? documentRef.value,
  {
    initialValue: `${STYLE_DEFAULTS.strokeWidth}`
  }
)

const sizeCssVar = useCssVar(
  '--customize-size',
  props.rootEl?.value ?? documentRef.value,
  {
    initialValue: `${STYLE_DEFAULTS.size}`
  }
)

syncRef(color, colorCssVar, { direction: 'ltr' })
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
syncRef(size, sizeCssVar, { direction: 'ltr' })

function resetStyle () {
  color.value = STYLE_DEFAULTS.color
  strokeWidth.value = STYLE_DEFAULTS.strokeWidth
  size.value = STYLE_DEFAULTS.size
  absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
  nextTick(() => {
    
  });
}

watch(absoluteStrokeWidth, (enabled) => {
  const htmlEl = document.documentElement

  htmlEl.classList.toggle('absolute-stroke-width', enabled)
})

const customizingActive = computed(() => {
  return color.value !== STYLE_DEFAULTS.color
    || strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
    || size.value !== STYLE_DEFAULTS.size
})


</script>

<template>
  <div class="customizer-card" :class="{ customized: customizingActive }">
    <div class="card-header">
      <h2 class="card-title">
        Customizer
      </h2>
      <ResetButton @click="resetStyle"></ResetButton>
    </div>

Review comment (suggestion):
Shouldn't this be inside the nextTick function?
```suggestion
  nextTick(() => {
    absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
  });
```

Code after:
  props.rootEl?.value ?? documentRef.value,
  {
    initialValue: `${STYLE_DEFAULTS.strokeWidth}`
  }
)

const sizeCssVar = useCssVar(
  '--customize-size',
  props.rootEl?.value ?? documentRef.value,
  {
    initialValue: `${STYLE_DEFAULTS.size}`
  }
)

syncRef(color, colorCssVar, { direction: 'ltr' })
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
syncRef(size, sizeCssVar, { direction: 'ltr' })

function resetStyle () {
  color.value = STYLE_DEFAULTS.color
  strokeWidth.value = STYLE_DEFAULTS.strokeWidth
  size.value = STYLE_DEFAULTS.size
  absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
}

watch(absoluteStrokeWidth, (enabled) => {
  const htmlEl = document.documentElement

  htmlEl.classList.toggle('absolute-stroke-width', enabled)
})

const customizingActive = computed(() => {
  return color.value !== STYLE_DEFAULTS.color
    || strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
    || size.value !== STYLE_DEFAULTS.size
})


</script>

<template>
  <div class="customizer-card" :class="{ customized: customizingActive }">
    <div class="card-header">
      <h2 class="card-title">
        Customizer
      </h2>
      <ResetButton @click="resetStyle"></ResetButton>
    </div>
    <InputField
      id="icon-color"
      label="Color"
Repository: lucide-icons/lucide
File: docs/.vitepress/theme/components/home/HomeIconCustomizer.vue (Vue)

Code before:
  {
    initialValue: '2'
  }
)

const sizeCssVar = useCssVar(
  '--customize-size',
  iconContainer,
  {
    initialValue: '24'
  }
)

syncRef(color, colorCssVar)
syncRef(strokeWidth, strokeWidthCssVar)
syncRef(size, sizeCssVar)

function resetStyle () {
  color.value = 'currentColor'
  strokeWidth.value = 2
  size.value = 24
  absoluteStrokeWidth.value = false;
  nextTick(() => {
    
  });

}

watch(absoluteStrokeWidth, (enabled) => {
  iconContainer.value?.classList.toggle('absolute-stroke-width', enabled)
  
})
</script>

<template>
  <HomeContainer>
    <div class="card">
      <div class="card-column">
        <h2 class="title">
          Style as you please
          <ResetButton @click="resetStyle"></ResetButton>
        </h2>
        <p class="copy">
          Lucide has a lot of customization options to match the icons with your UI.
        </p>

        <div
          class="customizer"
          style="--color-picker-bg: var(--vp-input-switch-bg-color)"
        >
          <InputField

Review comment (suggestion):
Should this not be in the nextTick function?
```suggestion
  nextTick(() => {
    absoluteStrokeWidth.value = false;
  });

```

Code after:
  {
    initialValue: '2'
  }
)

const sizeCssVar = useCssVar(
  '--customize-size',
  iconContainer,
  {
    initialValue: '24'
  }
)

syncRef(color, colorCssVar)
syncRef(strokeWidth, strokeWidthCssVar)
syncRef(size, sizeCssVar)

function resetStyle () {
  color.value = 'currentColor'
  strokeWidth.value = 2
  size.value = 24
  absoluteStrokeWidth.value = false;
}

watch(absoluteStrokeWidth, (enabled) => {
  iconContainer.value?.classList.toggle('absolute-stroke-width', enabled)
  
})
</script>

<template>
  <HomeContainer>
    <div class="card">
      <div class="card-column">
        <h2 class="title">
          Style as you please
          <ResetButton @click="resetStyle"></ResetButton>
        </h2>
        <p class="copy">
          Lucide has a lot of customization options to match the icons with your UI.
        </p>

        <div
          class="customizer"
          style="--color-picker-bg: var(--vp-input-switch-bg-color)"
        >
          <InputField
            id="icon-color"
            label="Color"
            class="color-picker-field"
          >
Repository: lucide-icons/lucide
File: scripts/generateChangedIconsCommentMarkup.mjs (JavaScript)

Code before:
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const cohesionSquaresImageTags = getImageTagsByFiles(
  shuffleArray(iconsFilteredByName('square')).slice(0, changedFiles.length),
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const changeFiles1pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/1`,
).join('');

const changeFiles2pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const changeFiles3pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/3`,
).join('');

const changeFilesLowDPIImageTags18 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/18`,
).join(' ');

const changeFilesLowDPIImageTags24 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/24`,
).join(' ');

const changeFilesLowDPIImageTags32 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/32`,
).join(' ');

const changeFilesLowDPIImageTags48 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/48`,
).join(' ');

const changeFilesXRayImageTags = getImageTagsByFiles(
  changedFiles,
  (file) => {
    const iconName = path.basename(file, '.svg');

    return `${BASE_URL}/${iconName}`;
  },
  400,

Review comment (suggestion):
Is `16px` not a more conventional size to use than `18px`?
```suggestion
  () => `${BASE_URL}/dpi/16`,
```

Code after:
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const cohesionSquaresImageTags = getImageTagsByFiles(
  shuffleArray(iconsFilteredByName('square')).slice(0, changedFiles.length),
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const changeFiles1pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/1`,
).join('');

const changeFiles2pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/2`,
).join('');

const changeFiles3pxStrokeImageTags = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/stroke-width/3`,
).join('');

const changeFilesLowDPIImageTags16 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/16`,
).join(' ');

const changeFilesLowDPIImageTags24 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/24`,
).join(' ');

const changeFilesLowDPIImageTags32 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/32`,
).join(' ');

const changeFilesLowDPIImageTags48 = getImageTagsByFiles(
  changedFiles,
  () => `${BASE_URL}/dpi/48`,
).join(' ');

const changeFilesXRayImageTags = getImageTagsByFiles(
  changedFiles,
  (file) => {
    const iconName = path.basename(file, '.svg');

    return `${BASE_URL}/${iconName}`;
  },
  400,
Repository: lucide-icons/lucide
File: packages/lucide/src/lucide.ts (TypeScript)

Code before:
import replaceElement from './replaceElement';
import * as iconAndAliases from './iconsAndAliases';

/**
 * Replaces all elements with matching nameAttr with the defined icons
 * @param {{ icons?: object, nameAttr?: string, attrs?: object, context?: Element|Document }} options
 */
const createIcons = ({
  icons = {},
  nameAttr = 'data-lucide',
  attrs = {},
  context = document,
}: { icons?: object; nameAttr?: string; attrs?: object; context?: Element|Document } = {}) => {
  if (!Object.values(icons).length) {
    throw new Error(
      "Please provide an icons object.\nIf you want to use all the icons you can import it like:\n `import { createIcons, icons } from 'lucide';\nlucide.createIcons({icons});`",
    );
  }

  if (typeof context === 'undefined') {
    throw new Error('`createIcons()` only works in a browser environment.');
  }

  const elementsToReplace = context.querySelectorAll(`[${nameAttr}]`);
  Array.from(elementsToReplace).forEach((element) =>
    replaceElement(element, { nameAttr, icons, attrs }),
  );

  /** @todo: remove this block in v1.0 */
  if (nameAttr === 'data-lucide') {
    const deprecatedElements = context.querySelectorAll('[icon-name]');

Review comment (suggestion):
Maybe `root` fits better?
```suggestion
 * @param {{ icons?: object, nameAttr?: string, attrs?: object, root?: Element|Document }} options
```

Code after:
import replaceElement from './replaceElement';
import * as iconAndAliases from './iconsAndAliases';

/**
 * Replaces all elements with matching nameAttr with the defined icons
 * @param {{ icons?: object, nameAttr?: string, attrs?: object, root?: Element | Document }} options
 */
const createIcons = ({
  icons = {},
  nameAttr = 'data-lucide',
  attrs = {},
  root = document,
}: { icons?: object; nameAttr?: string; attrs?: object; root?: Element | Document } = {}) => {
  if (!Object.values(icons).length) {
    throw new Error(
      "Please provide an icons object.\nIf you want to use all the icons you can import it like:\n `import { createIcons, icons } from 'lucide';\nlucide.createIcons({icons});`",
    );
  }

  if (typeof root === 'undefined') {
    throw new Error('`createIcons()` only works in a browser environment.');
  }

  const elementsToReplace = root.querySelectorAll(`[${nameAttr}]`);
  Array.from(elementsToReplace).forEach((element) =>
    replaceElement(element, { nameAttr, icons, attrs }),
  );

  /** @todo: remove this block in v1.0 */
  if (nameAttr === 'data-lucide') {
    const deprecatedElements = root.querySelectorAll('[icon-name]');