main adfc697dba0b cached
49 files
46.3 MB
24.3k tokens
30 symbols
1 requests
Download .txt
Repository: Wondermarin/react-color-palette
Branch: main
Commit: adfc697dba0b
Files: 49
Total size: 46.3 MB

Directory structure:
gitextract_7m8wauft/

├── .eslintignore
├── .eslintrc
├── .github/
│   ├── COMMIT_CONVENTION.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── versioning.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .vscode/
│   └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── public/
│   └── demo.apng
├── src/
│   ├── components/
│   │   ├── alpha/
│   │   │   ├── alpha.component.tsx
│   │   │   └── index.ts
│   │   ├── color-picker/
│   │   │   ├── color-picker.component.tsx
│   │   │   └── index.ts
│   │   ├── fields/
│   │   │   ├── fields.component.tsx
│   │   │   └── index.ts
│   │   ├── hue/
│   │   │   ├── hue.component.tsx
│   │   │   └── index.ts
│   │   ├── interactive/
│   │   │   ├── index.ts
│   │   │   └── interactive.component.tsx
│   │   └── saturation/
│   │       ├── index.ts
│   │       └── saturation.component.tsx
│   ├── css/
│   │   └── rcp.css
│   ├── hooks/
│   │   ├── use-bounding-client-rect/
│   │   │   ├── index.ts
│   │   │   └── use-bounding-client-rect.hook.ts
│   │   └── use-color/
│   │       ├── index.ts
│   │       └── use-color.hook.ts
│   ├── rcp.ts
│   ├── services/
│   │   └── color/
│   │       ├── color.service.ts
│   │       └── index.ts
│   └── utils/
│       ├── clamp/
│       │   ├── clamp.util.ts
│       │   └── index.ts
│       ├── float/
│       │   ├── float.util.ts
│       │   └── index.ts
│       ├── format/
│       │   ├── format.util.ts
│       │   └── index.ts
│       ├── is-field-hide/
│       │   ├── index.ts
│       │   └── is-field-hide.util.ts
│       └── is-touch/
│           ├── index.ts
│           └── is-touch.util.ts
├── tsconfig.json
└── tsup.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintignore
================================================
# Dependencies
/node_modules

# Production
/dist


================================================
FILE: .eslintrc
================================================
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": ["./tsconfig.json"],
    "ecmaVersion": "latest",
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  },
  "env": {
    "es2022": true,
    "browser": true
  },
  "plugins": [
    "@typescript-eslint",
    "prettier",
    "react",
    "react-hooks"
  ],
  "rules": {
    // ESLint
    "array-callback-return": "error",
    "constructor-super": "off",
    "for-direction": "error",
    "getter-return": "off",
    "no-async-promise-executor": "error",
    "no-await-in-loop": "off",
    "no-class-assign": "error",
    "no-compare-neg-zero": "error",
    "no-cond-assign": ["error", "always"],
    "no-const-assign": "off",
    "no-constant-binary-expression": "error",
    "no-constant-condition": "error",
    "no-constructor-return": "error",
    "no-control-regex": "error",
    "no-debugger": "error",
    "no-dupe-args": "off",
    "no-dupe-class-members": "off",
    "no-dupe-else-if": "error",
    "no-dupe-keys": "off",
    "no-duplicate-case": "error",
    "no-duplicate-imports": "error",
    "no-empty-character-class": "error",
    "no-empty-pattern": "error",
    "no-ex-assign": "error",
    "no-fallthrough": "error",
    "no-func-assign": "off",
    "no-import-assign": "off",
    "no-inner-declarations": "error",
    "no-invalid-regexp": "error",
    "no-irregular-whitespace": "error",
    "no-loss-of-precision": "off",
    "no-misleading-character-class": "error",
    "no-new-native-nonconstructor": "error",
    "no-new-symbol": "off",
    "no-obj-calls": "off",
    "no-promise-executor-return": "error",
    "no-prototype-builtins": "error",
    "no-self-assign": "error",
    "no-self-compare": "error",
    "no-setter-return": "off",
    "no-sparse-arrays": "error",
    "no-template-curly-in-string": "error",
    "no-this-before-super": "off",
    "no-undef": "off",
    "no-unexpected-multiline": "off",
    "no-unmodified-loop-condition": "error",
    "no-unreachable": "off",
    "no-unreachable-loop": "error",
    "no-unsafe-finally": "error",
    "no-unsafe-negation": "off",
    "no-unsafe-optional-chaining": "error",
    "no-unused-private-class-members": "error",
    "no-unused-vars": "off",
    "no-use-before-define": "off",
    "no-useless-backreference": "error",
    "require-atomic-updates": "error",
    "use-isnan": "error",
    "valid-typeof": "off",
    "accessor-pairs": "off",
    "arrow-body-style": "off",
    "block-scoped-var": "error",
    "camelcase": "off",
    "capitalized-comments": "error",
    "class-methods-use-this": "off",
    "complexity": "off",
    "consistent-return": "off",
    "consistent-this": "off",
    "curly": "off",
    "default-case": "off",
    "default-case-last": "error",
    "default-param-last": "off",
    "dot-notation": "off",
    "eqeqeq": ["error", "smart"],
    "func-name-matching": "off",
    "func-names": ["error", "as-needed"],
    "grouped-accessor-pairs": ["error", "getBeforeSet"],
    "guard-for-in": "off",
    "id-denylist": "off",
    "id-length": "off",
    "id-match": "off",
    "init-declarations": "off",
    "logical-assignment-operators": ["error", "always"],
    "max-classes-per-file": "off",
    "max-depth": "off",
    "max-lines": "off",
    "max-lines-per-function": "off",
    "max-nested-callbacks": "off",
    "max-params": "off",
    "max-statements": "off",
    "multiline-comment-style": "error",
    "new-cap": ["error", { "capIsNew": false }],
    "no-alert": "error",
    "no-array-constructor": "off",
    "no-bitwise": "off",
    "no-caller": "error",
    "no-case-declarations": "error",
    "no-confusing-arrow": "off",
    "no-console": "off",
    "no-continue": "off",
    "no-delete-var": "error",
    "no-div-regex": "error",
    "no-else-return": "error",
    "no-empty": ["error", { "allowEmptyCatch": true }],
    "no-empty-function": "off",
    "no-empty-static-block": "error",
    "no-eq-null": "off",
    "no-eval": "error",
    "no-extend-native": "error",
    "no-extra-bind": "error",
    "no-extra-boolean-cast": "error",
    "no-extra-label": "error",
    "no-extra-semi": "off",
    "no-floating-decimal": "off",
    "no-global-assign": "error",
    "no-implicit-coercion": "off",
    "no-implicit-globals": "off",
    "no-implied-eval": "off",
    "no-inline-comments": "error",
    "no-invalid-this": "off",
    "no-iterator": "error",
    "no-label-var": "error",
    "no-labels": ["error", { "allowLoop": true }],
    "no-lone-blocks": "error",
    "no-lonely-if": "off",
    "no-loop-func": "off",
    "no-magic-numbers": "off",
    "no-mixed-operators": "off",
    "no-multi-assign": "error",
    "no-multi-str": "error",
    "no-negated-condition": "error",
    "no-nested-ternary": "off",
    "no-new": "error",
    "no-new-func": "error",
    "no-new-object": "error",
    "no-new-wrappers": "error",
    "no-nonoctal-decimal-escape": "error",
    "no-octal": "error",
    "no-octal-escape": "error",
    "no-param-reassign": "off",
    "no-plusplus": "error",
    "no-proto": "error",
    "no-redeclare": "off",
    "no-regex-spaces": "error",
    "no-restricted-exports": "off",
    "no-restricted-globals": "off",
    "no-restricted-imports": "off",
    "no-restricted-properties": "off",
    "no-restricted-syntax": "off",
    "no-return-assign": "error",
    "no-return-await": "off",
    "no-script-url": "error",
    "no-sequences": "error",
    "no-shadow": "off",
    "no-shadow-restricted-names": "error",
    "no-ternary": "off",
    "no-throw-literal": "off",
    "no-undef-init": "off",
    "no-undefined": "off",
    "no-underscore-dangle": "off",
    "no-unneeded-ternary": "error",
    "no-unused-expressions": "off",
    "no-unused-labels": "error",
    "no-useless-call": "error",
    "no-useless-catch": "off",
    "no-useless-computed-key": "error",
    "no-useless-concat": "error",
    "no-useless-constructor": "off",
    "no-useless-escape": "error",
    "no-useless-rename": "error",
    "no-useless-return": "off",
    "no-var": "off",
    "no-void": "error",
    "no-warning-comments": "off",
    "no-with": "error",
    "object-shorthand": "off",
    "one-var": "off",
    "one-var-declaration-per-line": "off",
    "operator-assignment": "error",
    "prefer-arrow-callback": "off",
    "prefer-const": "off",
    "prefer-destructuring": "error",
    "prefer-exponentiation-operator": "error",
    "prefer-named-capture-group": "off",
    "prefer-numeric-literals": "error",
    "prefer-object-has-own": "error",
    "prefer-object-spread": "error",
    "prefer-promise-reject-errors": "off",
    "prefer-regex-literals": "error",
    "prefer-rest-params": "off",
    "prefer-spread": "off",
    "prefer-template": "error",
    "quote-props": "off",
    "radix": "error",
    "require-await": "off",
    "require-unicode-regexp": "error",
    "require-yield": "error",
    "sort-imports": "off",
    "sort-keys": "off",
    "sort-vars": "off",
    "spaced-comment": "off",
    "strict": "off",
    "symbol-description": "error",
    "vars-on-top": "off",
    "yoda": "error",
    "array-bracket-newline": "off",
    "array-bracket-spacing": "off",
    "array-element-newline": "off",
    "arrow-parens": "off",
    "arrow-spacing": "off",
    "block-spacing": "off",
    "brace-style": "off",
    "comma-dangle": "off",
    "comma-spacing": "off",
    "comma-style": "off",
    "computed-property-spacing": "off",
    "dot-location": "off",
    "eol-last": "off",
    "func-call-spacing": "off",
    "function-call-argument-newline": "off",
    "function-paren-newline": "off",
    "generator-star-spacing": "off",
    "implicit-arrow-linebreak": "off",
    "indent": "off",
    "jsx-quotes": "off",
    "key-spacing": "off",
    "keyword-spacing": "off",
    "line-comment-position": "error",
    "linebreak-style": "off",
    "lines-around-comment": "off",
    "lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
    "max-len": "off",
    "max-statements-per-line": "off",
    "multiline-ternary": "off",
    "new-parens": "off",
    "newline-per-chained-call": "off",
    "no-extra-parens": "off",
    "no-mixed-spaces-and-tabs": "off",
    "no-multi-spaces": "off",
    "no-multiple-empty-lines": "off",
    "no-tabs": "off",
    "no-trailing-spaces": "off",
    "no-whitespace-before-property": "off",
    "nonblock-statement-body-position": "off",
    "object-curly-newline": "off",
    "object-curly-spacing": "off",
    "object-property-newline": "off",
    "operator-linebreak": "off",
    "padded-blocks": "off",
    "padding-line-between-statements": [
      "error",
      { "blankLine": "always", "prev": "*", "next": "return" },
      { "blankLine": "always", "prev": "*", "next": ["const", "let"] },
      { "blankLine": "always", "prev": ["const", "let"], "next": "*" },
      { "blankLine": "any", "prev": ["const", "let"], "next" : ["const", "let"] },
      { "blankLine": "always", "prev": "*", "next": "break" },
      { "blankLine": "always", "prev": "*", "next": "for" },
      { "blankLine": "always", "prev": "for", "next": "*" },
      { "blankLine": "always", "prev": "*", "next": "while" },
      { "blankLine": "always", "prev": "while", "next": "*" }
    ],
    "quotes": "off",
    "rest-spread-spacing": "off",
    "semi": "off",
    "semi-spacing": "off",
    "semi-style": "off",
    "space-before-blocks": "off",
    "space-before-function-paren": "off",
    "space-in-parens": "off",
    "space-infix-ops": "off",
    "space-unary-ops": "off",
    "switch-colon-spacing": "off",
    "template-curly-spacing": "off",
    "template-tag-spacing": "off",
    "unicode-bom": "off",
    "wrap-iife": "off",
    "wrap-regex": "off",
    "yield-star-spacing": "off",
    // TypeScript ESLint
    "@typescript-eslint/adjacent-overload-signatures": "error",
    "@typescript-eslint/array-type": ["error", { "default": "array", "readonly": "array" }],
    "@typescript-eslint/await-thenable": "error",
    "@typescript-eslint/ban-ts-comment": "error",
    "@typescript-eslint/ban-tslint-comment": "error",
    "@typescript-eslint/ban-types": "error",
    "@typescript-eslint/class-literal-property-style": "error",
    "@typescript-eslint/consistent-generic-constructors": "error",
    "@typescript-eslint/consistent-indexed-object-style": "error",
    "@typescript-eslint/consistent-type-assertions": "off",
    "@typescript-eslint/consistent-type-definitions": "error",
    "@typescript-eslint/consistent-type-exports": "off",
    "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports", "fixStyle": "inline-type-imports" }],
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/explicit-member-accessibility": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/member-delimiter-style": "off",
    "@typescript-eslint/member-ordering": "off",
    "@typescript-eslint/method-signature-style": ["error", "property"],
    "@typescript-eslint/naming-convention": [
      "error",
      { "selector": "interface", "format": ["StrictPascalCase"], "leadingUnderscore": "forbid", "trailingUnderscore": "forbid", "prefix": ["I"] },
      { "selector": "typeAlias", "format": ["StrictPascalCase"], "leadingUnderscore": "forbid", "trailingUnderscore": "forbid", "prefix": ["T"] },
      { "selector": "enum", "format": ["StrictPascalCase"], "leadingUnderscore": "forbid", "trailingUnderscore": "forbid", "prefix": ["E"] }
    ],
    "@typescript-eslint/no-base-to-string": "error",
    "@typescript-eslint/no-confusing-non-null-assertion": "error",
    "@typescript-eslint/no-confusing-void-expression": ["error", { "ignoreArrowShorthand": true }],
    "@typescript-eslint/no-duplicate-enum-values": "error",
    "@typescript-eslint/no-dynamic-delete": "error",
    "@typescript-eslint/no-empty-interface": "error",
    "@typescript-eslint/no-explicit-any": "off",
    "@typescript-eslint/no-extra-non-null-assertion": "error",
    "@typescript-eslint/no-extraneous-class": "off",
    "@typescript-eslint/no-floating-promises": "off",
    "@typescript-eslint/no-for-in-array": "error",
    "@typescript-eslint/no-inferrable-types": "error",
    "@typescript-eslint/no-invalid-void-type": "error",
    "@typescript-eslint/no-meaningless-void-operator": "error",
    "@typescript-eslint/no-misused-new": "error",
    "@typescript-eslint/no-misused-promises": "off",
    "@typescript-eslint/no-namespace": "error",
    "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
    "@typescript-eslint/no-non-null-asserted-optional-chain": "error",
    "@typescript-eslint/no-non-null-assertion": "error",
    "@typescript-eslint/no-redundant-type-constituents": "error",
    "@typescript-eslint/no-require-imports": "error",
    "@typescript-eslint/no-this-alias": "error",
    "@typescript-eslint/no-type-alias": "off",
    "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
    "@typescript-eslint/no-unnecessary-condition": "off",
    "@typescript-eslint/no-unnecessary-qualifier": "error",
    "@typescript-eslint/no-unnecessary-type-arguments": "error",
    "@typescript-eslint/no-unnecessary-type-assertion": "error",
    "@typescript-eslint/no-unnecessary-type-constraint": "error",
    "@typescript-eslint/no-unsafe-argument": "off",
    "@typescript-eslint/no-unsafe-assignment": "off",
    "@typescript-eslint/no-unsafe-call": "off",
    "@typescript-eslint/no-unsafe-declaration-merging": "error",
    "@typescript-eslint/no-unsafe-member-access": "off",
    "@typescript-eslint/no-unsafe-return": "off",
    "@typescript-eslint/no-useless-empty-export": "error",
    "@typescript-eslint/no-var-requires": "error",
    "@typescript-eslint/non-nullable-type-assertion-style": "off",
    "@typescript-eslint/parameter-properties": "off",
    "@typescript-eslint/prefer-as-const": "error",
    "@typescript-eslint/prefer-enum-initializers": "error",
    "@typescript-eslint/prefer-for-of": "off",
    "@typescript-eslint/prefer-function-type": "error",
    "@typescript-eslint/prefer-includes": "error",
    "@typescript-eslint/prefer-literal-enum-member": ["error", { "allowBitwiseExpressions": true }],
    "@typescript-eslint/prefer-namespace-keyword": "error",
    "@typescript-eslint/prefer-nullish-coalescing": "error",
    "@typescript-eslint/prefer-optional-chain": "error",
    "@typescript-eslint/prefer-readonly": "off",
    "@typescript-eslint/prefer-readonly-parameter-types": "off",
    "@typescript-eslint/prefer-reduce-type-parameter": "error",
    "@typescript-eslint/prefer-regexp-exec": "off",
    "@typescript-eslint/prefer-return-this-type": "error",
    "@typescript-eslint/prefer-string-starts-ends-with": "error",
    "@typescript-eslint/prefer-ts-expect-error": "error",
    "@typescript-eslint/promise-function-async": "error",
    "@typescript-eslint/require-array-sort-compare": "off",
    "@typescript-eslint/restrict-plus-operands": "error",
    "@typescript-eslint/restrict-template-expressions": "off",
    "@typescript-eslint/sort-type-constituents": "off",
    "@typescript-eslint/strict-boolean-expressions": "off",
    "@typescript-eslint/switch-exhaustiveness-check": "off",
    "@typescript-eslint/triple-slash-reference": "error",
    "@typescript-eslint/typedef": "off",
    "@typescript-eslint/unbound-method": "off",
    "@typescript-eslint/unified-signatures": "error",
    "@typescript-eslint/default-param-last": "error",
    "@typescript-eslint/dot-notation": "error",
    "@typescript-eslint/init-declarations": "off",
    "@typescript-eslint/no-array-constructor": "error",
    "@typescript-eslint/no-dupe-class-members": "error",
    "@typescript-eslint/no-empty-function": "error",
    "@typescript-eslint/no-extra-semi": "off",
    "@typescript-eslint/no-implied-eval": "error",
    "@typescript-eslint/no-invalid-this": "error",
    "@typescript-eslint/no-loop-func": "error",
    "@typescript-eslint/no-loss-of-precision": "error",
    "@typescript-eslint/no-magic-numbers": "off",
    "@typescript-eslint/no-redeclare": "error",
    "@typescript-eslint/no-restricted-imports": "off",
    "@typescript-eslint/no-shadow": "off",
    "@typescript-eslint/no-throw-literal": "off",
    "@typescript-eslint/no-unused-expressions": "error",
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/no-use-before-define": "error",
    "@typescript-eslint/no-useless-constructor": "error",
    "@typescript-eslint/require-await": "off",
    "@typescript-eslint/return-await": "error",
    "@typescript-eslint/brace-style": "off",
    "@typescript-eslint/comma-dangle": "off",
    "@typescript-eslint/comma-spacing": "off",
    "@typescript-eslint/func-call-spacing": "off",
    "@typescript-eslint/indent": "off",
    "@typescript-eslint/keyword-spacing": "off",
    "@typescript-eslint/lines-between-class-members": "off",
    "@typescript-eslint/no-extra-parens": "off",
    "@typescript-eslint/object-curly-spacing": "off",
    "@typescript-eslint/padding-line-between-statements": "off",
    "@typescript-eslint/quotes": "off",
    "@typescript-eslint/semi": "off",
    "@typescript-eslint/space-before-blocks": "off",
    "@typescript-eslint/space-before-function-paren": "off",
    "@typescript-eslint/space-infix-ops": "off",
    "@typescript-eslint/type-annotation-spacing": "off",
    // Prettier
    "prettier/prettier": "error",
    // React
    "react/boolean-prop-naming": "off",
    "react/button-has-type": "error",
    "react/default-props-match-prop-types": "off",
    "react/destructuring-assignment": ["error", "always"],
    "react/display-name": "off",
    "react/forbid-component-props": "off",
    "react/forbid-dom-props": "off",
    "react/forbid-elements": "off",
    "react/forbid-foreign-prop-types": "off",
    "react/forbid-prop-types": "off",
    "react/function-component-definition": ["error", { "namedComponents": "function-declaration", "unnamedComponents": "arrow-function" }],
    "react/hook-use-state": "error",
    "react/iframe-missing-sandbox": "off",
    "react/jsx-boolean-value": ["error", "never"],
    "react/jsx-child-element-spacing": "off",
    "react/jsx-closing-bracket-location": "off",
    "react/jsx-closing-tag-location": "off",
    "react/jsx-curly-brace-presence": "off",
    "react/jsx-curly-newline": "off",
    "react/jsx-curly-spacing": "off",
    "react/jsx-equals-spacing": "off",
    "react/jsx-filename-extension": "off",
    "react/jsx-first-prop-new-line": "off",
    "react/jsx-fragments": ["error", "element"],
    "react/jsx-handler-names": "error",
    "react/jsx-indent": "off",
    "react/jsx-indent-props": "off",
    "react/jsx-key": "error",
    "react/jsx-max-depth": "off",
    "react/jsx-max-props-per-line": "off",
    "react/jsx-newline": "off",
    "react/jsx-no-bind": "off",
    "react/jsx-no-comment-textnodes": "error",
    "react/jsx-no-constructed-context-values": "error",
    "react/jsx-no-duplicate-props": "error",
    "react/jsx-no-leaked-render": "error",
    "react/jsx-no-literals": "off",
    "react/jsx-no-script-url": "error",
    "react/jsx-no-target-blank": ["error", { "allowReferrer": true, "enforceDynamicLinks": "always", "links": false }],
    "react/jsx-no-undef": "error",
    "react/jsx-no-useless-fragment": "off",
    "react/jsx-one-expression-per-line": "off",
    "react/jsx-pascal-case": "error",
    "react/jsx-props-no-multi-spaces": "off",
    "react/jsx-props-no-spreading": "off",
    "react/jsx-sort-props": "off",
    "react/jsx-tag-spacing": "off",
    "react/jsx-uses-react": "off",
    "react/jsx-uses-vars": "error",
    "react/jsx-wrap-multilines": "off",
    "react/no-access-state-in-setstate": "error",
    "react/no-adjacent-inline-elements": "off",
    "react/no-array-index-key": "error",
    "react/no-arrow-function-lifecycle": "error",
    "react/no-children-prop": "error",
    "react/no-danger": "off",
    "react/no-danger-with-children": "error",
    "react/no-deprecated": "error",
    "react/no-did-mount-set-state": "error",
    "react/no-did-update-set-state": "error",
    "react/no-direct-mutation-state": "error",
    "react/no-find-dom-node": "error",
    "react/no-invalid-html-attribute": "error",
    "react/no-is-mounted": "error",
    "react/no-multi-comp": "error",
    "react/no-namespace": "error",
    "react/no-object-type-as-default-prop": "off",
    "react/no-redundant-should-component-update": "error",
    "react/no-render-return-value": "error",
    "react/no-set-state": "off",
    "react/no-string-refs": "error",
    "react/no-this-in-sfc": "error",
    "react/no-typos": "error",
    "react/no-unescaped-entities": "error",
    "react/no-unknown-property": "error",
    "react/no-unsafe": "off",
    "react/no-unstable-nested-components": "error",
    "react/no-unused-class-component-methods": "off",
    "react/no-unused-prop-types": "off",
    "react/no-unused-state": "off",
    "react/no-will-update-set-state": "error",
    "react/prefer-es6-class": "error",
    "react/prefer-exact-props": "off",
    "react/prefer-read-only-props": "off",
    "react/prefer-stateless-function": "off",
    "react/prop-types": "off",
    "react/react-in-jsx-scope": "off",
    "react/require-default-props": "off",
    "react/require-optimization": "off",
    "react/require-render-return": "error",
    "react/self-closing-comp": "error",
    "react/sort-comp": "off",
    "react/sort-default-props": "off",
    "react/sort-prop-types": "off",
    "react/state-in-constructor": "error",
    "react/static-property-placement": "off",
    "react/style-prop-object": "error",
    "react/void-dom-elements-no-children": "error",
    // React Hooks
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}


================================================
FILE: .github/COMMIT_CONVENTION.md
================================================
## Git Commit Message Convention

> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).

#### TL;DR:

Messages must be matched by the following regex:

```js
/^(feat|fix|chore|docs|style|refactor|perf|test|ci)(\(.+\))?: .{1,72}/;
```

### Full Message Format

A commit message consists of a **header**, **body** and **footer**. The header has a **type** and **subject**:

```
<type>: <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

### Type

If the prefix is `feat` or `fix` it will appear in the changelog. However, if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.

Other prefixes are up to your discretion. Suggested prefixes are `chore`, `docs`, `style`, `refactor`, `perf`, `test`, and `ci` for non-changelog related tasks.

### Subject

The subject contains a succinct description of the change:

- use the imperative, present tense: "change" not "changed" nor "changes"
- capitalize the first letter
- no dot (.) at the end

### Body

Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.

### Footer

The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing

## Setup

1. Fork & Clone the repository.
2. Run `pnpm install`.
3. Time to code!

## Test

1. Run `pnpm test`.

## Submit

1. [Submit a pull request](https://github.com/Wondermarin/react-color-palette/compare) (make sure you follow the [Conventional Commit Format](https://github.com/Wondermarin/react-color-palette/blob/master/.github/COMMIT_CONVENTION.md)).


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug Report
about: Report incorrect behavior of react-color-palette
title: ''
labels: 's: unverified, t: bug'
assignees: 'Wondermarin'
---

### My Environment

| Dependency                  | Version  |
| --------------------------- | -------- |
| Node.JS version             | vX.Y.Z   |
| react-color-palette version | vX.Y.Z   |

### Expected Behavior:

<!-- 
  A brief description of the expected behavior.
-->

### Actual Behavior:

<!--
  A brief description of the actual behavior.
-->

### Additional Context:

<!--
  Add any other context about the bug report here.
-->


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature Request
about: Suggest your idea for the development of the project
title: ''
labels: 't: enhancement'
assignees: 'Wondermarin'
---

### The Problem:

<!--
  A brief description of the problem and why its solution should be implemented in the project.
-->

### The Solution:

<!--
  A brief description of what you want to happen.
-->

### Additional Context:

<!--
  Add any other context about the feature request here.
-->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
  Before opening the request, make sure that all the listed conditions are met.

  - Code is up-to-date with the `main` branch.
  - `pnpm test (npm run test)` passes with this change.
  - The new commits follow conventions explained in [CONTRIBUTING.md](https://github.com/Wondermarin/react-color-palette/blob/master/.github/CONTRIBUTING.md)

  If your PR adds new functionality, you should also change the `demo`!
-->

### Description of Change

<!--
  A brief description of what you did and why the project needs it.
-->

<!--
  Thank you for helping the project, thanks to you it will live <3
-->


================================================
FILE: .github/workflows/versioning.yml
================================================
name: Versioning

on:
  push:
    branches:
      - main

permissions:
  contents: write
  pull-requests: write

jobs:
  release-please:
    name: Release Please
    runs-on: ubuntu-latest
    steps:
      - name: Release Please Action
        uses: google-github-actions/release-please-action@v3
        with:
          release-type: node
          package-name: release-please-action
          pull-request-title-pattern: 'chore: Release ${version}'


================================================
FILE: .gitignore
================================================
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# Dependencies
/node_modules

# Demo
/demo

# Production
/dist

# Env
.env

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output


================================================
FILE: .prettierignore
================================================
# Dependencies
/node_modules

# Production
/dist


================================================
FILE: .prettierrc
================================================
{
  "printWidth": 120,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": false,
  "quoteProps": "as-needed",
  "jsxSingleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "bracketSameLine": false,
  "arrowParens": "always",
  "requirePragma": false,
  "insertPragma": false,
  "proseWrap": "preserve",
  "htmlWhitespaceSensitivity": "css",
  "endOfLine": "auto",
  "embeddedLanguageFormatting": "auto",
  "singleAttributePerLine": false,
  "plugins": [
    "@ianvs/prettier-plugin-sort-imports"
  ],
  "importOrderParserPlugins": ["typescript", "classProperties", "jsx"],
  "importOrderTypeScriptVersion": "5.1.6",
  "importOrder": [
    "<BUILTIN_MODULES>",
    "",
    "<THIRD_PARTY_MODULES>",
    "",
    "^@/components$",
    "^@/components/(.*)$",
    "",
    "^@/hooks$",
    "^@/hooks/(.*)$",
    "",
    "^@/services$",
    "^@/services/(.*)$",
    "",
    "^@/utils$",
    "^@/utils/(.*)$",
    "",
    "^@/css/(.*)$",
    "",
    "^[.]"
  ]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "editor.tabSize": 2,
  "editor.quickSuggestions": {
    "strings": "on"
  },
  "[typescript][typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": "explicit"
    }
  },
  "files.exclude": {
    "**/.git": true,
    "**/.svn": true,
    "**/.hg": true,
    "**/CVS": true,
    "**/.DS_Store": true,
    "**/Thumbs.db": true,
    "**/node_modules": true
  },
  "typescript.preferences.includePackageJsonAutoImports": "on",
  "typescript.tsdk": "node_modules\\typescript\\lib"
}


================================================
FILE: CHANGELOG.md
================================================
# Changelog


## [7.3.1](https://github.com/Wondermarin/react-color-palette/compare/v7.3.0...v7.3.1) (2025-08-07)


### Bug Fixes

* Replace `undefined` to avoid unexpected output ([#88](https://github.com/Wondermarin/react-color-palette/issues/88)) ([269b7a4](https://github.com/Wondermarin/react-color-palette/commit/269b7a412b6aeac4d358c5f3da1c7110eb3153cc))

## [7.3.0](https://github.com/Wondermarin/react-color-palette/compare/v7.2.2...v7.3.0) (2024-09-13)


### Features

* Add disabled prop ([#82](https://github.com/Wondermarin/react-color-palette/issues/82)) ([6f025db](https://github.com/Wondermarin/react-color-palette/commit/6f025db6ee0172ddad42c31782578b4f52671f2a))

## [7.2.2](https://github.com/Wondermarin/react-color-palette/compare/v7.2.1...v7.2.2) (2024-07-30)


### Bug Fixes

* Replace `pointer` event with `mouse` event and `touch` event for better support across different environments ([671a74e](https://github.com/Wondermarin/react-color-palette/commit/671a74e036228ab4b97231979c666a4af1e03a76))

## [7.2.1](https://github.com/Wondermarin/react-color-palette/compare/v7.2.0...v7.2.1) (2024-07-12)


### Bug Fixes

* `useBoundingClientRect` wrong dimensions in modal ([#75](https://github.com/Wondermarin/react-color-palette/issues/75)) ([770820b](https://github.com/Wondermarin/react-color-palette/commit/770820b22db6b72bfebf925e0a53914edcd64d46))

## [7.2.0](https://github.com/Wondermarin/react-color-palette/compare/v7.1.1...v7.2.0) (2024-06-27)


### Features

* Add `onChangeComplete` event ([#73](https://github.com/Wondermarin/react-color-palette/issues/73)) ([2aa616e](https://github.com/Wondermarin/react-color-palette/commit/2aa616e1e82f18b499474a87e91ad287adc666b1))

## [7.1.1](https://github.com/Wondermarin/react-color-palette/compare/v7.1.0...v7.1.1) (2024-04-10)


### Bug Fixes

* Mark `.css` files as `sideEffect` ([#68](https://github.com/Wondermarin/react-color-palette/issues/68)) ([1acc892](https://github.com/Wondermarin/react-color-palette/commit/1acc892302f46bc3afe02adf4c34e88df6d3be6f))

## [7.1.0](https://github.com/Wondermarin/react-color-palette/compare/v7.0.4...v7.1.0) (2023-09-07)


### Features

* Add "individual visibility control for color inputs" support ([#62](https://github.com/Wondermarin/react-color-palette/issues/62)) ([157dbb1](https://github.com/Wondermarin/react-color-palette/commit/157dbb1b162d53dd0acfafebb7e238f969f1e894))

## [7.0.4](https://github.com/Wondermarin/react-color-palette/compare/v7.0.3...v7.0.4) (2023-08-12)


### Bug Fixes

* Add reposition support ([#60](https://github.com/Wondermarin/react-color-palette/issues/60)) ([8342bf3](https://github.com/Wondermarin/react-color-palette/commit/8342bf345215ed621f15936069ecb599a5f43d12))

## [7.0.3](https://github.com/Wondermarin/react-color-palette/compare/v7.0.2...v7.0.3) (2023-08-09)


### Bug Fixes

* Add resize support ([003f052](https://github.com/Wondermarin/react-color-palette/commit/003f05284a7a860d8e2a330c5c450df93b9dc441))

## [7.0.2](https://github.com/Wondermarin/react-color-palette/compare/v7.0.1...v7.0.2) (2023-08-04)


### Bug Fixes

* Add `touch-action: none` to prevent `pointercancel` ([be5bfd0](https://github.com/Wondermarin/react-color-palette/commit/be5bfd039a88a25a302438cd9557969ad4225209))

## [7.0.1](https://github.com/Wondermarin/react-color-palette/compare/v7.0.0...v7.0.1) (2023-08-04)


### Bug Fixes

* Add direct path to stylesheet ([#53](https://github.com/Wondermarin/react-color-palette/issues/53)) ([762f465](https://github.com/Wondermarin/react-color-palette/commit/762f4651ebc3bef4f4507c8fbc0ca59fe3ddbee2))

## [7.0.0](https://github.com/Wondermarin/react-color-palette/compare/v6.2.0...v7.0.0) (2023-08-03)


### ⚠ BREAKING CHANGES

* Remove `model` arg in `useColor()`
* Remove `width` prop in `<ColorPicker />` component
* Remove `onChangeComplete` prop in `<ColorPicker />` component
* Replace `hideHEX`, `hideRGB` and `hideHSV` to `hideInput` prop in `<ColorPicker />` component
* Replace `alpha` to `hideAlpha` prop in `<ColorPicker />` component
* Remove `dark` prop in `<ColorPicker />` component
* Replace `toColor()` to `ColorService`
* Rename `Color`, `ColorRGB` and `ColorHSV` types in `IColor`, `IColorRgb` and `IColorHsv`
* Replace `react-color-palette/lib/css/styles.css` to `react-color-palette/css`

### Features

* Add CSS-like values support in `useColor()` ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Add responsive support ([#22](https://github.com/Wondermarin/react-color-palette/issues/22)) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Add RSC support (Next.js 13 App Router) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Add touch support ([#20](https://github.com/Wondermarin/react-color-palette/issues/20)) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Enable alpha-channel by default ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Export `<Saturation />`, `<Hue />` and `<Alpha />` components ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Implement update state from props in `useColor()` ([#38](https://github.com/Wondermarin/react-color-palette/issues/38)) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Remove `dark` prop in `<ColorPicker />` component ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Remove `model` arg in `useColor()` ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Remove `onChangeComplete` prop in `<ColorPicker />` component ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Remove `width` prop in `<ColorPicker />` component ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Rename `Color`, `ColorRGB` and `ColorHSV` types in `IColor`, `IColorRgb` and `IColorHsv` ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Replace `alpha` to `hideAlpha` prop in `<ColorPicker />` component ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Replace `hideHEX`, `hideRGB` and `hideHSV` to `hideInput` prop in `<ColorPicker />` component ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Replace `react-color-palette/lib/css/styles.css` to `react-color-palette/css` ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Replace `toColor()` to `ColorService` ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))


### Bug Fixes

* Add `types` in `exports` field ([#51](https://github.com/Wondermarin/react-color-palette/issues/51)) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))
* Add check for `NaN` alpha value in `hex2rgb()` ([#33](https://github.com/Wondermarin/react-color-palette/issues/33)) ([91d0ca6](https://github.com/Wondermarin/react-color-palette/commit/91d0ca63891272ef4153f8201a0dd81ef524d5d0))

## [6.2.0](https://github.com/Wondermarin/react-color-palette/compare/v6.1.0...v6.2.0) (2021-11-11)


### Features

* `onChangeComplete` callback. ([bd83997](https://github.com/Wondermarin/react-color-palette/commit/bd83997da178d79d9292264cf513f20b696a665e)), closes [#18](https://github.com/Wondermarin/react-color-palette/issues/18)


### Bug Fixes

* Infinite `useColor` re-renders ([#26](https://github.com/Wondermarin/react-color-palette/issues/26)) ([3dcc66b](https://github.com/Wondermarin/react-color-palette/commit/3dcc66bbe38615dea273e147bf379aa3f982f493))
* Sliders width ([#24](https://github.com/Wondermarin/react-color-palette/issues/24)) ([6c8fa99](https://github.com/Wondermarin/react-color-palette/commit/6c8fa999742e474a1d2f67877e8045d399a9f280))

## [6.1.0](https://github.com/Wondermarin/react-color-palette/compare/v6.0.0...v6.1.0) (2021-07-22)


### Features

* Add `alpha channel` ([#15](https://github.com/Wondermarin/react-color-palette/issues/15)) ([aa7c289](https://github.com/Wondermarin/react-color-palette/commit/aa7c289b971e02fe0c0740904202f80d39fd9bbd))

## [6.0.0](https://github.com/Wondermarin/react-color-palette/compare/v5.0.0...v6.0.0) (2021-06-26)


### ⚠ BREAKING CHANGES

* `hideHSB` -> `hideHSV` (#14)

### Bug Fixes

* `hideHSB` -> `hideHSV` ([#14](https://github.com/Wondermarin/react-color-palette/issues/14)) ([b6d8e8b](https://github.com/Wondermarin/react-color-palette/commit/b6d8e8b95f31bbd8269d5a4e9aa9f8fe0be336e1))
* Hue bar size ([#12](https://github.com/Wondermarin/react-color-palette/issues/12)) ([95084b1](https://github.com/Wondermarin/react-color-palette/commit/95084b148e37fc28cdaee7abc143161a0b7b9f6e))

## [5.0.0](https://github.com/Wondermarin/react-color-palette/compare/v4.1.0...v5.0.0) (2021-04-28)


### ⚠ BREAKING CHANGES

* Remove `ColorPicker` default export
* Rename `HSB` -> `HSV`

### Features

* Add `ESModule` support. ([e534a6d](https://github.com/Wondermarin/react-color-palette/commit/e534a6dacddb9b71a8a429cb8538d2a83ccb311c))
* Remove `ColorPicker` default export ([f51c337](https://github.com/Wondermarin/react-color-palette/commit/f51c33767f85165a7dc5506b9571028040bac192))
* Rename `HSB` -> `HSV` ([bf741e3](https://github.com/Wondermarin/react-color-palette/commit/bf741e3071115cadb738db6e26179d63192e6cd3))


### Bug Fixes

* Add `React 16` support ([#9](https://github.com/Wondermarin/react-color-palette/issues/9)) ([cd4c729](https://github.com/Wondermarin/react-color-palette/commit/cd4c72988e4e20e03c2cf2f31436d76385da6305))

## [4.1.0](https://github.com/Wondermarin/react-color-palette/compare/v4.0.0...v4.1.0) (2021-04-16)


### Features

* Now `Saturation` is a `div` ([5dd224a](https://github.com/Wondermarin/react-color-palette/commit/5dd224a78373b20c99a799e737824d7063b16991))

## [4.0.0](https://github.com/Wondermarin/react-color-palette/compare/v3.1.0...v4.0.0) (2021-04-03)


### Bug Fixes

* CSS Import ([#7](https://github.com/Wondermarin/react-color-palette/issues/7)) ([30ddf8e](https://github.com/Wondermarin/react-color-palette/commit/30ddf8e30ed4e84dacf2f1728eaae0fdafeecfd5))

## [3.1.0](https://github.com/Wondermarin/react-color-palette/compare/v3.0.0...v3.1.0) (2021-02-25)


### Features

* Hide color fields ([#4](https://github.com/Wondermarin/react-color-palette/issues/4)) ([3af0074](https://github.com/Wondermarin/react-color-palette/commit/3af0074d4fe3357d9ef6d3ceee03b42ba8e57a57))

### Bug Fixes

* Fixed the display of fields ([4ddc02f](https://github.com/Wondermarin/react-color-palette/commit/4ddc02ff2a30ae9689ff72effee7fd827de9db00))

## 3.0.0 (2021-01-08)


### Whats new?

* Rewritten and improved code. ([a58ea61](https://github.com/Wondermarin/react-color-palette/commit/a58ea610b2a9fdb23945f28a07deb3978bce57df))


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Wondermarin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<div align="center">
  <p>
    <img alt="react-color-palette" src="https://github.com/Wondermarin/react-color-palette/raw/main/public/logo.png" width="128px" height="128px" />
  </p>
  <p>🎨 Lightweight &lt;ColorPicker /&gt; component for <a href="https://github.com/facebook/react">React</a>.</p>
  <p>
    <a href="https://www.npmjs.com/package/react-color-palette">
      <img alt="npm" src="https://badgen.net/npm/v/react-color-palette?color=561ecb" />
    </a>
    <a href="https://www.npmjs.com/package/react-color-palette">
      <img alt="downloads" src="https://badgen.net/npm/dw/react-color-palette?color=561ecb" />
    </a>
    <a href="https://bundlephobia.com/result?p=react-color-palette">
      <img alt="size" src="https://badgen.net/bundlephobia/minzip/react-color-palette@latest?color=561ecb" />
    </a>
  </p>
  <p>
    <img src="https://github.com/Wondermarin/react-color-palette/raw/main/public/demo.apng" />
  </p>
</div>

## Installation

### yarn
```sh
yarn add react-color-palette
```

### npm
```sh
npm install react-color-palette
```

## Usage

```tsx
import { ColorPicker, useColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("#561ecb");

  return <ColorPicker color={color} onChange={setColor} />;
}
```

## Examples

### Usage <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb">`rgb()`</a> in <a href="#usecolor">`useColor()`</a>
```tsx
import { ColorPicker, useColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("rgb(86 30 203)");

  return <ColorPicker color={color} onChange={setColor} />;
}
```

### Usage <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/named-color">`<named-color>`</a> in <a href="#usecolor">`useColor()`</a>
```tsx
import { ColorPicker, useColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("cyan");

  return <ColorPicker color={color} onChange={setColor} />;
}
```

### Custom Layout
```tsx
import { Saturation, Hue, useColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("hsl(120 100% 50% / .5)");

  return (
    <div className="custom-layout">
      <Saturation height={300} color={color} onChange={setColor} />
      <Hue color={color} onChange={setColor} />
    </div>
  );
}
```

### HEX input only
```tsx
import { ColorPicker, useColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("#123123");

  return <ColorPicker hideInput={["rgb", "hsv"]} color={color} onChange={setColor} />
}
```

### onChangeComplete optional callback
```tsx
import { ColorPicker, useColor, type IColor } from "react-color-palette";
import "react-color-palette/css";

export function App() {
  const [color, setColor] = useColor("#123123");

  const onChangeComplete = (color: IColor) => localStorage.setItem("color", color.hex);

  return <ColorPicker hideInput={["rgb", "hsv"]} color={color} onChange={setColor} onChangeComplete={onChangeComplete} />
}
```

## API

### `<ColorPicker />`
<p>The main component, which includes: <a href="#saturation">&lt;Saturation /&gt;</a>, <a href="#hue">&lt;Hue /&gt;</a>, <a href="#alpha">&lt;Alpha /&gt;</a> and &lt;Fields /&gt; components for instant use.<br />If you need a custom layout, then you can use <a href="#saturation">&lt;Saturation /&gt;</a>, <a href="#hue">&lt;Hue /&gt;</a> and <a href="#alpha">&lt;Alpha /&gt;</a> components separately, which are also exported from the library.</p>

<table>
  <tr>
    <th>Prop</th>
    <th>Type</th>
    <th>Default</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>height</td>
    <td>number</td>
    <td>200</td>
    <td>Height of the <a href="#saturation">Saturation</a> component in pixels.</td>
  </tr>
  <tr>
    <td>hideAlpha</td>
    <td>boolean</td>
    <td>false</td>
    <td>Hides the <a href="#alpha">Alpha</a> component.</td>
  </tr>
  <tr>
    <td>hideInput</td>
    <td>(keyof <a href="#icolor">IColor</a>)[] | boolean</td>
    <td>false</td>
    <td>If boolean: hides all inputs if true or displays all inputs if false. If array: hides all inputs listed in the array.</td>
  </tr>
  <tr>
    <td>color</td>
    <td><a href="#icolor">IColor</a></td>
    <td></td>
    <td>Current <a href="#icolor">color</a>.</td>
  </tr>
  <tr>
    <td>disabled</td>
    <td>boolean</td>
    <td>false</td>
    <td>Disables interactivity.</td>
  </tr>
  <tr>
    <td>onChange</td>
    <td>Function</td>
    <td></td>
    <td>Сallback function will be fired when <a href="#icolor">color</a> changes.</td>
  </tr>
  <tr>
    <td>onChangeComplete</td>
    <td>Function</td>
    <td></td>
    <td>Callback function will be fired when the interaction is complete with the color picker.</td>
  </tr>
</table>

### `<Saturation />`

<table>
  <tr>
    <th>Prop</th>
    <th>Type</th>
    <th>Default</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>height</td>
    <td>number</td>
    <td></td>
    <td>Height of the saturation element in pixels.</td>
  </tr>
  <tr>
    <td>color</td>
    <td><a href="#icolor">IColor</a></td>
    <td></td>
    <td>Current <a href="#icolor">color</a>.</td>
  </tr>
  <tr>
    <td>disabled</td>
    <td>boolean</td>
    <td>false</td>
    <td>Disables interactivity.</td>
  </tr>
  <tr>
    <td>onChange</td>
    <td>Function</td>
    <td></td>
    <td>Сallback function will be fired when <a href="#icolor">color</a> changes.</td>
  </tr>
  <tr>
    <td>onChangeComplete</td>
    <td>Function</td>
    <td></td>
    <td>Callback function will be fired when the interaction is complete with the saturation picker.</td>
  </tr>
</table>

### `<Hue />`

<table>
  <tr>
    <th>Prop</th>
    <th>Type</th>
    <th>Default</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>color</td>
    <td><a href="#icolor">IColor</a></td>
    <td></td>
    <td>Current <a href="#icolor">color</a>.</td>
  </tr>
  <tr>
    <td>disabled</td>
    <td>boolean</td>
    <td>false</td>
    <td>Disables interactivity.</td>
  </tr>
  <tr>
    <td>onChange</td>
    <td>Function</td>
    <td></td>
    <td>Сallback function will be fired when <a href="#icolor">color</a> changes.</td>
  </tr>
  <tr>
    <td>onChangeComplete</td>
    <td>Function</td>
    <td></td>
    <td>Callback function will be fired when the interaction is complete with the hue picker.</td>
  </tr>
</table>

### `<Alpha />`

<table>
  <tr>
    <th>Prop</th>
    <th>Type</th>
    <th>Default</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>color</td>
    <td><a href="#icolor">IColor</a></td>
    <td></td>
    <td>Current <a href="#icolor">color</a>.</td>
  </tr>
  <tr>
    <td>disabled</td>
    <td>boolean</td>
    <td>false</td>
    <td>Disables interactivity.</td>
  </tr>
  <tr>
    <td>onChange</td>
    <td>Function</td>
    <td></td>
    <td>Сallback function will be fired when <a href="#icolor">color</a> changes.</td>
  </tr>
  <tr>
    <td>onChangeComplete</td>
    <td>Function</td>
    <td></td>
    <td>Callback function will be fired when the interaction is complete with the alpha picker.</td>
  </tr>
</table>

### `useColor()`

<table>
  <tr>
    <th>Arg</th>
    <th>Type</th>
    <th>Default</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>initialColor</td>
    <td><a href="#tcolor">TColor</a></td>
    <td></td>
    <td>Initial <a href="#tcolor">сolor</a>.</td>
  </tr>
</table>

### `TColor`
<p>Value can be specified using one of the methods listed below:</p>

- <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/named-color">`<named-color>`</a>
- <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color">`<hex-color>`</a>
- <a href="https://en.wikipedia.org/wiki/SRGB">sRGB</a> color space: <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl">`hsl()`</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb">`hwb()`</a> or <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb">`rgb()`</a>

### `IColor`

<table>
  <tr>
    <th>Field</th>
    <th>Type</th>
  </tr>
  <tr>
    <td>hex</td>
    <td>string</td>
  </tr>
  <tr>
    <td>rgb</td>
    <td><a href="#icolorrgb">IColorRgb</a></td>
  </tr>
  <tr>
    <td>hsv</td>
    <td><a href="#icolorhsv">IColorHsv</a></td>
  </tr>
</table>

### `IColorRgb`

<table>
  <tr>
    <th>Field</th>
    <th>Type</th>
  </tr>
  <tr>
    <td>r</td>
    <td>number</td>
  </tr>
  <tr>
    <td>g</td>
    <td>number</td>
  </tr>
  <tr>
    <td>b</td>
    <td>number</td>
  </tr>
    <tr>
    <td>a</td>
    <td>number</td>
  </tr>
</table>

### `IColorHsv`

<table>
  <tr>
    <th>Field</th>
    <th>Type</th>
  </tr>
  <tr>
    <td>h</td>
    <td>number</td>
  </tr>
  <tr>
    <td>s</td>
    <td>number</td>
  </tr>
  <tr>
    <td>v</td>
    <td>number</td>
  </tr>
    <tr>
    <td>a</td>
    <td>number</td>
  </tr>
</table>

## License

<p>Code released under the <a href="https://github.com/Wondermarin/react-color-palette/blob/master/LICENSE">MIT</a> license.</p>


================================================
FILE: package.json
================================================
{
  "name": "react-color-palette",
  "version": "7.3.1",
  "description": "🎨 Lightweight Color Picker component for React.",
  "author": "Wondermarin",
  "type": "commonjs",
  "main": "dist/rcp.js",
  "module": "dist/rcp.mjs",
  "types": "dist/rcp.d.ts",
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "import": {
        "types": "./dist/rcp.d.mts",
        "default": "./dist/rcp.mjs"
      },
      "require": {
        "types": "./dist/rcp.d.ts",
        "default": "./dist/rcp.js"
      }
    },
    "./css": "./dist/css/rcp.css",
    "./dist/css/rcp.css": "./dist/css/rcp.css"
  },
  "homepage": "https://github.com/Wondermarin/react-color-palette#readme",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Wondermarin/react-color-palette.git"
  },
  "bugs": {
    "url": "https://github.com/Wondermarin/react-color-palette/issues"
  },
  "license": "MIT",
  "sideEffects": [
    "*.css"
  ],
  "private": false,
  "keywords": [
    "react",
    "react-component",
    "color-palette",
    "color palette",
    "color-picker",
    "color picker",
    "color",
    "picker"
  ],
  "files": [
    "dist"
  ],
  "engines": {
    "node": ">=10"
  },
  "scripts": {
    "test:lint": "eslint src/**/*.{ts,tsx}",
    "test:types": "tsc",
    "test": "pnpm test:lint && pnpm test:types",
    "prebuild": "pnpm test",
    "build": "tsup"
  },
  "peerDependencies": {
    "react": ">=16.8"
  },
  "devDependencies": {
    "@ianvs/prettier-plugin-sort-imports": "^4.1.0",
    "@types/node": "^20.4.4",
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.1.0",
    "@typescript-eslint/parser": "^6.1.0",
    "eslint": "^8.45.0",
    "eslint-plugin-prettier": "^5.0.0",
    "eslint-plugin-react": "^7.33.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "prettier": "^3.0.0",
    "tsup": "^7.2.0",
    "typescript": "^5.1.6"
  }
}


================================================
FILE: public/demo.apng
================================================
[File too large to display: 46.2 MB]

================================================
FILE: src/components/alpha/alpha.component.tsx
================================================
import React, { memo, useCallback, useMemo } from "react";

import { useBoundingClientRect } from "@/hooks/use-bounding-client-rect";

import { ColorService, type IColor } from "@/services/color";

import { Interactive } from "../interactive";

interface IAlphaProps {
  readonly color: IColor;
  readonly disabled?: boolean;
  readonly onChange: (color: IColor) => void;
  readonly onChangeComplete?: (color: IColor) => void;
}

export const Alpha = memo(({ color, disabled, onChange, onChangeComplete }: IAlphaProps) => {
  const [alphaRef, { width }] = useBoundingClientRect<HTMLDivElement>();

  const position = useMemo(() => {
    const x = color.hsv.a * width;

    return { x };
  }, [color.hsv.a, width]);

  const updateColor = useCallback(
    (final: boolean, x: number) => {
      const nextColor = ColorService.convert("hsv", {
        ...color.hsv,
        a: x / width,
      });

      onChange(nextColor);
      if (final) onChangeComplete?.(nextColor);
    },
    [color.hsv, width, onChange, onChangeComplete]
  );

  const rgb = useMemo(() => [color.rgb.r, color.rgb.g, color.rgb.b].join(" "), [color.rgb.r, color.rgb.g, color.rgb.b]);
  const rgba = useMemo(() => [rgb, color.rgb.a].join(" / "), [rgb, color.rgb.a]);

  return (
    <Interactive disabled={disabled} onCoordinateChange={updateColor}>
      <div
        ref={alphaRef}
        style={{
          background: `linear-gradient(to right, rgb(${rgb} / 0), rgb(${rgb} / 1)) top left / auto auto,
                      conic-gradient(#666 0.25turn, #999 0.25turn 0.5turn, #666 0.5turn 0.75turn, #999 0.75turn) top left / 12px 12px
                      repeat`,
        }}
        className="rcp-alpha"
      >
        <div
          style={{
            left: position.x,
            background: `linear-gradient(to right, rgb(${rgba}), rgb(${rgba})) top left / auto auto,
                        conic-gradient(#666 0.25turn, #999 0.25turn 0.5turn, #666 0.5turn 0.75turn, #999 0.75turn) ${
                          -position.x - 4
                        }px 2px / 12px 12px
                        repeat`,
          }}
          className="rcp-alpha-cursor"
        />
      </div>
    </Interactive>
  );
});


================================================
FILE: src/components/alpha/index.ts
================================================
export * from "./alpha.component";


================================================
FILE: src/components/color-picker/color-picker.component.tsx
================================================
import React, { memo } from "react";

import { type IColor } from "@/services/color";

import { isFieldHide } from "@/utils/is-field-hide";

import { Alpha } from "../alpha";
import { Fields } from "../fields";
import { Hue } from "../hue";
import { Saturation } from "../saturation";

interface IColorPickerProps {
  readonly height?: number;
  readonly hideAlpha?: boolean;
  readonly hideInput?: (keyof IColor)[] | boolean;
  readonly color: IColor;
  readonly disabled?: boolean;
  readonly onChange: (color: IColor) => void;
  readonly onChangeComplete?: (color: IColor) => void;
}

export const ColorPicker = memo(
  ({
    height = 200,
    hideAlpha = false,
    hideInput = false,
    color,
    disabled = false,
    onChange,
    onChangeComplete,
  }: IColorPickerProps) => (
    <div className="rcp-root rcp">
      <Saturation
        height={height}
        color={color}
        disabled={disabled}
        onChange={onChange}
        onChangeComplete={onChangeComplete}
      />
      <div className="rcp-body">
        <section className="rcp-section">
          <Hue color={color} disabled={disabled} onChange={onChange} onChangeComplete={onChangeComplete} />
          {!hideAlpha && (
            <Alpha color={color} disabled={disabled} onChange={onChange} onChangeComplete={onChangeComplete} />
          )}
        </section>
        {(!isFieldHide(hideInput, "hex") || !isFieldHide(hideInput, "rgb") || !isFieldHide(hideInput, "hsv")) && (
          <section className="rcp-section">
            <Fields
              hideInput={hideInput}
              color={color}
              disabled={disabled}
              onChange={onChange}
              onChangeComplete={onChangeComplete}
            />
          </section>
        )}
      </div>
    </div>
  )
);


================================================
FILE: src/components/color-picker/index.ts
================================================
export * from "./color-picker.component";


================================================
FILE: src/components/fields/fields.component.tsx
================================================
import React, { memo, useCallback, useEffect, useState } from "react";

import { ColorService, type IColor } from "@/services/color";

import { formatHsv, formatRgb } from "@/utils/format";
import { isFieldHide } from "@/utils/is-field-hide";

interface IFieldsProps {
  readonly hideInput: (keyof IColor)[] | boolean;
  readonly color: IColor;
  readonly disabled?: boolean;
  readonly onChange: (color: IColor) => void;
  readonly onChangeComplete?: (color: IColor) => void;
}

export const Fields = memo(({ hideInput, color, disabled, onChange, onChangeComplete }: IFieldsProps) => {
  const [fields, setFields] = useState({
    hex: {
      value: color.hex,
      inputted: false,
    },
    rgb: {
      value: formatRgb(color.rgb),
      inputted: false,
    },
    hsv: {
      value: formatHsv(color.hsv),
      inputted: false,
    },
  });

  useEffect(() => {
    if (!fields.hex.inputted) {
      setFields((fields) => ({ ...fields, hex: { ...fields.hex, value: color.hex } }));
    }
  }, [fields.hex.inputted, color.hex]);

  useEffect(() => {
    if (!fields.rgb.inputted) {
      setFields((fields) => ({ ...fields, rgb: { ...fields.rgb, value: formatRgb(color.rgb) } }));
    }
  }, [fields.rgb.inputted, color.rgb]);

  useEffect(() => {
    if (!fields.hsv.inputted) {
      setFields((fields) => ({ ...fields, hsv: { ...fields.hsv, value: formatHsv(color.hsv) } }));
    }
  }, [fields.hsv.inputted, color.hsv]);

  const onInputChange = useCallback(
    <T extends keyof typeof fields>(field: T) =>
      (event: React.ChangeEvent<HTMLInputElement>) => {
        const { value } = event.target;

        setFields((fields) => ({ ...fields, [field]: { ...fields[field], value } }));

        if (field === "hsv") onChange(ColorService.convert("hsv", ColorService.toHsv(value)));
        else if (field === "rgb") onChange(ColorService.convert("rgb", ColorService.toRgb(value)));
        else onChange(ColorService.convert("hex", value));
      },
    [onChange]
  );

  const onInputFocus = useCallback(
    <T extends keyof typeof fields>(field: T) =>
      () => {
        setFields((fields) => ({ ...fields, [field]: { ...fields[field], inputted: true } }));
      },
    []
  );

  const onInputBlur = useCallback(
    <T extends keyof typeof fields>(field: T) =>
      (event: React.ChangeEvent<HTMLInputElement>) => {
        const { value } = event.target;

        setFields((fields) => ({ ...fields, [field]: { ...fields[field], inputted: false } }));

        if (field === "hsv") onChangeComplete?.(ColorService.convert("hsv", ColorService.toHsv(value)));
        else if (field === "rgb") onChangeComplete?.(ColorService.convert("rgb", ColorService.toRgb(value)));
        else onChangeComplete?.(ColorService.convert("hex", value));
      },
    [onChangeComplete]
  );

  return (
    <div className="rcp-fields">
      {!isFieldHide(hideInput, "hex") && (
        <div className="rcp-fields-floor">
          <div className="rcp-field">
            <input
              id="hex"
              className="rcp-field-input"
              readOnly={disabled}
              value={fields.hex.value}
              onChange={onInputChange("hex")}
              onFocus={onInputFocus("hex")}
              onBlur={onInputBlur("hex")}
            />
            <label htmlFor="hex" className="rcp-field-label">
              HEX
            </label>
          </div>
        </div>
      )}
      {(!isFieldHide(hideInput, "rgb") || !isFieldHide(hideInput, "hsv")) && (
        <div className="rcp-fields-floor">
          {!isFieldHide(hideInput, "rgb") && (
            <div className="rcp-field">
              <input
                id="rgb"
                className="rcp-field-input"
                readOnly={disabled}
                value={fields.rgb.value}
                onChange={onInputChange("rgb")}
                onFocus={onInputFocus("rgb")}
                onBlur={onInputBlur("rgb")}
              />
              <label htmlFor="rgb" className="rcp-field-label">
                RGB
              </label>
            </div>
          )}
          {!isFieldHide(hideInput, "hsv") && (
            <div className="rcp-field">
              <input
                id="hsv"
                className="rcp-field-input"
                readOnly={disabled}
                value={fields.hsv.value}
                onChange={onInputChange("hsv")}
                onFocus={onInputFocus("hsv")}
                onBlur={onInputBlur("hsv")}
              />
              <label htmlFor="hsv" className="rcp-field-label">
                HSV
              </label>
            </div>
          )}
        </div>
      )}
    </div>
  );
});


================================================
FILE: src/components/fields/index.ts
================================================
export * from "./fields.component";


================================================
FILE: src/components/hue/hue.component.tsx
================================================
import React, { memo, useCallback, useMemo } from "react";

import { useBoundingClientRect } from "@/hooks/use-bounding-client-rect";

import { ColorService, type IColor } from "@/services/color";

import { Interactive } from "../interactive";

interface IHueProps {
  readonly color: IColor;
  readonly disabled?: boolean;
  readonly onChange: (color: IColor) => void;
  readonly onChangeComplete?: (color: IColor) => void;
}

export const Hue = memo(({ color, disabled, onChange, onChangeComplete }: IHueProps) => {
  const [hueRef, { width }] = useBoundingClientRect<HTMLDivElement>();

  const position = useMemo(() => {
    const x = (color.hsv.h / 360) * width;

    return { x };
  }, [color.hsv.h, width]);

  const updateColor = useCallback(
    (final: boolean, x: number) => {
      const nextColor = ColorService.convert("hsv", {
        ...color.hsv,
        h: (x / width) * 360,
      });

      onChange(nextColor);
      if (final) onChangeComplete?.(nextColor);
    },
    [color.hsv, width, onChange, onChangeComplete]
  );

  const hsl = useMemo(() => [color.hsv.h, "100%", "50%"].join(" "), [color.hsv.h]);

  return (
    <Interactive disabled={disabled} onCoordinateChange={updateColor}>
      <div ref={hueRef} className="rcp-hue">
        <div style={{ left: position.x, backgroundColor: `hsl(${hsl})` }} className="rcp-hue-cursor" />
      </div>
    </Interactive>
  );
});


================================================
FILE: src/components/hue/index.ts
================================================
export * from "./hue.component";


================================================
FILE: src/components/interactive/index.ts
================================================
export * from "./interactive.component";


================================================
FILE: src/components/interactive/interactive.component.tsx
================================================
import React, { memo, useCallback } from "react";

import { useBoundingClientRect } from "@/hooks/use-bounding-client-rect";

import { clamp } from "@/utils/clamp";
import { isTouch } from "@/utils/is-touch";

interface IInteractiveProps {
  readonly onCoordinateChange: (final: boolean, x: number, y: number) => void;
  readonly children: React.ReactNode;
  readonly disabled?: boolean;
}

type TInteractionEvent = React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement> | MouseEvent | TouchEvent;
type TMoveEvent = React.MouseEvent<HTMLDivElement> | React.Touch | MouseEvent | Touch;

export const Interactive = memo(({ onCoordinateChange, children, disabled }: IInteractiveProps) => {
  const [interactiveRef, { width, height }, getPosition] = useBoundingClientRect<HTMLDivElement>();

  const move = useCallback(
    (event: TMoveEvent, final = false) => {
      const { left, top } = getPosition();

      const x = clamp(event.clientX - left, 0, width);
      const y = clamp(event.clientY - top, 0, height);

      onCoordinateChange(final, x, y);
    },
    [width, height, getPosition, onCoordinateChange]
  );

  const onStart = useCallback(
    (event: TInteractionEvent) => {
      if (!isTouch(event) && event.button !== 0) return;

      const onMove = (event: TInteractionEvent) => {
        move(isTouch(event) ? event.touches[0] : event);
      };

      const onEnd = (event: TInteractionEvent) => {
        move(isTouch(event) ? event.changedTouches[0] : event, true);

        document.removeEventListener(isTouch(event) ? "touchmove" : "mousemove", onMove, false);
        document.removeEventListener(isTouch(event) ? "touchend" : "mouseup", onEnd, false);
      };

      onMove(event);

      document.addEventListener(isTouch(event) ? "touchmove" : "mousemove", onMove, false);
      document.addEventListener(isTouch(event) ? "touchend" : "mouseup", onEnd, false);
    },
    [move]
  );

  return (
    <div
      ref={interactiveRef}
      className="rcp-interactive"
      onMouseDown={onStart}
      onTouchStart={onStart}
      aria-disabled={disabled}
    >
      {children}
    </div>
  );
});


================================================
FILE: src/components/saturation/index.ts
================================================
export * from "./saturation.component";


================================================
FILE: src/components/saturation/saturation.component.tsx
================================================
import React, { memo, useCallback, useMemo } from "react";

import { useBoundingClientRect } from "@/hooks/use-bounding-client-rect";

import { ColorService, type IColor } from "@/services/color";

import { Interactive } from "../interactive";

interface ISaturationProps {
  readonly height: number;
  readonly color: IColor;
  readonly disabled?: boolean;
  readonly onChange: (color: IColor) => void;
  readonly onChangeComplete?: (color: IColor) => void;
}

export const Saturation = memo(({ height, color, disabled, onChange, onChangeComplete }: ISaturationProps) => {
  const [saturationRef, { width }] = useBoundingClientRect<HTMLDivElement>();

  const position = useMemo(() => {
    const x = (color.hsv.s / 100) * width;
    const y = ((100 - color.hsv.v) / 100) * height;

    return { x, y };
  }, [color.hsv.s, color.hsv.v, width, height]);

  const updateColor = useCallback(
    (final: boolean, x: number, y: number) => {
      const nextColor = ColorService.convert("hsv", {
        ...color.hsv,
        s: (x / width) * 100,
        v: 100 - (y / height) * 100,
      });

      onChange(nextColor);
      if (final) onChangeComplete?.(nextColor);
    },
    [color.hsv, width, height, onChange, onChangeComplete]
  );

  const hsl = useMemo(() => [color.hsv.h, "100%", "50%"].join(" "), [color.hsv.h]);
  const rgb = useMemo(() => [color.rgb.r, color.rgb.g, color.rgb.b].join(" "), [color.rgb.r, color.rgb.g, color.rgb.b]);

  return (
    <Interactive disabled={disabled} onCoordinateChange={updateColor}>
      <div ref={saturationRef} style={{ height, backgroundColor: `hsl(${hsl})` }} className="rcp-saturation">
        <div
          style={{ left: position.x, top: position.y, backgroundColor: `rgb(${rgb})` }}
          className="rcp-saturation-cursor"
        />
      </div>
    </Interactive>
  );
});


================================================
FILE: src/css/rcp.css
================================================
.rcp-root {
  --rcp-background-color: #121212;
  --rcp-field-input-color: #ffffff;
  --rcp-field-input-border-color: #242424;
  --rcp-field-label-color: #808080;
}

.rcp {
  display: flex;
  flex-direction: column;
  background-color: var(--rcp-background-color);
  border-radius: 10px;
}

.rcp-body {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 20px 10px;
}

.rcp-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.rcp-interactive {
  width: 100%;
  height: 100%;
  user-select: none;
  touch-action: none;
}

.rcp-interactive[aria-disabled="true"] {
  cursor: unset;
  pointer-events: none;
}

.rcp-saturation {
  cursor: all-scroll;
  width: 100%;
  position: relative;
  background-image: linear-gradient(to bottom, transparent, black), linear-gradient(to right, white, transparent);
  border-radius: 10px 10px 0 0;
}

.rcp-saturation-cursor {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 2px solid white;
  border-radius: 100%;
  box-shadow: 0 0 15px 0 rgb(0 0 0 / .15);
  transform: translate(-10px, -10px);
}

.rcp-hue {
  cursor: ew-resize;
  position: relative;
  width: 100%;
  height: 12px;
  background-image: linear-gradient(
    to right,
    rgb(255, 0, 0),
    rgb(255, 255, 0),
    rgb(0, 255, 0),
    rgb(0, 255, 255),
    rgb(0, 0, 255),
    rgb(255, 0, 255),
    rgb(255, 0, 0)
  );
  border-radius: 10px;
}

.rcp-hue-cursor {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 2px solid white;
  border-radius: 100%;
  box-shadow: 0 0 15px 0 rgb(0 0 0 / .15);
  transform: translate(-10px, -4px);
}

.rcp-alpha {
  cursor: ew-resize;
  position: relative;
  width: 100%;
  height: 12px;
  border-radius: 10px;
}

.rcp-alpha-cursor {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 2px solid white;
  border-radius: 100%;
  box-shadow: 0 0 15px 0 rgb(0 0 0 / .15);
  transform: translate(-10px, -4px);
}

.rcp-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.rcp-fields-floor {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
}

.rcp-field {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.rcp-field-input {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
  text-align: center;
  color: var(--rcp-field-input-color);
  background-color: transparent;
  border: 2px solid var(--rcp-field-input-border-color);
  border-radius: 5px;
  outline: none;
  padding: 5px 0;
}

.rcp-field-input:read-only {
  opacity: 0.8;
}

.rcp-field-label {
  font-size: 14px;
  text-align: center;
  color: var(--rcp-field-label-color);
}


================================================
FILE: src/hooks/use-bounding-client-rect/index.ts
================================================
export * from "./use-bounding-client-rect.hook";


================================================
FILE: src/hooks/use-bounding-client-rect/use-bounding-client-rect.hook.ts
================================================
import { useCallback, useLayoutEffect, useRef, useState } from "react";

interface ISize {
  readonly width: number;
  readonly height: number;
}

interface IPosition {
  readonly left: number;
  readonly right: number;
  readonly top: number;
  readonly bottom: number;
}

const getElementDimensions = (element: Element): ISize => {
  const rect = element.getBoundingClientRect();

  return {
    width: rect.width,
    height: rect.height,
  };
};

export function useBoundingClientRect<T extends HTMLElement>(): [React.RefObject<T>, ISize, () => IPosition] {
  const ref = useRef<T>(null);

  const [size, setSize] = useState<ISize>({ width: 1, height: 1 });

  useLayoutEffect(() => {
    const onWindowResize = () => {
      if (!ref.current) return;
      setSize(getElementDimensions(ref.current));
    };
    const onElementResize: ResizeObserverCallback = ([{ contentBoxSize }]) => {
      setSize({
        height: contentBoxSize[0].blockSize,
        width: contentBoxSize[0].inlineSize,
      });
    };

    window.addEventListener("resize", onWindowResize, false);

    const observer = new ResizeObserver(onElementResize);

    if (ref.current) observer.observe(ref.current);

    return () => {
      window.removeEventListener("resize", onWindowResize, false);
      observer.disconnect();
    };
  }, []);

  const getPosition = useCallback(() => {
    const { left = 1, right = 1, top = 1, bottom = 1 } = ref.current?.getBoundingClientRect() ?? ({} as DOMRect);

    return { left, right, top, bottom };
  }, []);

  return [ref, size, getPosition];
}


================================================
FILE: src/hooks/use-color/index.ts
================================================
export * from "./use-color.hook";


================================================
FILE: src/hooks/use-color/use-color.hook.ts
================================================
import { useEffect, useState } from "react";

import { ColorService, type IColor } from "@/services/color";

export function useColor(initialColor: string): [IColor, React.Dispatch<React.SetStateAction<IColor>>] {
  const [color, setColor] = useState(ColorService.convert("hex", initialColor));

  useEffect(() => {
    setColor(ColorService.convert("hex", initialColor));
  }, [initialColor]);

  return [color, setColor];
}


================================================
FILE: src/rcp.ts
================================================
export { ColorPicker } from "./components/color-picker";
export { Saturation } from "./components/saturation";
export { Hue } from "./components/hue";
export { Alpha } from "./components/alpha";

export { useColor } from "./hooks/use-color";

export { ColorService, type IColor } from "./services/color";


================================================
FILE: src/services/color/color.service.ts
================================================
import { clamp } from "@/utils/clamp";

export interface IColor {
  readonly hex: string;
  readonly rgb: IColorRgb;
  readonly hsv: IColorHsv;
}

interface IColorRgb {
  readonly r: number;
  readonly g: number;
  readonly b: number;
  readonly a: number;
}

interface IColorHsv {
  readonly h: number;
  readonly s: number;
  readonly v: number;
  readonly a: number;
}

class ColorServiceStatic {
  public convert<M extends keyof IColor, C extends IColor[M]>(model: M, color: C): IColor {
    let hex: IColor["hex"] = this.toHex("#000000");
    let rgb: IColor["rgb"] = this.hex2rgb(hex);
    let hsv: IColor["hsv"] = this.rgb2hsv(rgb);

    if (model === "hex") {
      const value = color as IColor["hex"];

      hex = this.toHex(value);
      rgb = this.hex2rgb(hex);

      if (hex.startsWith("rgba")) {
        rgb = this.toRgb(hex);
        hex = this.rgb2hex(rgb);
      }

      hsv = this.rgb2hsv(rgb);
    } else if (model === "rgb") {
      const value = color as IColor["rgb"];

      rgb = value;
      hex = this.rgb2hex(rgb);
      hsv = this.rgb2hsv(rgb);
    } else if (model === "hsv") {
      const value = color as IColor["hsv"];

      hsv = value;
      rgb = this.hsv2rgb(hsv);
      hex = this.rgb2hex(rgb);
    }

    return { hex, rgb, hsv };
  }

  public toHex(value: string): IColor["hex"] {
    if (!value.startsWith("#")) {
      const ctx = document.createElement("canvas").getContext("2d");

      if (!ctx) throw new Error("2d context not supported or canvas already initialized");

      ctx.fillStyle = value;

      return ctx.fillStyle;
    } else if (value.length === 4 || value.length === 5) {
      value = value
        .split("")
        .map((v, i) => (i ? (i < 4 ? v + v : v === "f" ? undefined : v + v) : "#"))
        .join("");

      return value;
    } else if (value.length === 7) {
      return value;
    } else if (value.length === 9) {
      return value.endsWith("ff") ? value.slice(0, 7) : value;
    }

    return "#000000";
  }

  public toRgb(value: string): IColor["rgb"] {
    const rgb: string[] = value.match(/\d+(\.\d+)?/gu) ?? [];

    const [r, g, b, a] = Array.from({ length: 4 }).map((_, i) =>
      clamp(+(rgb[i] ?? (i < 3 ? 0 : 1)), 0, i < 3 ? 255 : 1)
    );

    return { r, g, b, a };
  }

  public toHsv(value: string): IColor["hsv"] {
    const hsv: string[] = value.match(/\d+(\.\d+)?/gu) ?? [];

    const [h, s, v, a] = Array.from({ length: 4 }).map((_, i) =>
      clamp(+(hsv[i] ?? (i < 3 ? 0 : 1)), 0, i ? (i < 3 ? 100 : 1) : 360)
    );

    return { h, s, v, a };
  }

  public hex2rgb(hex: IColor["hex"]): IColor["rgb"] {
    hex = hex.slice(1);

    let [r, g, b, a] = Array.from({ length: 4 }).map((_, i) => parseInt(hex.slice(i * 2, i * 2 + 2), 16));

    a = Number.isNaN(a) ? 1 : a / 255;

    return { r, g, b, a };
  }

  public rgb2hsv({ r, g, b, a }: IColor["rgb"]): IColor["hsv"] {
    r /= 255;
    g /= 255;
    b /= 255;

    const max = Math.max(r, g, b);
    const d = max - Math.min(r, g, b);

    const h = d ? (max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? 2 + (b - r) / d : 4 + (r - g) / d) * 60 : 0;
    const s = max ? (d / max) * 100 : 0;
    const v = max * 100;

    return { h, s, v, a };
  }

  public hsv2rgb({ h, s, v, a }: IColor["hsv"]): IColor["rgb"] {
    s /= 100;
    v /= 100;

    const i = ~~(h / 60);
    const f = h / 60 - i;
    const p = v * (1 - s);
    const q = v * (1 - s * f);
    const t = v * (1 - s * (1 - f));
    const index = i % 6;

    const r = [v, q, p, p, t, v][index] * 255;
    const g = [t, v, v, q, p, p][index] * 255;
    const b = [p, p, t, v, v, q][index] * 255;

    return { r, g, b, a };
  }

  public rgb2hex({ r, g, b, a }: IColor["rgb"]): IColor["hex"] {
    const [rr, gg, bb, aa] = [r, g, b, a].map((v, i) =>
      Math.round(i < 3 ? v : v * 255)
        .toString(16)
        .padStart(2, "0")
    );

    return ["#", rr, gg, bb, aa === "ff" ? "" : aa].join("");
  }
}

export const ColorService = new ColorServiceStatic();


================================================
FILE: src/services/color/index.ts
================================================
export * from "./color.service";


================================================
FILE: src/utils/clamp/clamp.util.ts
================================================
export function clamp(value: number, min: number, max: number) {
  return value < min ? min : value > max ? max : value;
}


================================================
FILE: src/utils/clamp/index.ts
================================================
export * from "./clamp.util";


================================================
FILE: src/utils/float/float.util.ts
================================================
export function float(value: number, decimalPlaces: number) {
  return Math.round(value * 10 ** decimalPlaces) / 10 ** decimalPlaces;
}


================================================
FILE: src/utils/float/index.ts
================================================
export * from "./float.util";


================================================
FILE: src/utils/format/format.util.ts
================================================
import { type IColor } from "@/services/color";

import { float } from "../float";

export function formatRgb({ r, g, b, a }: IColor["rgb"]) {
  const rgb: any[] = [Math.round(r), Math.round(g), Math.round(b)];
  const alpha = float(a, 3);

  if (alpha < 1) rgb.push(alpha);

  return rgb.join(", ");
}

export function formatHsv({ h, s, v, a }: IColor["hsv"]) {
  const hsv: any[] = [`${Math.round(h)}°`, `${Math.round(s)}%`, `${Math.round(v)}%`];
  const alpha = float(a, 3);

  if (alpha < 1) hsv.push(alpha);

  return hsv.join(", ");
}


================================================
FILE: src/utils/format/index.ts
================================================
export * from "./format.util";


================================================
FILE: src/utils/is-field-hide/index.ts
================================================
export * from "./is-field-hide.util";


================================================
FILE: src/utils/is-field-hide/is-field-hide.util.ts
================================================
import { type IColor } from "@/services/color";

export function isFieldHide(hideInput: (keyof IColor)[] | boolean, field: keyof IColor) {
  return Array.isArray(hideInput) ? hideInput.includes(field) : hideInput;
}


================================================
FILE: src/utils/is-touch/index.ts
================================================
export * from "./is-touch.util";


================================================
FILE: src/utils/is-touch/is-touch.util.ts
================================================
export function isTouch<T>(event: any): event is React.TouchEvent<T> | TouchEvent {
  return "touches" in event;
}


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Node",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    "noEmit": true,
    "strict": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "removeComments": true,
  },
  "include": ["src", "demo", "tsup.config.ts"],
  "exclude": ["node_modules", "dist"]
}


================================================
FILE: tsup.config.ts
================================================
import { defineConfig } from "tsup";

const config = defineConfig({
  entry: ["src/rcp.ts", "src/css/rcp.css"],
  outDir: "dist",
  format: ["esm", "cjs"],
  external: ["react"],
  clean: true,
  minify: false,
  dts: "src/rcp.ts",
  banner: {
    js: `"use client"`,
  },
});

export default config;
Download .txt
gitextract_7m8wauft/

├── .eslintignore
├── .eslintrc
├── .github/
│   ├── COMMIT_CONVENTION.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── versioning.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .vscode/
│   └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── public/
│   └── demo.apng
├── src/
│   ├── components/
│   │   ├── alpha/
│   │   │   ├── alpha.component.tsx
│   │   │   └── index.ts
│   │   ├── color-picker/
│   │   │   ├── color-picker.component.tsx
│   │   │   └── index.ts
│   │   ├── fields/
│   │   │   ├── fields.component.tsx
│   │   │   └── index.ts
│   │   ├── hue/
│   │   │   ├── hue.component.tsx
│   │   │   └── index.ts
│   │   ├── interactive/
│   │   │   ├── index.ts
│   │   │   └── interactive.component.tsx
│   │   └── saturation/
│   │       ├── index.ts
│   │       └── saturation.component.tsx
│   ├── css/
│   │   └── rcp.css
│   ├── hooks/
│   │   ├── use-bounding-client-rect/
│   │   │   ├── index.ts
│   │   │   └── use-bounding-client-rect.hook.ts
│   │   └── use-color/
│   │       ├── index.ts
│   │       └── use-color.hook.ts
│   ├── rcp.ts
│   ├── services/
│   │   └── color/
│   │       ├── color.service.ts
│   │       └── index.ts
│   └── utils/
│       ├── clamp/
│       │   ├── clamp.util.ts
│       │   └── index.ts
│       ├── float/
│       │   ├── float.util.ts
│       │   └── index.ts
│       ├── format/
│       │   ├── format.util.ts
│       │   └── index.ts
│       ├── is-field-hide/
│       │   ├── index.ts
│       │   └── is-field-hide.util.ts
│       └── is-touch/
│           ├── index.ts
│           └── is-touch.util.ts
├── tsconfig.json
└── tsup.config.ts
Download .txt
SYMBOL INDEX (30 symbols across 14 files)

FILE: src/components/alpha/alpha.component.tsx
  type IAlphaProps (line 9) | interface IAlphaProps {

FILE: src/components/color-picker/color-picker.component.tsx
  type IColorPickerProps (line 12) | interface IColorPickerProps {

FILE: src/components/fields/fields.component.tsx
  type IFieldsProps (line 8) | interface IFieldsProps {

FILE: src/components/hue/hue.component.tsx
  type IHueProps (line 9) | interface IHueProps {

FILE: src/components/interactive/interactive.component.tsx
  type IInteractiveProps (line 8) | interface IInteractiveProps {
  type TInteractionEvent (line 14) | type TInteractionEvent = React.MouseEvent<HTMLDivElement> | React.TouchE...
  type TMoveEvent (line 15) | type TMoveEvent = React.MouseEvent<HTMLDivElement> | React.Touch | Mouse...

FILE: src/components/saturation/saturation.component.tsx
  type ISaturationProps (line 9) | interface ISaturationProps {

FILE: src/hooks/use-bounding-client-rect/use-bounding-client-rect.hook.ts
  type ISize (line 3) | interface ISize {
  type IPosition (line 8) | interface IPosition {
  function useBoundingClientRect (line 24) | function useBoundingClientRect<T extends HTMLElement>(): [React.RefObjec...

FILE: src/hooks/use-color/use-color.hook.ts
  function useColor (line 5) | function useColor(initialColor: string): [IColor, React.Dispatch<React.S...

FILE: src/services/color/color.service.ts
  type IColor (line 3) | interface IColor {
  type IColorRgb (line 9) | interface IColorRgb {
  type IColorHsv (line 16) | interface IColorHsv {
  class ColorServiceStatic (line 23) | class ColorServiceStatic {
    method convert (line 24) | public convert<M extends keyof IColor, C extends IColor[M]>(model: M, ...
    method toHex (line 58) | public toHex(value: string): IColor["hex"] {
    method toRgb (line 83) | public toRgb(value: string): IColor["rgb"] {
    method toHsv (line 93) | public toHsv(value: string): IColor["hsv"] {
    method hex2rgb (line 103) | public hex2rgb(hex: IColor["hex"]): IColor["rgb"] {
    method rgb2hsv (line 113) | public rgb2hsv({ r, g, b, a }: IColor["rgb"]): IColor["hsv"] {
    method hsv2rgb (line 128) | public hsv2rgb({ h, s, v, a }: IColor["hsv"]): IColor["rgb"] {
    method rgb2hex (line 146) | public rgb2hex({ r, g, b, a }: IColor["rgb"]): IColor["hex"] {

FILE: src/utils/clamp/clamp.util.ts
  function clamp (line 1) | function clamp(value: number, min: number, max: number) {

FILE: src/utils/float/float.util.ts
  function float (line 1) | function float(value: number, decimalPlaces: number) {

FILE: src/utils/format/format.util.ts
  function formatRgb (line 5) | function formatRgb({ r, g, b, a }: IColor["rgb"]) {
  function formatHsv (line 14) | function formatHsv({ h, s, v, a }: IColor["hsv"]) {

FILE: src/utils/is-field-hide/is-field-hide.util.ts
  function isFieldHide (line 3) | function isFieldHide(hideInput: (keyof IColor)[] | boolean, field: keyof...

FILE: src/utils/is-touch/is-touch.util.ts
  function isTouch (line 1) | function isTouch<T>(event: any): event is React.TouchEvent<T> | TouchEve...
Condensed preview — 49 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (85K chars).
[
  {
    "path": ".eslintignore",
    "chars": 49,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/dist\n"
  },
  {
    "path": ".eslintrc",
    "chars": 21807,
    "preview": "{\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"project\": [\"./tsconfig.json\"],\n    \"ecmaVersion\": \""
  },
  {
    "path": ".github/COMMIT_CONVENTION.md",
    "chars": 1620,
    "preview": "## Git Commit Message Convention\n\n> This is adapted from [Angular's commit convention](https://github.com/conventional-c"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 377,
    "preview": "# Contributing\n\n## Setup\n\n1. Fork & Clone the repository.\n2. Run `pnpm install`.\n3. Time to code!\n\n## Test\n\n1. Run `pnpm"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 588,
    "preview": "---\nname: Bug Report\nabout: Report incorrect behavior of react-color-palette\ntitle: ''\nlabels: 's: unverified, t: bug'\na"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 444,
    "preview": "---\nname: Feature Request\nabout: Suggest your idea for the development of the project\ntitle: ''\nlabels: 't: enhancement'"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 606,
    "preview": "<!--\n  Before opening the request, make sure that all the listed conditions are met.\n\n  - Code is up-to-date with the `m"
  },
  {
    "path": ".github/workflows/versioning.yml",
    "chars": 452,
    "preview": "name: Versioning\n\non:\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n "
  },
  {
    "path": ".gitignore",
    "chars": 413,
    "preview": "# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.v"
  },
  {
    "path": ".prettierignore",
    "chars": 49,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/dist\n"
  },
  {
    "path": ".prettierrc",
    "chars": 992,
    "preview": "{\n  \"printWidth\": 120,\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": true,\n  \"singleQuote\": false,\n  \"quoteProps\": \"as-"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 568,
    "preview": "{\n  \"editor.tabSize\": 2,\n  \"editor.quickSuggestions\": {\n    \"strings\": \"on\"\n  },\n  \"[typescript][typescriptreact]\": {\n  "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 11393,
    "preview": "# Changelog\n\n\n## [7.3.1](https://github.com/Wondermarin/react-color-palette/compare/v7.3.0...v7.3.1) (2025-08-07)\n\n\n### "
  },
  {
    "path": "LICENSE",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2021 Wondermarin\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 9182,
    "preview": "<div align=\"center\">\n  <p>\n    <img alt=\"react-color-palette\" src=\"https://github.com/Wondermarin/react-color-palette/ra"
  },
  {
    "path": "package.json",
    "chars": 1931,
    "preview": "{\n  \"name\": \"react-color-palette\",\n  \"version\": \"7.3.1\",\n  \"description\": \"🎨 Lightweight Color Picker component for Reac"
  },
  {
    "path": "src/components/alpha/alpha.component.tsx",
    "chars": 2196,
    "preview": "import React, { memo, useCallback, useMemo } from \"react\";\n\nimport { useBoundingClientRect } from \"@/hooks/use-bounding-"
  },
  {
    "path": "src/components/alpha/index.ts",
    "chars": 35,
    "preview": "export * from \"./alpha.component\";\n"
  },
  {
    "path": "src/components/color-picker/color-picker.component.tsx",
    "chars": 1789,
    "preview": "import React, { memo } from \"react\";\n\nimport { type IColor } from \"@/services/color\";\n\nimport { isFieldHide } from \"@/ut"
  },
  {
    "path": "src/components/color-picker/index.ts",
    "chars": 42,
    "preview": "export * from \"./color-picker.component\";\n"
  },
  {
    "path": "src/components/fields/fields.component.tsx",
    "chars": 4681,
    "preview": "import React, { memo, useCallback, useEffect, useState } from \"react\";\n\nimport { ColorService, type IColor } from \"@/ser"
  },
  {
    "path": "src/components/fields/index.ts",
    "chars": 36,
    "preview": "export * from \"./fields.component\";\n"
  },
  {
    "path": "src/components/hue/hue.component.tsx",
    "chars": 1401,
    "preview": "import React, { memo, useCallback, useMemo } from \"react\";\n\nimport { useBoundingClientRect } from \"@/hooks/use-bounding-"
  },
  {
    "path": "src/components/hue/index.ts",
    "chars": 33,
    "preview": "export * from \"./hue.component\";\n"
  },
  {
    "path": "src/components/interactive/index.ts",
    "chars": 41,
    "preview": "export * from \"./interactive.component\";\n"
  },
  {
    "path": "src/components/interactive/interactive.component.tsx",
    "chars": 2139,
    "preview": "import React, { memo, useCallback } from \"react\";\n\nimport { useBoundingClientRect } from \"@/hooks/use-bounding-client-re"
  },
  {
    "path": "src/components/saturation/index.ts",
    "chars": 40,
    "preview": "export * from \"./saturation.component\";\n"
  },
  {
    "path": "src/components/saturation/saturation.component.tsx",
    "chars": 1834,
    "preview": "import React, { memo, useCallback, useMemo } from \"react\";\n\nimport { useBoundingClientRect } from \"@/hooks/use-bounding-"
  },
  {
    "path": "src/css/rcp.css",
    "chars": 2612,
    "preview": ".rcp-root {\n  --rcp-background-color: #121212;\n  --rcp-field-input-color: #ffffff;\n  --rcp-field-input-border-color: #24"
  },
  {
    "path": "src/hooks/use-bounding-client-rect/index.ts",
    "chars": 49,
    "preview": "export * from \"./use-bounding-client-rect.hook\";\n"
  },
  {
    "path": "src/hooks/use-bounding-client-rect/use-bounding-client-rect.hook.ts",
    "chars": 1571,
    "preview": "import { useCallback, useLayoutEffect, useRef, useState } from \"react\";\n\ninterface ISize {\n  readonly width: number;\n  r"
  },
  {
    "path": "src/hooks/use-color/index.ts",
    "chars": 34,
    "preview": "export * from \"./use-color.hook\";\n"
  },
  {
    "path": "src/hooks/use-color/use-color.hook.ts",
    "chars": 426,
    "preview": "import { useEffect, useState } from \"react\";\n\nimport { ColorService, type IColor } from \"@/services/color\";\n\nexport func"
  },
  {
    "path": "src/rcp.ts",
    "chars": 305,
    "preview": "export { ColorPicker } from \"./components/color-picker\";\nexport { Saturation } from \"./components/saturation\";\nexport { "
  },
  {
    "path": "src/services/color/color.service.ts",
    "chars": 3998,
    "preview": "import { clamp } from \"@/utils/clamp\";\n\nexport interface IColor {\n  readonly hex: string;\n  readonly rgb: IColorRgb;\n  r"
  },
  {
    "path": "src/services/color/index.ts",
    "chars": 33,
    "preview": "export * from \"./color.service\";\n"
  },
  {
    "path": "src/utils/clamp/clamp.util.ts",
    "chars": 123,
    "preview": "export function clamp(value: number, min: number, max: number) {\n  return value < min ? min : value > max ? max : value;"
  },
  {
    "path": "src/utils/clamp/index.ts",
    "chars": 30,
    "preview": "export * from \"./clamp.util\";\n"
  },
  {
    "path": "src/utils/float/float.util.ts",
    "chars": 136,
    "preview": "export function float(value: number, decimalPlaces: number) {\n  return Math.round(value * 10 ** decimalPlaces) / 10 ** d"
  },
  {
    "path": "src/utils/float/index.ts",
    "chars": 30,
    "preview": "export * from \"./float.util\";\n"
  },
  {
    "path": "src/utils/format/format.util.ts",
    "chars": 541,
    "preview": "import { type IColor } from \"@/services/color\";\n\nimport { float } from \"../float\";\n\nexport function formatRgb({ r, g, b,"
  },
  {
    "path": "src/utils/format/index.ts",
    "chars": 31,
    "preview": "export * from \"./format.util\";\n"
  },
  {
    "path": "src/utils/is-field-hide/index.ts",
    "chars": 38,
    "preview": "export * from \"./is-field-hide.util\";\n"
  },
  {
    "path": "src/utils/is-field-hide/is-field-hide.util.ts",
    "chars": 216,
    "preview": "import { type IColor } from \"@/services/color\";\n\nexport function isFieldHide(hideInput: (keyof IColor)[] | boolean, fiel"
  },
  {
    "path": "src/utils/is-touch/index.ts",
    "chars": 33,
    "preview": "export * from \"./is-touch.util\";\n"
  },
  {
    "path": "src/utils/is-touch/is-touch.util.ts",
    "chars": 115,
    "preview": "export function isTouch<T>(event: any): event is React.TouchEvent<T> | TouchEvent {\n  return \"touches\" in event;\n}\n"
  },
  {
    "path": "tsconfig.json",
    "chars": 533,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"lib\": [\"ES"
  },
  {
    "path": "tsup.config.ts",
    "chars": 301,
    "preview": "import { defineConfig } from \"tsup\";\n\nconst config = defineConfig({\n  entry: [\"src/rcp.ts\", \"src/css/rcp.css\"],\n  outDir"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the Wondermarin/react-color-palette GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 49 files (46.3 MB), approximately 24.3k tokens, and a symbol index with 30 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!