From ee905c6569704f97a2f1ff56956ed726d092d744 Mon Sep 17 00:00:00 2001 From: C <21029087+csqrl@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:36:52 +0100 Subject: [PATCH] v1.4.1 (#6) ### Added - Implemented `Palette.Nearest` method, which returns the nearest colour in a palette to a given colour. - Implemented `LAB.Lerp` method, which returns a colour between two colours in the LAB colour space. - Missing TypeScript types for new methods and `Hex.fromHexRGBA`. - CI workflow to ensure code is formatted and linted correctly. ### Fixed - Due to a typo, the `APCA.GetContrastRatio` method was throwing an error when attempting to calculate the contrast ratio for certain colours. ### Changed All deprecated methods will output warnings to the console when used for the first time. This is to help users migrate to the new methods. - This project's toolchain is now managed by aftman. Use of foreman is not recommended. - All instances of the word "colour" have been changed to "color" to match the US spelling and keep consistency with the Roblox API. - `ColorUtils.Emphasise` and `ColorUtils.GetContrastingColour` are now marked as deprecated for the same reason as above. - `ColorUtils.GetContrastingColor` is now marked as deprecated. The `WCAG` submodule should be used instead, since both `APCA` and `WCAG` provide two different methods for calculating contrast ratio. - `ColorUtils.GetContrastRatio` is now marked as deprecated and implements a compatibility layer. Previously this was a redirect to `WCAG.GetContrastRatio` but now it will use `APCA.GetContrastRatio` because it is more accurate. `WCAG` values (`0-21`) will be returned for backwards compatibility until the method is removed in a future release. - `Palette.Tailwind` will now produce a darker 950 shade, in line with [Tailwind v3.3.2](https://tailwindcss.com/docs/customizing-colors). Note that the generated palette will be slightly different to tailwind's, since the algorithm used to generate the palette is different. --- .github/workflows/ci.yml | 52 +++++++ .github/workflows/publish.yml | 36 +---- .github/workflows/release.yml | 23 ++- .gitignore | 2 +- .husky/pre-commit | 5 + .markdownlint.json | 3 + .moonwave/static/media/tailwind-palette.png | Bin 0 -> 13264 bytes .stylua.toml | 2 + .vscode/extensions.json | 10 -- .vscode/scripts/run-tests.ps1 | 2 +- .vscode/settings.json | 11 +- CHANGELOG.md | 77 ++++++++-- README.md | 44 +++--- aftman.toml | 7 + foreman.toml | 6 - moonwave.toml | 4 +- package-lock.json | 26 +++- package.json | 8 +- src/APCA/GetContrastRatio.lua | 20 +-- src/Blend/Burn.lua | 6 +- src/Blend/Burn.spec.lua | 2 +- src/Blend/Dodge.lua | 6 +- src/Blend/Dodge.spec.lua | 2 +- src/Blend/Multiply.lua | 6 +- src/Blend/Multiply.spec.lua | 2 +- src/Blend/Overlay.lua | 6 +- src/Blend/Overlay.spec.lua | 2 +- src/Blend/Screen.lua | 6 +- src/Blend/Screen.spec.lua | 2 +- src/Blend/Transparency.lua | 6 +- src/Blend/Transparency.spec.lua | 2 +- src/Blend/_Filter.lua | 8 +- src/Blind/Enum.lua | 28 ++-- src/Blind/Simulate/init.lua | 30 ++-- src/Blind/Simulate/init.spec.lua | 16 +- src/Darken.lua | 16 +- src/Darken.spec.lua | 32 ++-- src/Desaturate.lua | 14 +- src/Desaturate.spec.lua | 8 +- src/Emphasise.lua | 23 --- src/Emphasise.spec.lua | 27 ---- src/Emphasize.lua | 17 +++ src/Emphasize.spec.lua | 27 ++++ src/GetContrastRatio.lua | 20 --- src/GetContrastRatioCompat.lua | 18 +++ src/GetContrastingColour.lua | 28 ---- src/GetLuminance.lua | 18 +-- src/GetPerceivedBrightness.lua | 18 +-- src/HSL/init.lua | 26 ++-- src/HSL/init.spec.lua | 2 +- src/Hex/init.lua | 30 ++-- src/Hex/init.spec.lua | 2 +- src/Int/init.lua | 20 +-- src/Int/init.spec.lua | 2 +- src/Invert.lua | 18 +-- src/Invert.spec.lua | 2 +- src/LAB/FromLAB.lua | 8 +- src/LAB/FromLAB.spec.lua | 4 +- src/LAB/Lerp.lua | 31 ++++ src/LAB/Lerp.spec.lua | 33 +++++ src/LAB/ToLAB.lua | 20 +-- src/LAB/ToLAB.spec.lua | 2 +- src/LAB/init.lua | 1 + src/LCH/FromLCH.lua | 6 +- src/LCH/FromLCH.spec.lua | 4 +- src/LCH/ToLCH.lua | 10 +- src/LCH/ToLCH.spec.lua | 2 +- src/Lighten.lua | 16 +- src/Lighten.spec.lua | 36 ++--- src/Palette/Analogous.lua | 8 +- src/Palette/Analogous.spec.lua | 2 +- src/Palette/Complementary.lua | 8 +- src/Palette/Complementary.spec.lua | 2 +- src/Palette/Monochromatic.lua | 14 +- src/Palette/Monochromatic.spec.lua | 2 +- src/Palette/Nearest.lua | 42 ++++++ src/Palette/Nearest.spec.lua | 63 ++++++++ src/Palette/SplitComplementary.lua | 8 +- src/Palette/SplitComplementary.spec.lua | 2 +- src/Palette/Tailwind.lua | 43 ++++-- src/Palette/Tailwind.spec.lua | 9 +- src/Palette/Tetradic.lua | 8 +- src/Palette/Tetradic.spec.lua | 2 +- src/Palette/Triadic.lua | 8 +- src/Palette/Triadic.spec.lua | 2 +- src/Palette/Vibrant.lua | 8 +- src/Palette/Vibrant.spec.lua | 4 +- src/Palette/init.lua | 1 + src/Rotate.lua | 20 +-- src/Rotate.spec.lua | 18 +-- src/Saturate.lua | 18 +-- src/Saturate.spec.lua | 8 +- src/{_Util => Util}/Array.lua | 0 src/{_Util => Util}/Assert.lua | 11 +- src/{_Util => Util}/BasicallyIdentical.lua | 10 +- src/Util/ClampColor.lua | 9 ++ src/Util/DeprecateWarnOnce.lua | 18 +++ src/{_Util => Util}/Schema.lua | 0 src/Util/Types.lua | 4 + src/{_Util => Util}/init.lua | 2 +- src/{_Util => Util}/isNaN.lua | 0 src/WCAG/GetContrastRatio.lua | 6 +- ...tingColour.lua => GetContrastingColor.lua} | 14 +- ....spec.lua => GetContrastingColor.spec.lua} | 24 +-- src/WCAG/init.lua | 2 +- src/_Util/ClampColour.lua | 9 -- src/_Util/Types.lua | 4 - src/init.lua | 33 ++++- src/isDark.lua | 14 +- src/isLight.lua | 14 +- test-runner.server.lua | 4 +- testez.toml | 66 +++++++++ typings/index.d.ts | 140 +++++++++++------- wally.lock | 8 + wally.toml | 7 +- 115 files changed, 1043 insertions(+), 665 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .husky/pre-commit create mode 100644 .markdownlint.json create mode 100644 .moonwave/static/media/tailwind-palette.png create mode 100644 .stylua.toml delete mode 100644 .vscode/extensions.json create mode 100644 aftman.toml delete mode 100644 foreman.toml delete mode 100644 src/Emphasise.lua delete mode 100644 src/Emphasise.spec.lua create mode 100644 src/Emphasize.lua create mode 100644 src/Emphasize.spec.lua delete mode 100644 src/GetContrastRatio.lua create mode 100644 src/GetContrastRatioCompat.lua delete mode 100644 src/GetContrastingColour.lua create mode 100644 src/LAB/Lerp.lua create mode 100644 src/LAB/Lerp.spec.lua create mode 100644 src/Palette/Nearest.lua create mode 100644 src/Palette/Nearest.spec.lua rename src/{_Util => Util}/Array.lua (100%) rename src/{_Util => Util}/Assert.lua (92%) rename src/{_Util => Util}/BasicallyIdentical.lua (86%) create mode 100644 src/Util/ClampColor.lua create mode 100644 src/Util/DeprecateWarnOnce.lua rename src/{_Util => Util}/Schema.lua (100%) create mode 100644 src/Util/Types.lua rename src/{_Util => Util}/init.lua (84%) rename src/{_Util => Util}/isNaN.lua (100%) rename src/WCAG/{GetContrastingColour.lua => GetContrastingColor.lua} (74%) rename src/WCAG/{GetContrastingColour.spec.lua => GetContrastingColor.spec.lua} (55%) delete mode 100644 src/_Util/ClampColour.lua delete mode 100644 src/_Util/Types.lua create mode 100644 testez.toml create mode 100644 wally.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bfdda07 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: CI + +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + push: + branches: [main] + +jobs: + build: + name: Test and Build + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v2 + + - name: Setup Aftman + uses: ok-nick/setup-aftman@v0.3.0 + + - name: Install Packages + run: wally install + + - name: Build + run: rojo build default.project.json -o test.rbxm + + - name: Set Environment Variables + run: | + echo "COMMIT_HASH=$(git rev-parse --short ${{github.sha}})" >> $GITHUB_ENV + + - name: Upload Build Artifact + uses: actions/upload-artifact@v3 + with: + name: ${{github.event.repository.name}}-${{env.COMMIT_HASH}}.rbxm + path: test.rbxm + + lint: + name: Format and Lint + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v2 + + - name: Setup Aftman + uses: ok-nick/setup-aftman@v0.3.0 + + - name: Format + run: stylua --check src/ + + - name: Lint + run: selene src/ diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 19db075..131e226 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,8 +1,5 @@ name: Publish Package -env: - ASSET_ID_STABLE: 6573728888 - on: workflow_dispatch: release: @@ -14,39 +11,19 @@ jobs: timeout-minutes: 8 steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - # - name: Test Roblox Login Tokens - # shell: bash - # run: | - # if [ -z "${{ secrets.ROBLOSECURITY }}" ]; then - # echo "No cookie found. Please set the ROBLOSECURITY secret." - # exit 1 - # fi - - # RBX_USERNAME=$(curl -s -X GET -H "Cookie: .ROBLOSECURITY=${{ secrets.ROBLOSECURITY }}" https://users.roblox.com/v1/users/authenticated | jq -r ".name") - - # if [ -z "$RBX_USERNAME" ]; then - # echo "ROBLOSECURITY is invalid or expired. Please reset the ROBLOSECURITY secret." - # exit 1 - # fi - - # echo "Logged in as $RBX_USERNAME." + - uses: actions/checkout@v2 - name: Setup Node LTS uses: actions/setup-node@v2 with: node-version: lts/* - - name: Setup Toolchain - uses: Roblox/setup-foreman@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup Aftman + uses: ok-nick/setup-aftman@v0.3.0 - name: Report Tool Versions run: | - foreman list + aftman list npm -v node -v @@ -59,11 +36,6 @@ jobs: run: | find . -name "*.spec.lua" -delete - # - name: Publish to Roblox - # if: ${{ github.event.release.prerelease == false }} - # shell: bash - # run: rojo upload default.project.json --asset_id $ASSET_ID_STABLE --cookie "${{ secrets.ROBLOSECURITY }}" - - name: Publish to Wally if: ${{ github.event.release.prerelease == false }} env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 66aa485..709661f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,16 +2,13 @@ name: Create GitHub Release on: workflow_dispatch: - branches: - - default jobs: create-release: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - name: Checkout Repository - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - name: Ensure Wally+NPM Version Numbers Match run: | @@ -33,14 +30,11 @@ jobs: exit 1 fi - - name: Setup Toolchain - uses: Roblox/setup-foreman@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - version: "^1.0.1" + - name: Setup Aftman + uses: ok-nick/setup-aftman@v0.3.0 - name: Report Tool Versions - run: foreman list + run: aftman list - name: Get Release Details shell: bash @@ -55,12 +49,17 @@ jobs: run: wally install - name: Remove Tests - run: | - find . -name "*.spec.lua" -delete + run: find . -name "*.spec.lua" -delete - name: Build Project run: rojo build default.project.json -o $RELEASE_FILENAME + - name: Upload Build Artifact + uses: actions/upload-artifact@v2 + with: + name: ${{ env.RELEASE_FILENAME }} + path: ${{ env.RELEASE_FILENAME }} + - name: Create GitHub Release uses: softprops/action-gh-release@v1 with: diff --git a/.gitignore b/.gitignore index 67b1128..a85f4ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.rbx* +sourcemap.json roblox.toml -testez.toml node_modules/ *.tsbuildinfo diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..ece6a97 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +stylua --check src/ +selene src/ diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..79aa8d7 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,3 @@ +{ + "MD033": false +} diff --git a/.moonwave/static/media/tailwind-palette.png b/.moonwave/static/media/tailwind-palette.png new file mode 100644 index 0000000000000000000000000000000000000000..d35ef071bd3e4753f17b658f8c5c3a30942b7357 GIT binary patch literal 13264 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Μ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 literal 0 HcmV?d00001 diff --git a/.stylua.toml b/.stylua.toml new file mode 100644 index 0000000..ed2de71 --- /dev/null +++ b/.stylua.toml @@ -0,0 +1,2 @@ +[sort_requires] +enabled = true diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 605cacc..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "recommendations": [ - "kampfkarren.selene-vscode", - "nightrains.robloxlsp", - "evaera.vscode-rojo", - "redhat.vscode-yaml", - "johnnymorganz.stylua", - "bungcip.better-toml" - ] -} diff --git a/.vscode/scripts/run-tests.ps1 b/.vscode/scripts/run-tests.ps1 index 622c0cd..d6e29e0 100644 --- a/.vscode/scripts/run-tests.ps1 +++ b/.vscode/scripts/run-tests.ps1 @@ -1,6 +1,6 @@ $FILE_NAME = "test-place" -foreman install +aftman install rojo build .\test.project.json -o ".\$FILE_NAME.rbxl" run-in-roblox --place ".\$FILE_NAME.rbxl" --script ".\test-runner.server.lua" Remove-Item -Force ".\$FILE_NAME.rbxl" diff --git a/.vscode/settings.json b/.vscode/settings.json index 5b58779..26142c8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,7 @@ { - "robloxLsp.diagnostics.severity": { - "unused-local": "Error", - "unused-function": "Error", - "unused-vararg": "Error", - "duplicate-index": "Error" - } + "[lua]": { + "editor.defaultFormatter": "JohnnyMorganz.stylua", + "editor.formatOnSave": true + }, + "debug.toolBarLocation": "hidden" } diff --git a/CHANGELOG.md b/CHANGELOG.md index c51767c..34dd717 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,51 @@ # Changelog +## [1.4.1] + +### Added + +- Implemented `Palette.Nearest` method, which returns the nearest colour in a + palette to a given colour. +- Implemented `LAB.Lerp` method, which returns a colour between two colours in + the LAB colour space. +- Missing TypeScript types for new methods and `Hex.fromHexRGBA`. +- CI workflow to ensure code is formatted and linted correctly. + +### Fixed + +- Due to a typo, the `APCA.GetContrastRatio` method was throwing an error when + attempting to calculate the contrast ratio for certain colours. + +### Changed + +All deprecated methods will output warnings to the console when used for the +first time. This is to help users migrate to the new methods. + +- This project's toolchain is now managed by aftman. Use of foreman is not recommended. +- All instances of the word "colour" have been changed to "color" to match the + US spelling and keep consistency with the Roblox API. +- `ColorUtils.Emphasise` and `ColorUtils.GetContrastingColour` are now marked as + deprecated for the same reason as above. +- `ColorUtils.GetContrastingColor` is now marked as deprecated. The `WCAG` + submodule should be used instead, since both `APCA` and `WCAG` provide two + different methods for calculating contrast ratio. +- `ColorUtils.GetContrastRatio` is now marked as deprecated and implements a + compatibility layer. Previously this was a redirect to `WCAG.GetContrastRatio` + but now it will use `APCA.GetContrastRatio` because it is more accurate. `WCAG` + values (`0-21`) will be returned for backwards compatibility until the method is + removed in a future release. +- `Palette.Tailwind` will now produce a darker 950 shade, in line with + [Tailwind v3.3.2](https://tailwindcss.com/docs/customizing-colors). Note that the + generated palette will be slightly different to tailwind's, since the algorithm + used to generate the palette is different. + ## [1.3.1] - Implemented transparency blending: - - This returns a new Color3 that acts as if it was overlaid on a background color with a given alpha. -- Added `Hex.fromHexRGBA`, which converts a hex string with an alpha channel to a Color3. + - This returns a new Color3 that acts as if it was overlaid on a background + color with a given alpha. +- Added `Hex.fromHexRGBA`, which converts a hex string with an alpha channel to + a Color3. ## [1.3.0] @@ -15,28 +56,36 @@ - `LAB` (`.fromLAB, .toLAB`) _(:test_tube: experimental)_. - `LCH` (`.fromLCH, .toLCH`) _(:test_tube: experimental)_. - Saturation methods to either saturate or desaturate a colour. -- Tailwind CSS-style palette generator - Generates 10 swatches, given a base colour, and returns a `TailwindPalette` object (see the docs for more details). +- Tailwind CSS-style palette generator - Generates 10 swatches, given a base + colour, and returns a `TailwindPalette` object (see the docs for more details). ### Changed -- Updated the docs for Hex and Int. The converter methods were previously documented in PascalCase, but they should have been documented in camelCase. -- The `Palette.Monochromatic` method now accepts an optional second parameter, `swatches`, which defaults to `3`. This is to allow for more control over the number of swatches generated. - - **:warning: Warning:** The behaviour of monochromatic has been changed to allow for more control over the number of swatches generated. - - The new behaviour will return `X` amount of swatches, **including** the base colour. The results do not necessarily include a single lighter and darker swatch, and the resulting array is now sorted from darkest to lightest (most vibrant). - -### +- Updated the docs for Hex and Int. The converter methods were previously + documented in PascalCase, but they should have been documented in camelCase. +- The `Palette.Monochromatic` method now accepts an optional second parameter, + `swatches`, which defaults to `3`. This is to allow for more control over the + number of swatches generated. + - **:warning: Warning:** The behaviour of monochromatic has been changed to + allow for more control over the number of swatches generated. + - The new behaviour will return `X` amount of swatches, **including** the base + colour. The results do not necessarily include a single lighter and darker + swatch, and the resulting array is now sorted from darkest to lightest (most + vibrant). ## [1.2.0] ### Added -- `WCAG` submodule to house the current `.GetContrastRatio` and `.GetContrastingColour` methods. +- `WCAG` submodule to house the current `.GetContrastRatio` and `.GetContrastingColour` + methods. - `APCA` submodule, which contains an updated version of `.GetContrastRatio`. - Implemented colour blindness simulation under the `Blind` submodule. - Supports the Trichroma-, Protan-, Deutan-, Tritan- and Achroma- groups. - Includes friendly "`Enums`" for non-scientists. - Documentation site using [moonwave](https://upliftgames.github.io/moonwave/). -- TypeScript alias for `.GetContrastingColour` in root namespace (previously only Luau). +- TypeScript alias for `.GetContrastingColour` in root namespace (previously only + Luau). ### Changed @@ -45,13 +94,15 @@ ### Removed -- Removed `rotriever.toml` to drop support for kayak and other rotriever-based package managers. +- Removed `rotriever.toml` to drop support for kayak and other rotriever-based + package managers. ## [1.1.1] ### Added -- Added `.GetContrastingColour` to adjust a forground colour to meet the minimum contrast ratio against a background colour. +- Added `.GetContrastingColour` to adjust a forground colour to meet the minimum + contrast ratio against a background colour. ## [1.1.0] diff --git a/README.md b/README.md index 0f115c5..df4ded5 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,8 @@ [repo]: https://github.com/csqrl/colour-utils [releases]: https://github.com/csqrl/colour-utils/releases -[library]: https://www.roblox.com/library/6573728888 +[library]: https://create.roblox.com/marketplace/asset/6573728888 [npm]: https://npmjs.com/package/@rbxts/colour-utils -[roblox-ts]: https://roblox-ts.com -[wally]: https://github.com/upliftgames/wally -[itch.io]: https://csqrl.itch.io/colour-utils @@ -17,33 +14,41 @@ [badge/github]: https://raw.githubusercontent.com/gist/csqrl/56c5f18b229ca1e61feb6eb5fb149f43/raw/githubSource.svg -[badge/itch]: https://raw.githubusercontent.com/gist/csqrl/56c5f18b229ca1e61feb6eb5fb149f43/raw/itch.svg [badge/npm]: https://raw.githubusercontent.com/gist/csqrl/56c5f18b229ca1e61feb6eb5fb149f43/raw/npm.svg -[badge/roblox]: https://raw.githubusercontent.com/gist/csqrl/56c5f18b229ca1e61feb6eb5fb149f43/raw/robloxSmall.svg -# ColourUtils +# ColorUtils
-[![Source Code][badge/github]][repo] [![Itch.io][badge/itch]][itch.io] [![NPM][badge/npm]][npm] +[![Source Code][badge/github]][repo] [![NPM][badge/npm]][npm] [![Releases][shield/ghv]][releases] [![NPM][shield/npmv]][npm] [![Wally][shield/wallyv]][releases]
-ColourUtils is a utility library for Roblox Studio that provides a number of functions for working with colours. +ColorUtils is a utility library for Roblox Studio that provides a number of +functions for working with colors. -The library contains methods to manipulate standard `Color3`s, as well as convert them back and forth between formats; such as Hex and Integer _(great for Discord!)_. +The library contains methods to manipulate standard `Color3`s, as well as convert +them back and forth between formats; such as Hex and Integer _(great for Discord!)_. -ColourUtils can also generate colour palettes, blend colours together, and even simulate colour blindness. In combination with the built-in accessibility-focused "submodules," ColourUtils can be used to find and generate the perfect and most accessible colours for your project. +ColorUtils can also generate color palettes, blend colors together, and even +simulate color blindness. In combination with the built-in accessibility-focused +"submodules," ColorUtils can be used to find and generate the perfect and most +accessible colors for your project. ## Documentation -Documentation is available at https://csqrl.github.io/colour-utils. +Documentation is available at . ## Quick Start -ColourUtils is available in Lua and TypeScript (via roblox-ts). It's available from the wally and npm registries, Roblox Library and via Itch.io. +ColorUtils is available in Lua and TypeScript (via roblox-ts). It's available +from the wally and npm registries, Roblox Library and via Itch.io. + +> :warning: **Note:** ColorUtils was released on wally and npm using the +> British spelling of "colour" in the package name. Bear this in mind when +> installing the package. ### Wally @@ -51,22 +56,23 @@ ColourUtils is available in Lua and TypeScript (via roblox-ts). It's available f # wally.toml [dependencies] -ColourUtils = "csqrl/colour-utils@^1.1.0" +ColorUtils = "csqrl/colour-utils@X.X.X" ``` ```sh -$ wally install +wally install ``` ### TypeScript -Install the [`@rbxts/colour-utils`][npm] package using npm or yarn. +Install the [`@rbxts/color-utils`][npm] package using npm or yarn. ```sh -$ npm i @rbxts/colour-utils -$ yarn add @rbxts/colour-utils +npm i @rbxts/color-utils +yarn add @rbxts/color-utils ``` ### Manual Installation -Grab a copy [from the Roblox Library (Toolbox)][library], or download the latest `.rbxm` file from [the releases page][releases] and drop it into Studio. +Grab a copy [from the Roblox Library (Toolbox)][library], or download the latest +`.rbxm` file from [the releases page][releases] and drop it into Studio. diff --git a/aftman.toml b/aftman.toml new file mode 100644 index 0000000..f8924e8 --- /dev/null +++ b/aftman.toml @@ -0,0 +1,7 @@ +[tools] +rojo = "rojo-rbx/rojo@7.3.0" +run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" +wally = "upliftgames/wally@0.3.2" +selene = "kampfkarren/selene@0.25.0" +stylua = "johnnymorganz/stylua@0.18.0" +luau-lsp = "johnnymorganz/luau-lsp@1.22.0" diff --git a/foreman.toml b/foreman.toml deleted file mode 100644 index 82852bb..0000000 --- a/foreman.toml +++ /dev/null @@ -1,6 +0,0 @@ -[tools] -rojo = { source = "rojo-rbx/rojo", version = "=7.0.0" } -run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "=0.3.0" } -wally = { source = "upliftgames/wally", version = "=0.3.1" } -selene = { source = "kampfkarren/selene", version = "=0.16.0" } -stylua = { source = "johnnymorganz/stylua", version = "=0.12.2" } diff --git a/moonwave.toml b/moonwave.toml index 17d2a16..a28cf5d 100644 --- a/moonwave.toml +++ b/moonwave.toml @@ -1,8 +1,8 @@ -title = "ColourUtils" +title = "ColorUtils" gitSourceBranch = "default" changelog = true -classOrder = ["ColourUtils"] +classOrder = ["ColorUtils"] [[navbar.items]] label = "Itch.io" diff --git a/package-lock.json b/package-lock.json index 6213ca7..cf57478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "@rbxts/colour-utils", - "version": "1.1.1", + "version": "1.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@rbxts/colour-utils", - "version": "1.1.1", + "version": "1.3.1", "license": "MIT", "devDependencies": { "@rbxts/compiler-types": "^1.2.3-types.0", "@rbxts/types": "^1.0.515", + "husky": "^8.0.0", "rbxts-transform-debug": "^1.0.0-rc.1", "rbxts-transform-env": "^1.0.0-rc.0", "roblox-ts": "^1.2.7", @@ -333,6 +334,21 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1075,6 +1091,12 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", diff --git a/package.json b/package.json index e5124fb..d66b75c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rbxts/colour-utils", - "version": "1.3.1", + "version": "1.4.1", "description": "Colour manipulation utility for Roblox", "homepage": "https://github.com/csqrl/colour-utils", "main": "src/init.lua", @@ -8,7 +8,8 @@ "scripts": { "build": "rbxtsc", "watch": "rbxtsc -w", - "prepublishOnly": "npm run build" + "prepublishOnly": "npm run build", + "prepare": "husky install" }, "types": "typings/index.d.ts", "files": [ @@ -33,6 +34,7 @@ "rbxts-transform-debug": "^1.0.0-rc.1", "rbxts-transform-env": "^1.0.0-rc.0", "typescript": "^4.3.5", - "roblox-ts": "^1.2.7" + "roblox-ts": "^1.2.7", + "husky": "^8.0.0" } } diff --git a/src/APCA/GetContrastRatio.lua b/src/APCA/GetContrastRatio.lua index 4f7910e..0ffc2ff 100644 --- a/src/APCA/GetContrastRatio.lua +++ b/src/APCA/GetContrastRatio.lua @@ -1,6 +1,6 @@ --[[ This is a Luau implementation of the APAC method of calculating the contrast - ratio between two colours. + ratio between two colors. This APAC method is based around a few different implementations: @@ -16,7 +16,7 @@ > Contrast by @cliambrown > https://github.com/cliambrown/contrast/blob/master/src/apca.js ]] -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local CONST = require(script.Parent.Const) local assertTypeOf = Assert.prepTypeOf("GetContrastRatioAPCA") @@ -27,10 +27,10 @@ local function ComputePower(value: number): number return value ^ CONST.SRGB_TRC end -local function ComputeY(colour: Color3): number - return ComputePower(colour.R) * CONST.RED_COEF - + ComputePower(colour.G) * CONST.GREEN_COEF - + ComputePower(colour.B) * CONST.BLUE_COEF +local function ComputeY(color: Color3): number + return ComputePower(color.R) * CONST.RED_COEF + + ComputePower(color.G) * CONST.GREEN_COEF + + ComputePower(color.B) * CONST.BLUE_COEF end local function SoftClampBlack(y: number): number @@ -41,8 +41,8 @@ end @function GetContrastRatio @within APCA - @param foreground Color3 -- The foreground colour. - @param background Color3 -- The background colour. + @param foreground Color3 -- The foreground color. + @param background Color3 -- The background color. @return number -- The contrast ratio [≈-100-100]. ]=] local function GetContrastRatio(foreground: Color3, background: Color3): number @@ -64,14 +64,14 @@ local function GetContrastRatio(foreground: Color3, background: Color3): number outputContrast = if sapc < CONST.LOW_CLIP then 0 - elseif sapc < CONST.LOW_BOW_THRS then sapc - sapc * CONST.LOW_BOW_FACTOR * CONST.LOW_BOW_OFFS + elseif sapc < CONST.LOW_BOW_THRS then sapc - sapc * CONST.LOW_BOW_FACT * CONST.LOW_BOW_OFFS else sapc - CONST.LOW_BOW_OFFS else sapc = (bgY ^ CONST.REV_BG_EXP - fgY ^ CONST.REV_FG_EXP) * CONST.SCALE_WOB outputContrast = if sapc > -CONST.LOW_CLIP then 0 - elseif sapc > -CONST.LOW_WOB_THRS then sapc - sapc * CONST.LOW_WOB_FACTOR * CONST.LOW_WOB_OFFS + elseif sapc > -CONST.LOW_WOB_THRS then sapc - sapc * CONST.LOW_WOB_FACT * CONST.LOW_WOB_OFFS else sapc + CONST.LOW_WOB_OFFS end diff --git a/src/Blend/Burn.lua b/src/Blend/Burn.lua index 2a85e3b..f2a5802 100644 --- a/src/Blend/Burn.lua +++ b/src/Blend/Burn.lua @@ -8,9 +8,9 @@ local max = math.max @function Burn @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. - @return Color3 -- The resulting colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. + @return Color3 -- The resulting color. ]=] return PrepFilter("Burn", function(background: number, foreground: number): number local bg = clamp(background * 255, 0, 255) diff --git a/src/Blend/Burn.spec.lua b/src/Blend/Burn.spec.lua index 13ba3d6..5c64ac4 100644 --- a/src/Blend/Burn.spec.lua +++ b/src/Blend/Burn.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Burn) diff --git a/src/Blend/Dodge.lua b/src/Blend/Dodge.lua index ad5b483..6159cc4 100644 --- a/src/Blend/Dodge.lua +++ b/src/Blend/Dodge.lua @@ -8,9 +8,9 @@ local min = math.min @function Dodge @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. - @return Color3 -- The resulting colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. + @return Color3 -- The resulting color. ]=] return PrepFilter("Dodge", function(background: number, foreground: number): number local bg = clamp(background * 255, 0, 255) diff --git a/src/Blend/Dodge.spec.lua b/src/Blend/Dodge.spec.lua index e1da504..3612d8b 100644 --- a/src/Blend/Dodge.spec.lua +++ b/src/Blend/Dodge.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Dodge) diff --git a/src/Blend/Multiply.lua b/src/Blend/Multiply.lua index 7fa20e2..63584ed 100644 --- a/src/Blend/Multiply.lua +++ b/src/Blend/Multiply.lua @@ -4,9 +4,9 @@ local PrepFilter = require(script.Parent._Filter) @function Multiply @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. - @return Color3 -- The resulting colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. + @return Color3 -- The resulting color. ]=] return PrepFilter("Multiply", function(background: number, foreground: number): number return ((foreground * 255) * (background * 255)) / 255 diff --git a/src/Blend/Multiply.spec.lua b/src/Blend/Multiply.spec.lua index d436c28..e677e1d 100644 --- a/src/Blend/Multiply.spec.lua +++ b/src/Blend/Multiply.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Multiply) diff --git a/src/Blend/Overlay.lua b/src/Blend/Overlay.lua index 848a6bd..76b9722 100644 --- a/src/Blend/Overlay.lua +++ b/src/Blend/Overlay.lua @@ -4,9 +4,9 @@ local PrepFilter = require(script.Parent._Filter) @function Overlay @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. - @return Color3 -- The resulting colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. + @return Color3 -- The resulting color. ]=] return PrepFilter("Overlay", function(background: number, foreground: number): number local bg = background * 255 diff --git a/src/Blend/Overlay.spec.lua b/src/Blend/Overlay.spec.lua index ade9f8b..a9edb88 100644 --- a/src/Blend/Overlay.spec.lua +++ b/src/Blend/Overlay.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Overlay) diff --git a/src/Blend/Screen.lua b/src/Blend/Screen.lua index 209d26f..69c0d7f 100644 --- a/src/Blend/Screen.lua +++ b/src/Blend/Screen.lua @@ -5,9 +5,9 @@ local rshift = bit32.rshift @function Screen @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. - @return Color3 -- The resulting colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. + @return Color3 -- The resulting color. ]=] return PrepFilter("Screen", function(background: number, foreground: number): number return 255 - rshift(((255 - (foreground * 255)) * (255 - (background * 255))), 8) diff --git a/src/Blend/Screen.spec.lua b/src/Blend/Screen.spec.lua index 2aedb76..d83261e 100644 --- a/src/Blend/Screen.spec.lua +++ b/src/Blend/Screen.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Screen) diff --git a/src/Blend/Transparency.lua b/src/Blend/Transparency.lua index 46e6000..0529408 100644 --- a/src/Blend/Transparency.lua +++ b/src/Blend/Transparency.lua @@ -2,10 +2,10 @@ @function Transparency @within Blend - @param background Color3 -- The background colour. - @param foreground Color3 -- The foreground colour. + @param background Color3 -- The background color. + @param foreground Color3 -- The foreground color. @param transparency number -- The transparency value. - @return Color3 -- The resulting colour. + @return Color3 -- The resulting color. ]=] local function applyTransparency(background: Color3, foreground: Color3, transparency: number): Color3 local alpha = 1 - transparency diff --git a/src/Blend/Transparency.spec.lua b/src/Blend/Transparency.spec.lua index ef38542..b54a4d4 100644 --- a/src/Blend/Transparency.spec.lua +++ b/src/Blend/Transparency.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Filter = require(script.Parent.Transparency) diff --git a/src/Blend/_Filter.lua b/src/Blend/_Filter.lua index f25f268..506a073 100644 --- a/src/Blend/_Filter.lua +++ b/src/Blend/_Filter.lua @@ -1,5 +1,5 @@ -local ClampColour = require(script.Parent.Parent._Util.ClampColour) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) +local ClampColor = require(script.Parent.Parent.Util.ClampColor) return function(filterName: string, applyFilter: (number, number) -> number): (Color3, Color3) -> Color3 local assertTypeOf = Assert.prepTypeOf(filterName) @@ -8,12 +8,12 @@ return function(filterName: string, applyFilter: (number, number) -> number): (C assertTypeOf("background", "Color3", background) assertTypeOf("foreground", "Color3", foreground) - local newColour = Color3.fromRGB( + local newColor = Color3.fromRGB( applyFilter(background.R, foreground.R), applyFilter(background.G, foreground.G), applyFilter(background.B, foreground.B) ) - return ClampColour(newColour) + return ClampColor(newColor) end end diff --git a/src/Blind/Enum.lua b/src/Blind/Enum.lua index deabe60..92aaa79 100644 --- a/src/Blind/Enum.lua +++ b/src/Blind/Enum.lua @@ -1,35 +1,35 @@ --[=[ @interface Enums @within Blind - .Blind Blind -- Types of colour blindness. - .Group Group -- Colour blindness groups. + .Blind Blind -- Types of color blindness. + .Group Group -- Color blindness groups. ]=] --[=[ @interface Blind @tag Enum @within Blind - .Trichromacy 0 -- No colour blindness. + .Trichromacy 0 -- No color blindness. .Protanopia 1 -- Red blind. .Protanomaly 2 -- Red deficient. .Deuteranopia 3 -- Green blind. .Deuteranomaly 4 -- Green deficient. .Tritanopia 5 -- Blue blind. .Tritanomaly 6 -- Blue deficient. - .Achromatopsia 7 -- All colours are absent. - .Achromatomaly 8 -- All colours are deficient. + .Achromatopsia 7 -- All colors are absent. + .Achromatomaly 8 -- All colors are deficient. - .None 0 -- Trichromacy (no colour blindness). + .None 0 -- Trichromacy (no color blindness). .NoRed 1 -- Protanopia (red blind). .LowRed 2 -- Protanomaly (red deficient). .NoGreen 3 -- Deuteranopia (green blind). .LowGreen 4 -- Deuteranomaly (green deficient). .NoBlue 5 -- Tritanopia (blue blind). .LowBlue 6 -- Tritanomaly (blue deficient). - .NoColour 7 -- Achromatopsia (totally colour blind). - .LowColour 8 -- Achromatomaly (colour deficient). + .NoColor 7 -- Achromatopsia (totally color blind). + .LowColor 8 -- Achromatomaly (color deficient). - The Blind enum is used to represent the different types of colour blindness. It + The Blind enum is used to represent the different types of color blindness. It features a number of aliases for non-scientists. ]=] @@ -37,15 +37,15 @@ @interface Group @tag Enum @within Blind - .Trichroma 0 -- Trichromacy (no colour blindness). + .Trichroma 0 -- Trichromacy (no color blindness). .Protan 1 -- Protanopia/Protanomaly. .Deutan 2 -- Deuteranopia/Deuteranomaly. .Tritan 3 -- Tritanopia/Tritanomaly. .Achroma 4 -- Achromatopsia/Achromatomaly. - The Group enum is used to represent the different groups of colour blindness. + The Group enum is used to represent the different groups of color blindness. It is used internally by the [Simulate](#Simulate) method to determine which - colour blindness simulation to use. It is unlikely that you will need to + color blindness simulation to use. It is unlikely that you will need to use this enum. ]=] local Enums = { @@ -74,11 +74,11 @@ Enums.Blind.None = Enums.Blind.Trichromacy Enums.Blind.LowRed = Enums.Blind.Protanomaly Enums.Blind.LowGreen = Enums.Blind.Deuteranomaly Enums.Blind.LowBlue = Enums.Blind.Tritanomaly -Enums.Blind.LowColour = Enums.Blind.Achromatomaly +Enums.Blind.LowColor = Enums.Blind.Achromatomaly Enums.Blind.NoRed = Enums.Blind.Protanopia Enums.Blind.NoGreen = Enums.Blind.Deuteranopia Enums.Blind.NoBlue = Enums.Blind.Tritanopia -Enums.Blind.NoColour = Enums.Blind.Achromatopsia +Enums.Blind.NoColor = Enums.Blind.Achromatopsia return Enums diff --git a/src/Blind/Simulate/init.lua b/src/Blind/Simulate/init.lua index 584ac6c..2dcd14a 100644 --- a/src/Blind/Simulate/init.lua +++ b/src/Blind/Simulate/init.lua @@ -4,7 +4,7 @@ > https://github.com/skratchdot/color-blind/blob/master/lib/blind.js - The `colour-utils` adaptation is ported for use within Roblox's Luau library, + The `color-utils` adaptation is ported for use within Roblox's Luau library, but also contains TypeScript bindings for those using roblox-ts. ]] @@ -14,15 +14,15 @@ type VectorXyY = { Y: number, } -local Enums = require(script.Parent.Enum) local Configs = require(script.Configs) +local Enums = require(script.Parent.Enum) -local function RGBtoXYZ(colour: Color3): Vector3 +local function RGBtoXYZ(color: Color3): Vector3 local M = Configs.Matrix.RGB_XYZ - local r = colour.R - local g = colour.G - local b = colour.B + local r = color.R + local g = color.G + local b = color.B r = if r > 0.04 then ((r + 0.055) / 1.055) ^ 2.4 else r / 12.92 g = if g > 0.04 then ((g + 0.055) / 1.055) ^ 2.4 else g / 12.92 @@ -65,34 +65,34 @@ end @function Simulate @within Blind - @param colour Color3 -- The colour to simulate. + @param color Color3 -- The color to simulate. @param blinder Blind -- The blinder to simulate with. - @return Color3 -- The simulated colour. + @return Color3 -- The simulated color. ]=] -local function SimulateBlinder(colour: Color3, blinder: number): Color3 - assert(typeof(colour) == "Color3", "Colour must be a Color3") +local function SimulateBlinder(color: Color3, blinder: number): Color3 + assert(typeof(color) == "Color3", "Color must be a Color3") assert(typeof(blinder) == "number", "Blinder must be a number (see Enums.Blind)") local group = Configs.Groups[blinder] local anomalise = Configs.Anomalised[blinder] if group == Enums.Group.Trichroma then - return colour + return color end if group == Enums.Group.Achroma then - local val = colour.R * 0.213 + colour.G * 0.715 + colour.B * 0.072 + local val = color.R * 0.213 + color.G * 0.715 + color.B * 0.072 local blinded = Color3.new(val, val, val) if anomalise then - return Anomalise(colour, blinded) + return Anomalise(color, blinded) end return blinded end local line = Configs.Blinder[group] - local xyy = XYZtoXyY(RGBtoXYZ(colour)) + local xyy = XYZtoXyY(RGBtoXYZ(color)) local slope = (xyy.y - line.Y) / (xyy.X - line.X) local yi = xyy.y - xyy.X * slope @@ -148,7 +148,7 @@ local function SimulateBlinder(colour: Color3, blinder: number): Color3 local blinded = Color3.fromRGB(vector.R or 0, vector.G or 0, vector.B or 0) if anomalise then - return Anomalise(colour, blinded) + return Anomalise(color, blinded) end return blinded diff --git a/src/Blind/Simulate/init.spec.lua b/src/Blind/Simulate/init.spec.lua index c6a9178..ad7a1ce 100644 --- a/src/Blind/Simulate/init.spec.lua +++ b/src/Blind/Simulate/init.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Parent.Util.BasicallyIdentical) local Enums = require(script.Parent.Parent.Enum) local BLIND_NAMES = { @@ -16,10 +16,10 @@ local BLIND_NAMES = { return function() local Simulate = require(script.Parent) - local TEST_COLOUR = Color3.fromHex("00a2ff") + local TEST_COLOR = Color3.fromHex("00a2ff") - local EXPECT_COLOURS = { - [Enums.Blind.Trichromacy] = TEST_COLOUR, + local EXPECT_COLORS = { + [Enums.Blind.Trichromacy] = TEST_COLOR, [Enums.Blind.Protanomaly] = Color3.fromHex("499bfa"), [Enums.Blind.Protanopia] = Color3.fromHex("7397f7"), [Enums.Blind.Deuteranomaly] = Color3.fromHex("349eff"), @@ -37,13 +37,13 @@ return function() end) it("returns a Color3", function() - local result = Simulate(TEST_COLOUR, Enums.Blind.Trichromacy) - expect(BasicallyIdentical(TEST_COLOUR, result)).to.equal(true) + local result = Simulate(TEST_COLOR, Enums.Blind.Trichromacy) + expect(BasicallyIdentical(TEST_COLOR, result)).to.equal(true) end) - for blinder, expected in pairs(EXPECT_COLOURS) do + for blinder, expected in pairs(EXPECT_COLORS) do it("correctly simulates " .. BLIND_NAMES[blinder]:lower() .. " against expected output", function() - local result = Simulate(TEST_COLOUR, blinder) + local result = Simulate(TEST_COLOR, blinder) expect(BasicallyIdentical(expected, result)).to.equal(true) end) end diff --git a/src/Darken.lua b/src/Darken.lua index 5ad440f..16ffe22 100644 --- a/src/Darken.lua +++ b/src/Darken.lua @@ -1,19 +1,19 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("Darken") -local clampColour = require(script.Parent._Util.ClampColour) +local clampColor = require(script.Parent.Util.ClampColor) --[=[ @function Darken - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to darken. + @param color Color3 -- The color to darken. @param coefficient number -- The amount to darken by [0-1]. - @return Color3 -- The darkened colour. + @return Color3 -- The darkened color. ]=] -return function(colour: Color3, coefficient: number): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3, coefficient: number): Color3 + assertTypeOf("color", "Color3", color) assertTypeOf("coefficient", "number", coefficient) - return clampColour(colour:Lerp(Color3.new(), coefficient)) + return clampColor(color:Lerp(Color3.new(), coefficient)) end diff --git a/src/Darken.spec.lua b/src/Darken.spec.lua index d4cc904..b15ff3d 100644 --- a/src/Darken.spec.lua +++ b/src/Darken.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Darken = require(script.Parent.Darken) @@ -8,37 +8,37 @@ return function() end) it("doesn't modify black", function() - local colour = Darken(Color3.new(), 0.1) - expect(BasicallyIdentical(Color3.new(), colour)).to.equal(true) + local color = Darken(Color3.new(), 0.1) + expect(BasicallyIdentical(Color3.new(), color)).to.equal(true) end) it("doesn't overshoot if an above-range coefficient is supplied", function() - local colour = Darken(Color3.new(0, 0.5, 1), 1.5) - expect(BasicallyIdentical(Color3.new(), colour)).to.equal(true) + local color = Darken(Color3.new(0, 0.5, 1), 1.5) + expect(BasicallyIdentical(Color3.new(), color)).to.equal(true) end) it("doesn't overshoot if a below-range coefficient is supplied", function() - local colour = Darken(Color3.new(0, 0.5, 1), -1.5) - expect(BasicallyIdentical(Color3.new(0, 1, 1), colour)).to.equal(true) + local color = Darken(Color3.new(0, 0.5, 1), -1.5) + expect(BasicallyIdentical(Color3.new(0, 1, 1), color)).to.equal(true) end) it("darkens white by 10% when coefficient is 0.1", function() - local colour = Darken(Color3.new(1, 1, 1), 0.1) - expect(BasicallyIdentical(Color3.new(0.9, 0.9, 0.9), colour)).to.equal(true) + local color = Darken(Color3.new(1, 1, 1), 0.1) + expect(BasicallyIdentical(Color3.new(0.9, 0.9, 0.9), color)).to.equal(true) end) it("darkens red by 50% when coefficient is 0.5", function() - local colour = Darken(Color3.new(1, 0, 0), 0.5) - expect(BasicallyIdentical(Color3.new(0.5, 0, 0), colour)).to.equal(true) + local color = Darken(Color3.new(1, 0, 0), 0.5) + expect(BasicallyIdentical(Color3.new(0.5, 0, 0), color)).to.equal(true) end) it("darkens grey by 50% when coefficient is 0.5", function() - local colour = Darken(Color3.new(0.5, 0.5, 0.5), 0.5) - expect(BasicallyIdentical(Color3.new(0.25, 0.25, 0.25), colour)).to.equal(true) + local color = Darken(Color3.new(0.5, 0.5, 0.5), 0.5) + expect(BasicallyIdentical(Color3.new(0.25, 0.25, 0.25), color)).to.equal(true) end) - it("doesn't modify colours when coefficient is 0", function() - local colour = Darken(Color3.new(1, 1, 1), 0) - expect(BasicallyIdentical(Color3.new(1, 1, 1), colour)).to.equal(true) + it("doesn't modify colors when coefficient is 0", function() + local color = Darken(Color3.new(1, 1, 1), 0) + expect(BasicallyIdentical(Color3.new(1, 1, 1), color)).to.equal(true) end) end diff --git a/src/Desaturate.lua b/src/Desaturate.lua index 7f9d522..111ade2 100644 --- a/src/Desaturate.lua +++ b/src/Desaturate.lua @@ -1,19 +1,19 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local Saturate = require(script.Parent.Saturate) local assertTypeOf = Assert.prepTypeOf("Saturate") --[=[ @function Desaturate - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to desaturate. + @param color Color3 -- The color to desaturate. @param coefficient number -- The coefficient to desaturate by [0-1]. - @return Color3 -- The desaturated colour. + @return Color3 -- The desaturated color. ]=] -return function(colour: Color3, coefficient: number): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3, coefficient: number): Color3 + assertTypeOf("color", "Color3", color) assertTypeOf("coefficient", "number", coefficient) - return Saturate(colour, -coefficient) + return Saturate(color, -coefficient) end diff --git a/src/Desaturate.spec.lua b/src/Desaturate.spec.lua index 331aae4..ec999e9 100644 --- a/src/Desaturate.spec.lua +++ b/src/Desaturate.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Desaturate = require(script.Parent.Desaturate) @@ -7,10 +7,10 @@ return function() local TEST_RESULT = Color3.fromHex("#80d0ff") local TEST_AMOUNT = 0.5 - it("should desaturate a colour", function() - local colour = Desaturate(TEST_BASE, TEST_AMOUNT) + it("should desaturate a color", function() + local color = Desaturate(TEST_BASE, TEST_AMOUNT) - expect(BasicallyIdentical(TEST_RESULT, colour)).to.equal(true) + expect(BasicallyIdentical(TEST_RESULT, color)).to.equal(true) end) it("throws if argument is not a Color3", function() diff --git a/src/Emphasise.lua b/src/Emphasise.lua deleted file mode 100644 index 28fdb58..0000000 --- a/src/Emphasise.lua +++ /dev/null @@ -1,23 +0,0 @@ -local GetLuminance = require(script.Parent.GetLuminance) -local Lighten = require(script.Parent.Lighten) -local Darken = require(script.Parent.Darken) - ---[=[ - @function Emphasise - @within ColourUtils - - :::tip - - Emphasise is also available under the `Emphasize` alias. - - ::: - - @param colour Color3 -- The colour to emphasise. - @param coefficient number -- The amount to emphasise by [0-1]. - @param threshold? number -- The threshold for light/dark [0-1] (defaults to 0.5). - @return Color3 -- The emphasised colour. -]=] -return function(colour: Color3, coefficient: number, threshold: number?): Color3 - threshold = type(threshold) == "number" and threshold or 0.5 - return GetLuminance(colour) > threshold and Darken(colour, coefficient) or Lighten(colour, coefficient) -end diff --git a/src/Emphasise.spec.lua b/src/Emphasise.spec.lua deleted file mode 100644 index 3e44639..0000000 --- a/src/Emphasise.spec.lua +++ /dev/null @@ -1,27 +0,0 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) - -return function() - local Emphasise = require(script.Parent.Emphasise) - local Lighten = require(script.Parent.Lighten) - local Darken = require(script.Parent.Darken) - - it("lightens a dark colour with the coefficient provided", function() - local colour = Color3.fromRGB(1, 2, 3) - expect(BasicallyIdentical(Emphasise(colour, 0.4), Lighten(colour, 0.4))).to.equal(true) - end) - - it("darkens a light colour with the coefficient provided", function() - local colour = Color3.fromRGB(250, 240, 230) - expect(BasicallyIdentical(Emphasise(colour, 0.3), Darken(colour, 0.3))).to.equal(true) - end) - - it("lightens a light colour with a high threshold", function() - local colour = Color3.fromRGB(230, 220, 210) - expect(BasicallyIdentical(Emphasise(colour, 0.1, 0.9), Lighten(colour, 0.1))).to.equal(true) - end) - - it("darkens a dark colour with a low threshold", function() - local colour = Color3.new(0.2, 0.2, 0.2) - expect(BasicallyIdentical(Emphasise(colour, 0.1, 0.01), Darken(colour, 0.1))).to.equal(true) - end) -end diff --git a/src/Emphasize.lua b/src/Emphasize.lua new file mode 100644 index 0000000..b87ecb6 --- /dev/null +++ b/src/Emphasize.lua @@ -0,0 +1,17 @@ +local Darken = require(script.Parent.Darken) +local GetLuminance = require(script.Parent.GetLuminance) +local Lighten = require(script.Parent.Lighten) + +--[=[ + @function Emphasize + @within ColorUtils + + @param color Color3 -- The color to emphasize. + @param coefficient number -- The amount to emphasize by [0-1]. + @param threshold? number -- The threshold for light/dark [0-1] (defaults to 0.5). + @return Color3 -- The emphasized color. +]=] +return function(color: Color3, coefficient: number, threshold: number?): Color3 + threshold = type(threshold) == "number" and threshold or 0.5 + return GetLuminance(color) > threshold and Darken(color, coefficient) or Lighten(color, coefficient) +end diff --git a/src/Emphasize.spec.lua b/src/Emphasize.spec.lua new file mode 100644 index 0000000..2d45c59 --- /dev/null +++ b/src/Emphasize.spec.lua @@ -0,0 +1,27 @@ +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) + +return function() + local Emphasize = require(script.Parent.Emphasize) + local Lighten = require(script.Parent.Lighten) + local Darken = require(script.Parent.Darken) + + it("lightens a dark color with the coefficient provided", function() + local color = Color3.fromRGB(1, 2, 3) + expect(BasicallyIdentical(Emphasize(color, 0.4), Lighten(color, 0.4))).to.equal(true) + end) + + it("darkens a light color with the coefficient provided", function() + local color = Color3.fromRGB(250, 240, 230) + expect(BasicallyIdentical(Emphasize(color, 0.3), Darken(color, 0.3))).to.equal(true) + end) + + it("lightens a light color with a high threshold", function() + local color = Color3.fromRGB(230, 220, 210) + expect(BasicallyIdentical(Emphasize(color, 0.1, 0.9), Lighten(color, 0.1))).to.equal(true) + end) + + it("darkens a dark color with a low threshold", function() + local color = Color3.new(0.2, 0.2, 0.2) + expect(BasicallyIdentical(Emphasize(color, 0.1, 0.01), Darken(color, 0.1))).to.equal(true) + end) +end diff --git a/src/GetContrastRatio.lua b/src/GetContrastRatio.lua deleted file mode 100644 index 400dcf3..0000000 --- a/src/GetContrastRatio.lua +++ /dev/null @@ -1,20 +0,0 @@ -local targetModule = script.Parent.WCAG.GetContrastRatio -local module = require(targetModule) - ---[=[ - @function GetContrastRatio - @within ColourUtils - - :::caution - - GetContrastRatio is now redirected to [WCAG.GetContrastRatio]. You should directly - use the WCAG module in newer work. This redirect is for backwards compatibility, and may be - removed or changed in future versions. - - ::: - - @param foreground Color3 -- The foreground colour. - @param background Color3 -- The background colour. - @return number -- The contrast ratio [0-21]. -]=] -return module diff --git a/src/GetContrastRatioCompat.lua b/src/GetContrastRatioCompat.lua new file mode 100644 index 0000000..465874b --- /dev/null +++ b/src/GetContrastRatioCompat.lua @@ -0,0 +1,18 @@ +local getContrastRatio = require(script.Parent.APCA.GetContrastRatio) +local didWarnAPCA = false + +local function getContrastRatioCompat(foreground: Color3, background: Color3): number + local contrastRatio = math.abs(getContrastRatio(foreground, background)) + + if not didWarnAPCA then + didWarnAPCA = true + + warn( + "ColorUtils.GetContrastRatio is providing a compatibility layer for APCA.GetContrastRatio. To continue using the old behavior, use WCAG.GetContrastRatio instead." + ) + end + + return (contrastRatio / 100) * 21 +end + +return getContrastRatioCompat diff --git a/src/GetContrastingColour.lua b/src/GetContrastingColour.lua deleted file mode 100644 index d245906..0000000 --- a/src/GetContrastingColour.lua +++ /dev/null @@ -1,28 +0,0 @@ -local targetModule = script.Parent.WCAG.GetContrastingColour -local module = require(targetModule) - ---[=[ - @function GetContrastingColour - @within ColourUtils - - :::caution - - GetContrastingColour is now redirected to [WCAG.GetContrastingColour]. You should directly - use the WCAG module in newer work. This redirect is for backwards compatibility, and may be - removed or changed in future versions. - - ::: - - :::tip - - GetContrastingColour is also available under the `GetContrastingColor` alias. - This **does not** apply to the WCAG and APCA submodules! - - ::: - - @param foreground Color3 -- The foreground colour. - @param background Color3 -- The background colour. - @param ratio? number -- The ratio to check against [0-1] (defaults to 4.5). - @return Color3 -- The contrasting colour. -]=] -return module diff --git a/src/GetLuminance.lua b/src/GetLuminance.lua index bae29f8..cb32759 100644 --- a/src/GetLuminance.lua +++ b/src/GetLuminance.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("GetLuminance") @@ -8,17 +8,17 @@ end --[=[ @function GetLuminance - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to get the luminance of. - @return number -- The luminance of the colour [0-1]. + @param color Color3 -- The color to get the luminance of. + @return number -- The luminance of the color [0-1]. ]=] -return function(colour: Color3): number - assertTypeOf("colour", "Color3", colour) +return function(color: Color3): number + assertTypeOf("color", "Color3", color) - local red = transformValue(colour.R) - local green = transformValue(colour.G) - local blue = transformValue(colour.B) + local red = transformValue(color.R) + local green = transformValue(color.G) + local blue = transformValue(color.B) local lum = 0.2126 * red + 0.7152 * green + 0.0722 * blue diff --git a/src/GetPerceivedBrightness.lua b/src/GetPerceivedBrightness.lua index 8bbace4..188a784 100644 --- a/src/GetPerceivedBrightness.lua +++ b/src/GetPerceivedBrightness.lua @@ -1,20 +1,20 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("GetPerceivedBrightness") --[=[ @function GetPerceivedBrightness - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to get the perceived brightness of. - @return number -- The perceived brightness of the colour [0-1]. + @param color Color3 -- The color to get the perceived brightness of. + @return number -- The perceived brightness of the color [0-1]. ]=] -return function(colour: Color3): number - assertTypeOf("colour", "Color3", colour) +return function(color: Color3): number + assertTypeOf("color", "Color3", color) - local red = colour.R * 255 - local green = colour.G * 255 - local blue = colour.B * 255 + local red = color.R * 255 + local green = color.G * 255 + local blue = color.B * 255 local bright = ((red * 299 + green * 587 + blue * 114) / 1000) / 255 diff --git a/src/HSL/init.lua b/src/HSL/init.lua index 248bf18..6d4f323 100644 --- a/src/HSL/init.lua +++ b/src/HSL/init.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local round = math.round local floor = math.floor @@ -24,14 +24,14 @@ export type HSL = { @function toHSL @within HSL - @param colour Color3 -- The colour to convert. - @return HSL -- The HSL representation of the colour. + @param color Color3 -- The color to convert. + @return HSL -- The HSL representation of the color. ]=] -local function ToHSL(colour: Color3): HSL - Assert.typeOf("ToHSL", "colour", "Color3", colour) +local function ToHSL(color: Color3): HSL + Assert.typeOf("ToHSL", "color", "Color3", color) - local channelMin = min(colour.R, colour.G, colour.B) - local channelMax = max(colour.R, colour.G, colour.B) + local channelMin = min(color.R, color.G, color.B) + local channelMax = max(color.R, color.G, color.B) local delta = channelMax - channelMin local hue = 0 @@ -40,12 +40,12 @@ local function ToHSL(colour: Color3): HSL if delta == 0 then hue = 0 - elseif channelMax == colour.R then - hue = ((colour.G - colour.B) / delta) % 6 - elseif channelMax == colour.G then - hue = (colour.B - colour.R) / delta + 2 + elseif channelMax == color.R then + hue = ((color.G - color.B) / delta) % 6 + elseif channelMax == color.G then + hue = (color.B - color.R) / delta + 2 else - hue = (colour.R - colour.G) / delta + 4 + hue = (color.R - color.G) / delta + 4 end hue = round(hue * 60) @@ -68,7 +68,7 @@ end @function fromHSL @within HSL - @param hsl HSL -- The HSL colour to convert. + @param hsl HSL -- The HSL color to convert. @return Color3 -- The resulting Color3. ]=] local function FromHSL(hsl: HSL): Color3 diff --git a/src/HSL/init.spec.lua b/src/HSL/init.spec.lua index 829a4db..f56ad5d 100644 --- a/src/HSL/init.spec.lua +++ b/src/HSL/init.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local HSL = require(script.Parent) diff --git a/src/Hex/init.lua b/src/Hex/init.lua index fd3adb6..11fdaad 100644 --- a/src/Hex/init.lua +++ b/src/Hex/init.lua @@ -1,5 +1,5 @@ -local Assert = require(script.Parent._Util.Assert) -local ClampColour = require(script.Parent._Util.ClampColour) +local Assert = require(script.Parent.Util.Assert) +local ClampColor = require(script.Parent.Util.ClampColor) local Transparency = require(script.Parent.Blend.Transparency) local sub = string.sub @@ -10,7 +10,7 @@ local split = string.split local HEX_EXCLUDE_PATTERN = "[^A-Fa-f0-9]" local HEX_FORMAT_PATTERN = "%.2x%.2x%.2x" -local BACKGROUND_BASE_COLOUR = Color3.new() +local BACKGROUND_BASE_COLOR = Color3.new() --[=[ @function fromHex @@ -49,7 +49,7 @@ local function FromHex(hex: string): Color3 local green = tonumber(sub(hex, 3, 4), 16) local blue = tonumber(sub(hex, 5, 6), 16) - return ClampColour(Color3.fromRGB(red, green, blue)) + return ClampColor(Color3.fromRGB(red, green, blue)) end --[=[ @@ -58,7 +58,7 @@ end Creates a Color3 from a hex string with an alpha value. The background doesn't need to be specified, but the resulting Color3 will vary - depending on the colour of the background, so it's recommended to + depending on the color of the background, so it's recommended to specify a background unless `Color3.new()` is what you want. If the hex string is less than 8 characters, it will be passed to @@ -70,7 +70,7 @@ end last two characters will be used as the alpha value. @param hex string -- The hex string to convert. - @param background Color3? -- The background colour (defaults to black). + @param background Color3? -- The background color (defaults to black). @return Color3 -- The resulting Color3. ]=] local function FromHexRGBA(hex: string, background: Color3?): Color3 @@ -83,9 +83,9 @@ local function FromHexRGBA(hex: string, background: Color3?): Color3 end local transparency = 1 - (tonumber(sub(hex, -2), 16) / 255) - local colour = FromHex(sub(hex, 1, -3)) + local color = FromHex(sub(hex, 1, -3)) - return Transparency(colour, background or BACKGROUND_BASE_COLOUR, transparency) + return Transparency(color, background or BACKGROUND_BASE_COLOR, transparency) end --[=[ @@ -99,15 +99,15 @@ end ::: - @param colour Color3 -- The colour to convert. - @return string -- The hex representation of the colour. + @param color Color3 -- The color to convert. + @return string -- The hex representation of the color. ]=] -local function ToHex(colour: Color3): string - Assert.typeOf("ToHex", "colour", "Color3", colour) +local function ToHex(color: Color3): string + Assert.typeOf("ToHex", "color", "Color3", color) - local red = colour.R * 255 - local green = colour.G * 255 - local blue = colour.B * 255 + local red = color.R * 255 + local green = color.G * 255 + local blue = color.B * 255 local hex = fmt(HEX_FORMAT_PATTERN, red, green, blue) diff --git a/src/Hex/init.spec.lua b/src/Hex/init.spec.lua index d789dff..f2188d0 100644 --- a/src/Hex/init.spec.lua +++ b/src/Hex/init.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Hex = require(script.Parent) diff --git a/src/Int/init.lua b/src/Int/init.lua index 767d0b0..7048ce1 100644 --- a/src/Int/init.lua +++ b/src/Int/init.lua @@ -1,5 +1,5 @@ -local Assert = require(script.Parent._Util.Assert) -local ClampColour = require(script.Parent._Util.ClampColour) +local Assert = require(script.Parent.Util.Assert) +local ClampColor = require(script.Parent.Util.ClampColor) local floor = math.floor local rshift = bit32.rshift @@ -21,22 +21,22 @@ local function FromInt(int: number): Color3 local green = band(rshift(int, 8), 255) local blue = band(int, 255) - return ClampColour(Color3.fromRGB(red, green, blue)) + return ClampColor(Color3.fromRGB(red, green, blue)) end --[=[ @function toInt @within Int - @param colour Color3 -- The colour to convert. - @return number -- The integer representation of the colour. + @param color Color3 -- The color to convert. + @return number -- The integer representation of the color. ]=] -local function ToInt(colour: Color3): number - Assert.typeOf("ToInt", "colour", "Color3", colour) +local function ToInt(color: Color3): number + Assert.typeOf("ToInt", "color", "Color3", color) - local int = floor(colour.R * 255) - int = lshift(int, 8) + floor(colour.G * 255) - int = lshift(int, 8) + floor(colour.B * 255) + local int = floor(color.R * 255) + int = lshift(int, 8) + floor(color.G * 255) + int = lshift(int, 8) + floor(color.B * 255) return int end diff --git a/src/Int/init.spec.lua b/src/Int/init.spec.lua index 5f718be..c78db6e 100644 --- a/src/Int/init.spec.lua +++ b/src/Int/init.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Int = require(script.Parent) diff --git a/src/Invert.lua b/src/Invert.lua index b132199..349e4e1 100644 --- a/src/Invert.lua +++ b/src/Invert.lua @@ -1,18 +1,18 @@ -local ClampColour = require(script.Parent._Util.ClampColour) -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) +local ClampColor = require(script.Parent.Util.ClampColor) local assertTypeOf = Assert.prepTypeOf("Invert") --[=[ @function Invert - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to invert. - @return Color3 -- The inverted colour. + @param color Color3 -- The color to invert. + @return Color3 -- The inverted color. ]=] -return function(colour: Color3): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3): Color3 + assertTypeOf("color", "Color3", color) - local inverse = Color3.new(1 - colour.R, 1 - colour.G, 1 - colour.B) + local inverse = Color3.new(1 - color.R, 1 - color.G, 1 - color.B) - return ClampColour(inverse) + return ClampColor(inverse) end diff --git a/src/Invert.spec.lua b/src/Invert.spec.lua index cf25ad4..b81921e 100644 --- a/src/Invert.spec.lua +++ b/src/Invert.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Invert = require(script.Parent.Invert) diff --git a/src/LAB/FromLAB.lua b/src/LAB/FromLAB.lua index 485b826..f621cbd 100644 --- a/src/LAB/FromLAB.lua +++ b/src/LAB/FromLAB.lua @@ -1,5 +1,5 @@ -local Assert = require(script.Parent.Parent._Util.Assert) -local isNaN = require(script.Parent.Parent._Util.isNaN) +local Assert = require(script.Parent.Parent.Util.Assert) +local isNaN = require(script.Parent.Parent.Util.isNaN) local CONST = require(script.Parent.Constants) @@ -15,8 +15,8 @@ end @function fromLAB @within LAB - @param lab LAB -- The colour to convert. - @return Color3 -- The converted colour. + @param lab LAB -- The color to convert. + @return Color3 -- The converted color. ]=] local function FromLAB(lab: CONST.LAB): Color3 Assert.typeOf("FromLAB", "lab", "table", lab) diff --git a/src/LAB/FromLAB.spec.lua b/src/LAB/FromLAB.spec.lua index 91c9fdd..3bbbdc1 100644 --- a/src/LAB/FromLAB.spec.lua +++ b/src/LAB/FromLAB.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local FromLab = require(script.Parent.FromLAB) @@ -6,7 +6,7 @@ return function() local TEST_COLOR3 = Color3.fromHex("#00a2ff") local TEST_LAB = { L = 64.21, A = -1.67, B = -55.7 } - it("converts a LAB colour to a Color3", function() + it("converts a LAB color to a Color3", function() local color3 = FromLab(TEST_LAB) expect(BasicallyIdentical(color3, TEST_COLOR3)).to.equal(true) diff --git a/src/LAB/Lerp.lua b/src/LAB/Lerp.lua new file mode 100644 index 0000000..64bc718 --- /dev/null +++ b/src/LAB/Lerp.lua @@ -0,0 +1,31 @@ +--!strict +local convertFromLAB = require(script.Parent.FromLAB) +local convertToLAB = require(script.Parent.ToLAB) + +--[=[ + @function Lerp + @within LAB + + Interpolates between two Color3s using the CIELAB color space. + + @param from Color3 -- The color to interpolate from. + @param to Color3 -- The color to interpolate to. + @param alpha number -- The amount to interpolate by (typically between 0-1). + @return Color3 -- The resulting color. +]=] +local function lerp(from: Color3, to: Color3, alpha: number): Color3 + assert(typeof(from) == "Color3", `Lerp(...): Expected "from" to be a Color3, got {typeof(from)}`) + assert(typeof(to) == "Color3", `Lerp(...): Expected "to" to be a Color3, got {typeof(to)}`) + assert(typeof(alpha) == "number", `Lerp(...): Expected "alpha" to be a number, got {typeof(alpha)}`) + + local fromLAB = convertToLAB(from) + local toLAB = convertToLAB(to) + + local L = fromLAB.L * (1 - alpha) + toLAB.L * alpha + local A = fromLAB.A * (1 - alpha) + toLAB.A * alpha + local B = fromLAB.B * (1 - alpha) + toLAB.B * alpha + + return convertFromLAB({ L = L, A = A, B = B }) +end + +return lerp diff --git a/src/LAB/Lerp.spec.lua b/src/LAB/Lerp.spec.lua new file mode 100644 index 0000000..0c1d321 --- /dev/null +++ b/src/LAB/Lerp.spec.lua @@ -0,0 +1,33 @@ +local basicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) +local labLerp = require(script.Parent.Lerp) + +local START_COLOR3 = Color3.fromHex("#00a2ff") +local MID_COLOR3 = Color3.fromHex("#8ecea1") +local END_COLOR3 = Color3.fromHex("#a2ff00") + +return function() + it("lerps between two colors", function() + local lerp = labLerp(START_COLOR3, END_COLOR3, 0.5) + expect(basicallyIdentical(lerp, MID_COLOR3)).to.equal(true) + end) + + it("throws if argument is not a Color3", function() + expect(function() + labLerp(nil, END_COLOR3, 0.5) + end).to.throw() + + expect(function() + labLerp(START_COLOR3, nil, 0.5) + end).to.throw() + + expect(function() + labLerp(START_COLOR3, END_COLOR3, nil) + end).to.throw() + end) + + it("throws if alpha is not a number", function() + expect(function() + labLerp(START_COLOR3, END_COLOR3, "0.5") + end).to.throw() + end) +end diff --git a/src/LAB/ToLAB.lua b/src/LAB/ToLAB.lua index 565e692..0c240da 100644 --- a/src/LAB/ToLAB.lua +++ b/src/LAB/ToLAB.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local CONST = require(script.Parent.Constants) local function RGB_XYZ(value: number): number @@ -17,10 +17,10 @@ local function XYZ_LAB(value: number): number return value / CONST.t2 + CONST.t0 end -local function ToVector3(colour: Color3): Vector3 - local red = RGB_XYZ(colour.R) - local green = RGB_XYZ(colour.G) - local blue = RGB_XYZ(colour.B) +local function ToVector3(color: Color3): Vector3 + local red = RGB_XYZ(color.R) + local green = RGB_XYZ(color.G) + local blue = RGB_XYZ(color.B) return Vector3.new( XYZ_LAB((0.4124564 * red + 0.3575761 * green + 0.1804375 * blue) / CONST.Xn), @@ -33,13 +33,13 @@ end @function toLAB @within LAB - @param colour Color3 -- The colour to convert. - @return LAB -- The converted colour. + @param color Color3 -- The color to convert. + @return LAB -- The converted color. ]=] -local function ToLAB(colour: Color3): CONST.LAB - Assert.typeOf("ToLAB", "colour", "Color3", colour) +local function ToLAB(color: Color3): CONST.LAB + Assert.typeOf("ToLAB", "color", "Color3", color) - local vector = ToVector3(colour) + local vector = ToVector3(color) local l = 116 * vector.Y - 16 return { diff --git a/src/LAB/ToLAB.spec.lua b/src/LAB/ToLAB.spec.lua index c33fd62..fa65c63 100644 --- a/src/LAB/ToLAB.spec.lua +++ b/src/LAB/ToLAB.spec.lua @@ -4,7 +4,7 @@ return function() local TEST_COLOR3 = Color3.fromHex("#00a2ff") local TEST_LAB = { L = 64.21, A = -1.67, B = -55.7 } - it("converts a Color3 to a LAB colour", function() + it("converts a Color3 to a LAB color", function() local lab = ToLAB(TEST_COLOR3) expect(lab.L).to.be.near(TEST_LAB.L, 0.02) diff --git a/src/LAB/init.lua b/src/LAB/init.lua index d3f80dc..51a06e8 100644 --- a/src/LAB/init.lua +++ b/src/LAB/init.lua @@ -8,4 +8,5 @@ export type LAB = CONST.LAB return { fromLAB = require(script.FromLAB), toLAB = require(script.ToLAB), + Lerp = require(script.Lerp), } diff --git a/src/LCH/FromLCH.lua b/src/LCH/FromLCH.lua index efb901d..72b9646 100644 --- a/src/LCH/FromLCH.lua +++ b/src/LCH/FromLCH.lua @@ -1,8 +1,8 @@ -local Assert = require(script.Parent.Parent._Util.Assert) -local isNaN = require(script.Parent.Parent._Util.isNaN) +local Assert = require(script.Parent.Parent.Util.Assert) +local isNaN = require(script.Parent.Parent.Util.isNaN) -local LAB = require(script.Parent.Parent.LAB) local CONST = require(script.Parent.Constants) +local LAB = require(script.Parent.Parent.LAB) local sin = math.sin local cos = math.cos diff --git a/src/LCH/FromLCH.spec.lua b/src/LCH/FromLCH.spec.lua index f37f9c5..d7bd4d8 100644 --- a/src/LCH/FromLCH.spec.lua +++ b/src/LCH/FromLCH.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local FromLCH = require(script.Parent.FromLCH) @@ -6,7 +6,7 @@ return function() local TEST_COLOR3 = Color3.fromHex("#00a2ff") local TEST_LCH = { L = 64.2, C = 55.72, H = 268.27 } - it("converts a LCH colour to a Color3", function() + it("converts a LCH color to a Color3", function() local color3 = FromLCH(TEST_LCH) expect(BasicallyIdentical(TEST_COLOR3, color3)).to.equal(true) diff --git a/src/LCH/ToLCH.lua b/src/LCH/ToLCH.lua index 60bec21..1383ab3 100644 --- a/src/LCH/ToLCH.lua +++ b/src/LCH/ToLCH.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local LAB = require(script.Parent.Parent.LAB) local CONST = require(script.Parent.Constants) @@ -26,13 +26,13 @@ end @function toLCH @within LCH - @param colour Color3 -- The color to convert. + @param color Color3 -- The color to convert. @return LCH -- The converted color. ]=] -local function ToLCH(colour: Color3): CONST.LCH - Assert.typeOf("ToLCH", "colour", "Color3", colour) +local function ToLCH(color: Color3): CONST.LCH + Assert.typeOf("ToLCH", "color", "Color3", color) - local lab = LAB.toLAB(colour) + local lab = LAB.toLAB(color) return LABtoLCH(lab) end diff --git a/src/LCH/ToLCH.spec.lua b/src/LCH/ToLCH.spec.lua index b0f6a75..7d4ec86 100644 --- a/src/LCH/ToLCH.spec.lua +++ b/src/LCH/ToLCH.spec.lua @@ -4,7 +4,7 @@ return function() local TEST_COLOR3 = Color3.fromHex("#00a2ff") local TEST_LCH = { L = 64.2, C = 55.72, H = 268.27 } - it("converts a Color3 to a LCH colour", function() + it("converts a Color3 to a LCH color", function() local lch = ToLCH(TEST_COLOR3) expect(lch.L).to.be.near(TEST_LCH.L, 0.02) diff --git a/src/Lighten.lua b/src/Lighten.lua index 9934a64..6d95cb1 100644 --- a/src/Lighten.lua +++ b/src/Lighten.lua @@ -1,19 +1,19 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("Lighten") -local clampColour = require(script.Parent._Util.ClampColour) +local clampColor = require(script.Parent.Util.ClampColor) --[=[ @function Lighten - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to lighten. + @param color Color3 -- The color to lighten. @param coefficient number -- The amount to lighten by [0-1]. - @return Color3 -- The lightened colour. + @return Color3 -- The lightened color. ]=] -return function(colour: Color3, coefficient: number): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3, coefficient: number): Color3 + assertTypeOf("color", "Color3", color) assertTypeOf("coefficient", "number", coefficient) - return clampColour(colour:Lerp(Color3.new(1, 1, 1), coefficient)) + return clampColor(color:Lerp(Color3.new(1, 1, 1), coefficient)) end diff --git a/src/Lighten.spec.lua b/src/Lighten.spec.lua index 7f11e74..291595d 100644 --- a/src/Lighten.spec.lua +++ b/src/Lighten.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Lighten = require(script.Parent.Lighten) @@ -8,42 +8,42 @@ return function() end) it("doesn't modify white", function() - local colour = Lighten(Color3.new(1, 1, 1), 0.1) - expect(BasicallyIdentical(Color3.new(1, 1, 1), colour)).to.equal(true) + local color = Lighten(Color3.new(1, 1, 1), 0.1) + expect(BasicallyIdentical(Color3.new(1, 1, 1), color)).to.equal(true) end) it("doesn't overshoot if an above-range coefficient is supplied", function() - local colour = Lighten(Color3.new(0, 0.5, 1), 1.5) - expect(BasicallyIdentical(Color3.new(1, 1, 1), colour)).to.equal(true) + local color = Lighten(Color3.new(0, 0.5, 1), 1.5) + expect(BasicallyIdentical(Color3.new(1, 1, 1), color)).to.equal(true) end) it("doesn't overshoot if a below-range coefficient is supplied", function() - local colour = Lighten(Color3.new(0, 0.5, 1), -1.5) - expect(BasicallyIdentical(Color3.new(0, 0, 1), colour)).to.equal(true) + local color = Lighten(Color3.new(0, 0.5, 1), -1.5) + expect(BasicallyIdentical(Color3.new(0, 0, 1), color)).to.equal(true) end) it("lightens black to white when coefficient is 1", function() - local colour = Lighten(Color3.new(), 1) - expect(BasicallyIdentical(Color3.new(1, 1, 1), colour)).to.equal(true) + local color = Lighten(Color3.new(), 1) + expect(BasicallyIdentical(Color3.new(1, 1, 1), color)).to.equal(true) end) it("lightens black by 10% when coefficient is 0.1", function() - local colour = Lighten(Color3.new(0, 0, 0), 0.1) - expect(BasicallyIdentical(Color3.new(0.1, 0.1, 0.1), colour)).to.equal(true) + local color = Lighten(Color3.new(0, 0, 0), 0.1) + expect(BasicallyIdentical(Color3.new(0.1, 0.1, 0.1), color)).to.equal(true) end) it("lightens red by 50% when coefficient is 0.5", function() - local colour = Lighten(Color3.new(1, 0, 0), 0.5) - expect(BasicallyIdentical(Color3.new(1, 0.5, 0.5), colour)).to.equal(true) + local color = Lighten(Color3.new(1, 0, 0), 0.5) + expect(BasicallyIdentical(Color3.new(1, 0.5, 0.5), color)).to.equal(true) end) it("lightens grey by 50% when coefficient is 0.5", function() - local colour = Lighten(Color3.new(0.5, 0.5, 0.5), 0.5) - expect(BasicallyIdentical(Color3.new(0.75, 0.75, 0.75), colour)).to.equal(true) + local color = Lighten(Color3.new(0.5, 0.5, 0.5), 0.5) + expect(BasicallyIdentical(Color3.new(0.75, 0.75, 0.75), color)).to.equal(true) end) - it("doesn't modify colours when coefficient is 0", function() - local colour = Lighten(Color3.new(0.5, 0.5, 0.5), 0) - expect(BasicallyIdentical(Color3.new(0.5, 0.5, 0.5), colour)).to.equal(true) + it("doesn't modify colors when coefficient is 0", function() + local color = Lighten(Color3.new(0.5, 0.5, 0.5), 0) + expect(BasicallyIdentical(Color3.new(0.5, 0.5, 0.5), color)).to.equal(true) end) end diff --git a/src/Palette/Analogous.lua b/src/Palette/Analogous.lua index bd6965a..35ef6be 100644 --- a/src/Palette/Analogous.lua +++ b/src/Palette/Analogous.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local Rotate = require(script.Parent.Parent.Rotate) +local Types = require(script.Parent.Parent.Util.Types) local assertTypeOf = Assert.prepTypeOf("Analogous") @@ -10,8 +10,8 @@ type Array = Types.Array @function Analogous @within Palette - @param base Color3 -- The base colour. - @return {Color3} -- The analogous colours. + @param base Color3 -- The base color. + @return {Color3} -- The analogous colors. ]=] return function(base: Color3): Array assertTypeOf("base", "Color3", base) diff --git a/src/Palette/Analogous.spec.lua b/src/Palette/Analogous.spec.lua index 86b7cf1..fdf1f0a 100644 --- a/src/Palette/Analogous.spec.lua +++ b/src/Palette/Analogous.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Analogous = require(script.Parent.Analogous) diff --git a/src/Palette/Complementary.lua b/src/Palette/Complementary.lua index 3b84b9b..b4c2bf1 100644 --- a/src/Palette/Complementary.lua +++ b/src/Palette/Complementary.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local Rotate = require(script.Parent.Parent.Rotate) +local Types = require(script.Parent.Parent.Util.Types) local assertTypeOf = Assert.prepTypeOf("Complementary") @@ -10,8 +10,8 @@ type Array = Types.Array @function Complementary @within Palette - @param base Color3 -- The base colour. - @return {Color3} -- The complementary colours. + @param base Color3 -- The base color. + @return {Color3} -- The complementary colors. ]=] return function(base: Color3): Array assertTypeOf("base", "Color3", base) diff --git a/src/Palette/Complementary.spec.lua b/src/Palette/Complementary.spec.lua index 0e1bfa7..699ec5d 100644 --- a/src/Palette/Complementary.spec.lua +++ b/src/Palette/Complementary.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Complementary = require(script.Parent.Complementary) diff --git a/src/Palette/Monochromatic.lua b/src/Palette/Monochromatic.lua index 191925b..eea18b0 100644 --- a/src/Palette/Monochromatic.lua +++ b/src/Palette/Monochromatic.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("Monochromatic") local assertEvalArg = Assert.prepEvalArg("Monochromatic") @@ -11,9 +11,9 @@ local sort = table.sort @function Monochromatic @within Palette - @param base Color3 -- The base colour. + @param base Color3 -- The base color. @param swatches number -- The number of swatches to generate. - @return {Color3} -- The monochromatic colours. + @return {Color3} -- The monochromatic colors. ]=] return function(base: Color3, swatches: number?): { Color3 } swatches = swatches or 3 @@ -27,16 +27,16 @@ return function(base: Color3, swatches: number?): { Color3 } local h, s, v = base:ToHSV() local increment = 1 / swatches - local colours = {} + local colors = {} for _ = 1, swatches do - push(colours, Color3.fromHSV(h, s, v)) + push(colors, Color3.fromHSV(h, s, v)) v = (v + increment) % 1 end - sort(colours, function(a, b) + sort(colors, function(a, b) return select(3, a:ToHSV()) < select(3, b:ToHSV()) end) - return colours + return colors end diff --git a/src/Palette/Monochromatic.spec.lua b/src/Palette/Monochromatic.spec.lua index 9d8e37d..770e989 100644 --- a/src/Palette/Monochromatic.spec.lua +++ b/src/Palette/Monochromatic.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Monochromatic = require(script.Parent.Monochromatic) diff --git a/src/Palette/Nearest.lua b/src/Palette/Nearest.lua new file mode 100644 index 0000000..7b00b12 --- /dev/null +++ b/src/Palette/Nearest.lua @@ -0,0 +1,42 @@ +--!strict +--[=[ + @function Nearest + @within Palette + + Given an array of Color3s, returns the color that is closest to the given Color3. + + @param to Color3 -- The color to find the nearest color to. + @param colors { Color3 } -- The array of colors to search through. + @return Color3 -- The nearest color. +]=] +local function nearest(to: Color3, colors: { Color3 }): Color3 + assert(typeof(to) == "Color3", `Nearest(...): Expected "to" to be a Color3, got "{to}" ({typeof(to)})`) + + local smallestMagnitude: number = math.huge + local nearestColor: Color3 = nil + local didWarn = false + + for index, color in colors do + if typeof(color) ~= "Color3" then + if didWarn == false then + warn( + `Nearest(...): Expected "colors" to be an array of Color3, got "{color}" ({typeof(color)}) at index #{index}` + ) + didWarn = true + end + + continue + end + + local magnitude = math.sqrt((color.R - to.R) ^ 2 + (color.G - to.G) ^ 2 + (color.B - to.B) ^ 2) + + if magnitude < smallestMagnitude then + smallestMagnitude = magnitude + nearestColor = color + end + end + + return nearestColor +end + +return nearest diff --git a/src/Palette/Nearest.spec.lua b/src/Palette/Nearest.spec.lua new file mode 100644 index 0000000..8ea8cd9 --- /dev/null +++ b/src/Palette/Nearest.spec.lua @@ -0,0 +1,63 @@ +local nearest = require(script.Parent.Nearest) + +local TEST_COLORS = { + OBSIDIAN = Color3.fromHex("#04040C"), + DANGER = Color3.fromHex("#FC0404"), + ORANGE = Color3.fromHex("#F26E1F"), + GOLD = Color3.fromHex("#E5CF18"), + FOREST = Color3.fromHex("#7A9C28"), + SKY = Color3.fromHex("#00A2FF"), + LAVENDER = Color3.fromHex("#7D5CA4"), + BUBBLEGUM = Color3.fromHex("#FC628F"), + SNOW = Color3.fromHex("#CCD6F4"), +} + +local TEST_TAILWIND_SKY = { + [50] = Color3.fromHex("#F0F9FF"), + [100] = Color3.fromHex("#E0F2FE"), + [200] = Color3.fromHex("#BAE6FD"), + [300] = Color3.fromHex("#7DD3FC"), + [400] = Color3.fromHex("#38BDF8"), + [500] = Color3.fromHex("#0EA5E9"), + [600] = Color3.fromHex("#0284C7"), + [700] = Color3.fromHex("#0369A1"), + [800] = Color3.fromHex("#075985"), + [900] = Color3.fromHex("#0C4A6E"), + [950] = Color3.fromHex("#0A4369"), +} + +local COLOR = { + BLACK = Color3.new(0, 0, 0), + RED = Color3.new(1, 0, 0), + GREEN = Color3.new(0, 1, 0), + BLUE = Color3.new(0, 0, 1), + WHITE = Color3.new(1, 1, 1), + RBX_BLUE = Color3.fromHex("#00a2ff"), +} + +local colorArray = {} + +for _, color in TEST_COLORS do + table.insert(colorArray, color) +end + +return function() + it("returns a Color3", function() + local result = nearest(COLOR.BLACK, colorArray) + expect(typeof(result)).to.equal("Color3") + end) + + it("returns the nearest Color3", function() + local result0 = nearest(COLOR.WHITE, colorArray) + local result1 = nearest(COLOR.BLUE, colorArray) + local result2 = nearest(COLOR.GREEN, colorArray) + local result3 = nearest(COLOR.RED, colorArray) + local result4 = nearest(COLOR.RBX_BLUE, TEST_TAILWIND_SKY) + + expect(result0).to.equal(TEST_COLORS.SNOW) + expect(result1).to.equal(TEST_COLORS.SKY) + expect(result2).to.equal(TEST_COLORS.FOREST) + expect(result3).to.equal(TEST_COLORS.DANGER) + expect(result4).to.equal(TEST_TAILWIND_SKY[500]) + end) +end diff --git a/src/Palette/SplitComplementary.lua b/src/Palette/SplitComplementary.lua index 41d079a..ff8d28f 100644 --- a/src/Palette/SplitComplementary.lua +++ b/src/Palette/SplitComplementary.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local Rotate = require(script.Parent.Parent.Rotate) +local Types = require(script.Parent.Parent.Util.Types) local assertTypeOf = Assert.prepTypeOf("SplitComplementary") @@ -10,8 +10,8 @@ type Array = Types.Array @function SplitComplementary @within Palette - @param base Color3 -- The base colour. - @return {Color3} -- The split complementary colours. + @param base Color3 -- The base color. + @return {Color3} -- The split complementary colors. ]=] return function(base: Color3): Array assertTypeOf("base", "Color3", base) diff --git a/src/Palette/SplitComplementary.spec.lua b/src/Palette/SplitComplementary.spec.lua index 7441dfb..90a8485 100644 --- a/src/Palette/SplitComplementary.spec.lua +++ b/src/Palette/SplitComplementary.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local SplitComplementary = require(script.Parent.SplitComplementary) diff --git a/src/Palette/Tailwind.lua b/src/Palette/Tailwind.lua index 8c640ef..73725f6 100644 --- a/src/Palette/Tailwind.lua +++ b/src/Palette/Tailwind.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) -local Array = require(script.Parent.Parent._Util.Array) +local Array = require(script.Parent.Parent.Util.Array) +local Assert = require(script.Parent.Parent.Util.Assert) +local Types = require(script.Parent.Parent.Util.Types) local HSL = require(script.Parent.Parent.HSL) local Saturate = require(script.Parent.Parent.Saturate) @@ -10,8 +10,8 @@ local assertTypeOf = Assert.prepTypeOf("Tailwind") local tfind = table.find local abs = math.abs -local LIGHTNESS_MAP = { 0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05 } -local SATURATION_MAP = { 0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32 } +local SATURATION_MAP = { 0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32, 0.84 } +local LIGHTNESS_MAP = { 0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.1, 0.05 } --[=[ @interface TailwindPalette @@ -26,10 +26,11 @@ local SATURATION_MAP = { 0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32 } .700 Color3 .800 Color3 .900 Color3 + .950 Color3 ]=] export type TailwindPalette = Types.Dictionary -local function GetBaseColourSaturationIndex(hsl: HSL.HSL): number +local function GetBaseColorSaturationIndex(hsl: HSL.HSL): number local goal = hsl.L / 100 local closestLightness = Array.reduce(LIGHTNESS_MAP, function(previous, current) @@ -43,28 +44,44 @@ end @function Tailwind @within Palette - @param base Color3 -- The base colour. + Generates a TailwindCSS-like palette from a given base color. The generator is + based on Smart Swatch by Ivan Dalmet, so results will not be identical to + TailwindCSS. + + @param base Color3 -- The base color. @return TailwindPalette -- The generated palette. + + ```lua + local BASE_COLOR = Color3.fromHex("#00a2ff") + local palette = Tailwind(BASE_COLOR) + ``` + + ![Tailwind palette](/media/tailwind-palette.png) ]=] local function Tailwind(base: Color3): TailwindPalette assertTypeOf("base", "Color3", base) local hsl = HSL.toHSL(base) - local satIndex = GetBaseColourSaturationIndex(hsl) + local satIndex = GetBaseColorSaturationIndex(hsl) - local colours = Array.map( + local colors = Array.map( Array.map(LIGHTNESS_MAP, function(lightness: number) return HSL.fromHSL({ H = hsl.H, S = hsl.S, L = lightness * 100 }) end), - function(colour: Color3, index) + function(color: Color3, index) local satDelta = SATURATION_MAP[index] - SATURATION_MAP[satIndex] - return Saturate(colour, satDelta) + return Saturate(color, satDelta) end ) - return Array.reduce(colours, function(accumulator, colour: Color3, index) + return Array.reduce(colors, function(accumulator, color: Color3, index) local key = if index == 1 then 50 else (index - 1) * 100 - accumulator[key] = colour + + if index == #colors then + key -= 50 + end + + accumulator[key] = color return accumulator end, {}) diff --git a/src/Palette/Tailwind.spec.lua b/src/Palette/Tailwind.spec.lua index 92dd69c..3e4475b 100644 --- a/src/Palette/Tailwind.spec.lua +++ b/src/Palette/Tailwind.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Tailwind = require(script.Parent.Tailwind) @@ -14,14 +14,15 @@ return function() [600] = Color3.fromHex("#0071b2"), [700] = Color3.fromHex("#00507f"), [800] = Color3.fromHex("#00304c"), - [900] = Color3.fromHex("#000f19"), + [900] = Color3.fromHex("#001f32"), + [950] = Color3.fromHex("#000f19"), } it("generates a tailwind-like palette", function() local palette = Tailwind(BASE) - for key, colour in pairs(RESULT) do - expect(BasicallyIdentical(colour, palette[key])).to.equal(true) + for key, color in pairs(RESULT) do + expect(BasicallyIdentical(color, palette[key])).to.equal(true) end end) diff --git a/src/Palette/Tetradic.lua b/src/Palette/Tetradic.lua index 16e391f..b75accc 100644 --- a/src/Palette/Tetradic.lua +++ b/src/Palette/Tetradic.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local Rotate = require(script.Parent.Parent.Rotate) +local Types = require(script.Parent.Parent.Util.Types) local assertTypeOf = Assert.prepTypeOf("Tetradic") @@ -10,8 +10,8 @@ type Array = Types.Array @function Tetradic @within Palette - @param base Color3 -- The base colour. - @return {Color3} -- The tetradic colours. + @param base Color3 -- The base color. + @return {Color3} -- The tetradic colors. ]=] return function(base: Color3): Array assertTypeOf("base", "Color3", base) diff --git a/src/Palette/Tetradic.spec.lua b/src/Palette/Tetradic.spec.lua index a5c0dcb..7cd019e 100644 --- a/src/Palette/Tetradic.spec.lua +++ b/src/Palette/Tetradic.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Tetradic = require(script.Parent.Tetradic) diff --git a/src/Palette/Triadic.lua b/src/Palette/Triadic.lua index 7ecdf0b..364571a 100644 --- a/src/Palette/Triadic.lua +++ b/src/Palette/Triadic.lua @@ -1,6 +1,6 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local Rotate = require(script.Parent.Parent.Rotate) +local Types = require(script.Parent.Parent.Util.Types) local assertTypeOf = Assert.prepTypeOf("Triadic") @@ -10,8 +10,8 @@ type Array = Types.Array @function Triadic @within Palette - @param base Color3 -- The base colour. - @return {Color3} -- The triadic colours. + @param base Color3 -- The base color. + @return {Color3} -- The triadic colors. ]=] return function(base: Color3): Array assertTypeOf("base", "Color3", base) diff --git a/src/Palette/Triadic.spec.lua b/src/Palette/Triadic.spec.lua index 8d91dd3..d83d8b2 100644 --- a/src/Palette/Triadic.spec.lua +++ b/src/Palette/Triadic.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Triadic = require(script.Parent.Triadic) diff --git a/src/Palette/Vibrant.lua b/src/Palette/Vibrant.lua index 5741342..2956d58 100644 --- a/src/Palette/Vibrant.lua +++ b/src/Palette/Vibrant.lua @@ -1,7 +1,7 @@ -local Types = require(script.Parent.Parent._Util.Types) -local Assert = require(script.Parent.Parent._Util.Assert) -local Schema = require(script.Parent.Parent._Util.Schema) +local Assert = require(script.Parent.Parent.Util.Assert) local GetLuminance = require(script.Parent.Parent.GetLuminance) +local Schema = require(script.Parent.Parent.Util.Schema) +local Types = require(script.Parent.Parent.Util.Types) local assertArrayOf = Assert.prepArrayOf("Vibrant") @@ -46,7 +46,7 @@ local DEFAULT_OPTIONS: VibrantOptions = { @param swatches {Color3} -- The swatches to select from. @param options? VibrantOptions -- The options to use. - @return Color3 -- The "most vibrant" colour. + @return Color3 -- The "most vibrant" color. ]=] return function(swatches: Array, options: VibrantOptions?): Color3 assertArrayOf("swatches", "Color3", swatches) diff --git a/src/Palette/Vibrant.spec.lua b/src/Palette/Vibrant.spec.lua index 4519213..fbee9c5 100644 --- a/src/Palette/Vibrant.spec.lua +++ b/src/Palette/Vibrant.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() local Vibrant = require(script.Parent.Vibrant) @@ -52,7 +52,7 @@ return function() expect(typeof(result)).to.equal("Color3") end) - it("correctly determines most vibrant colour", function() + it("correctly determines most vibrant color", function() local results, expects = {}, {} for _, swatches in ipairs(testSwatches) do diff --git a/src/Palette/init.lua b/src/Palette/init.lua index 35daee7..0ac2214 100644 --- a/src/Palette/init.lua +++ b/src/Palette/init.lua @@ -5,6 +5,7 @@ return { Analogous = require(script.Analogous), Complementary = require(script.Complementary), Monochromatic = require(script.Monochromatic), + Nearest = require(script.Nearest), SplitComplementary = require(script.SplitComplementary), Tailwind = require(script.Tailwind), Tetradic = require(script.Tetradic), diff --git a/src/Rotate.lua b/src/Rotate.lua index 33b722b..a5391f5 100644 --- a/src/Rotate.lua +++ b/src/Rotate.lua @@ -1,25 +1,25 @@ -local Assert = require(script.Parent._Util.Assert) -local clampColour = require(script.Parent._Util.ClampColour) +local Assert = require(script.Parent.Util.Assert) +local clampColor = require(script.Parent.Util.ClampColor) local assertTypeOf = Assert.prepTypeOf("Rotate") local clamp = math.clamp --[=[ @function Rotate - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to rotate. + @param color Color3 -- The color to rotate. @param angle number -- The angle to rotate by. - @return Color3 -- The rotated colour. + @return Color3 -- The rotated color. ]=] -return function(colour: Color3, angle: number): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3, angle: number): Color3 + assertTypeOf("color", "Color3", color) assertTypeOf("angle", "number", angle) - local hue, sat, val = colour:ToHSV() + local hue, sat, val = color:ToHSV() local newHue = clamp((hue + (angle / 360)) % 1, 0, 1) - local newColour = Color3.fromHSV(newHue, sat, val) + local newColor = Color3.fromHSV(newHue, sat, val) - return clampColour(newColour) + return clampColor(newColor) end diff --git a/src/Rotate.spec.lua b/src/Rotate.spec.lua index 2be30db..a8f7be1 100644 --- a/src/Rotate.spec.lua +++ b/src/Rotate.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Rotate = require(script.Parent.Rotate) @@ -9,19 +9,19 @@ return function() expect(pcall(Rotate, Color3.new(), false)).to.equal(false) end) - it("can rotate a colour 180deg to receive the inverse", function() - local colour = Color3.fromRGB(0, 162, 255) + it("can rotate a color 180deg to receive the inverse", function() + local color = Color3.fromRGB(0, 162, 255) - local inverseHue = Invert(colour):ToHSV() - local rotatedHue = Rotate(colour, 180):ToHSV() + local inverseHue = Invert(color):ToHSV() + local rotatedHue = Rotate(color, 180):ToHSV() expect(inverseHue).to.be.near(rotatedHue, 0.001) end) - it("can rotate a colour 360deg to receive the same colour", function() - local colour = Color3.new(0, 1, 1) - local result = Rotate(colour, 360) + it("can rotate a color 360deg to receive the same color", function() + local color = Color3.new(0, 1, 1) + local result = Rotate(color, 360) - expect(BasicallyIdentical(colour, result)).to.equal(true) + expect(BasicallyIdentical(color, result)).to.equal(true) end) end diff --git a/src/Saturate.lua b/src/Saturate.lua index 9c0e96b..a5cb0f4 100644 --- a/src/Saturate.lua +++ b/src/Saturate.lua @@ -1,5 +1,5 @@ -local Assert = require(script.Parent._Util.Assert) -local ClampColour = require(script.Parent._Util.ClampColour) +local Assert = require(script.Parent.Util.Assert) +local ClampColor = require(script.Parent.Util.ClampColor) local assertTypeOf = Assert.prepTypeOf("Saturate") @@ -7,18 +7,18 @@ local clamp = math.clamp --[=[ @function Saturate - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to saturate. + @param color Color3 -- The color to saturate. @param coefficient number -- The coefficient to saturate by [0-1]. - @return Color3 -- The saturated colour. + @return Color3 -- The saturated color. ]=] -return function(colour: Color3, coefficient: number): Color3 - assertTypeOf("colour", "Color3", colour) +return function(color: Color3, coefficient: number): Color3 + assertTypeOf("color", "Color3", color) assertTypeOf("coefficient", "number", coefficient) - local H, S, V = colour:ToHSV() + local H, S, V = color:ToHSV() S += S * coefficient - return ClampColour(Color3.fromHSV(H, clamp(S, 0, 1), V)) + return ClampColor(Color3.fromHSV(H, clamp(S, 0, 1), V)) end diff --git a/src/Saturate.spec.lua b/src/Saturate.spec.lua index 4f358ef..6ec7bd1 100644 --- a/src/Saturate.spec.lua +++ b/src/Saturate.spec.lua @@ -1,4 +1,4 @@ -local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Util.BasicallyIdentical) return function() local Saturate = require(script.Parent.Saturate) @@ -7,10 +7,10 @@ return function() local TEST_RESULT = Color3.fromHex("#00a2ff") local TEST_AMOUNT = 0.5 - it("should saturate a colour", function() - local colour = Saturate(TEST_BASE, TEST_AMOUNT) + it("should saturate a color", function() + local color = Saturate(TEST_BASE, TEST_AMOUNT) - expect(BasicallyIdentical(TEST_RESULT, colour)).to.equal(true) + expect(BasicallyIdentical(TEST_RESULT, color)).to.equal(true) end) it("throws if argument is not a Color3", function() diff --git a/src/_Util/Array.lua b/src/Util/Array.lua similarity index 100% rename from src/_Util/Array.lua rename to src/Util/Array.lua diff --git a/src/_Util/Assert.lua b/src/Util/Assert.lua similarity index 92% rename from src/_Util/Assert.lua rename to src/Util/Assert.lua index 936e6e6..f45d7ae 100644 --- a/src/_Util/Assert.lua +++ b/src/Util/Assert.lua @@ -35,15 +35,8 @@ function Assert.arrayOf(methodName: string, argName: string, class: string, arra for index, value in ipairs(array) do if typeof(value) ~= class then - local errorText = fmt( - Assert.TYPE.INVALID_ARRAY, - methodName, - argName, - class, - tostring(value), - typeof(value), - index - ) + local errorText = + fmt(Assert.TYPE.INVALID_ARRAY, methodName, argName, class, tostring(value), typeof(value), index) error(errorText, 3) end end diff --git a/src/_Util/BasicallyIdentical.lua b/src/Util/BasicallyIdentical.lua similarity index 86% rename from src/_Util/BasicallyIdentical.lua rename to src/Util/BasicallyIdentical.lua index 00b8cd7..5ecea26 100644 --- a/src/_Util/BasicallyIdentical.lua +++ b/src/Util/BasicallyIdentical.lua @@ -1,14 +1,8 @@ local fmt = string.format local abs = math.abs -local function StringifyColor3(colour: Color3): string - return string.format( - 'Color3<%.3g, %.3g, %.3g> "#%s"', - colour.R * 255, - colour.G * 255, - colour.B * 255, - colour:ToHex() - ) +local function StringifyColor3(color: Color3): string + return string.format('Color3<%.3g, %.3g, %.3g> "#%s"', color.R * 255, color.G * 255, color.B * 255, color:ToHex()) end return function(base: Color3, compare: Color3, distance: number?): boolean diff --git a/src/Util/ClampColor.lua b/src/Util/ClampColor.lua new file mode 100644 index 0000000..5e5807a --- /dev/null +++ b/src/Util/ClampColor.lua @@ -0,0 +1,9 @@ +local clamp = math.clamp + +return function(color: Color3): Color3 + local red = clamp(color.R, 0, 1) + local green = clamp(color.G, 0, 1) + local blue = clamp(color.B, 0, 1) + + return Color3.new(red, green, blue) +end diff --git a/src/Util/DeprecateWarnOnce.lua b/src/Util/DeprecateWarnOnce.lua new file mode 100644 index 0000000..81502bc --- /dev/null +++ b/src/Util/DeprecateWarnOnce.lua @@ -0,0 +1,18 @@ +local function deprecateWarnOnce(method) + return function(oldMethod: string, newMethod: string, removalInVersion: string?): typeof(method) + local didWarn = false + + return function(...) + if not didWarn then + local removalString = removalInVersion and ` and will be removed in {removalInVersion}` or "" + + didWarn = true + warn(`{oldMethod} is deprecated{removalString}. Please use {newMethod} instead.`) + end + + return method(...) + end + end +end + +return deprecateWarnOnce diff --git a/src/_Util/Schema.lua b/src/Util/Schema.lua similarity index 100% rename from src/_Util/Schema.lua rename to src/Util/Schema.lua diff --git a/src/Util/Types.lua b/src/Util/Types.lua new file mode 100644 index 0000000..acb5109 --- /dev/null +++ b/src/Util/Types.lua @@ -0,0 +1,4 @@ +export type Dictionary = { [K]: V } +export type Array = Dictionary + +return nil diff --git a/src/_Util/init.lua b/src/Util/init.lua similarity index 84% rename from src/_Util/init.lua rename to src/Util/init.lua index a9adb4d..6f5d36f 100644 --- a/src/_Util/init.lua +++ b/src/Util/init.lua @@ -2,7 +2,7 @@ return { Array = require(script.Array), Assert = require(script.Assert), BasicallyIdentical = require(script.BasicallyIdentical), - ClampColour = require(script.ClampColour), + ClampColor = require(script.ClampColor), isNaN = require(script.isNaN), Schema = require(script.Schema), Types = require(script.Types), diff --git a/src/_Util/isNaN.lua b/src/Util/isNaN.lua similarity index 100% rename from src/_Util/isNaN.lua rename to src/Util/isNaN.lua diff --git a/src/WCAG/GetContrastRatio.lua b/src/WCAG/GetContrastRatio.lua index ed026d6..6e91c4d 100644 --- a/src/WCAG/GetContrastRatio.lua +++ b/src/WCAG/GetContrastRatio.lua @@ -1,4 +1,4 @@ -local Assert = require(script.Parent.Parent._Util.Assert) +local Assert = require(script.Parent.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("GetContrastRatio") local GetLuminance = require(script.Parent.Parent.GetLuminance) @@ -10,8 +10,8 @@ local min = math.min @function GetContrastRatio @within WCAG - @param foreground Color3 -- The foreground colour. - @param background Color3 -- The background colour. + @param foreground Color3 -- The foreground color. + @param background Color3 -- The background color. @return number -- The contrast ratio [0-21]. ]=] return function(foreground: Color3, background: Color3): number diff --git a/src/WCAG/GetContrastingColour.lua b/src/WCAG/GetContrastingColor.lua similarity index 74% rename from src/WCAG/GetContrastingColour.lua rename to src/WCAG/GetContrastingColor.lua index f69343c..47c53bf 100644 --- a/src/WCAG/GetContrastingColour.lua +++ b/src/WCAG/GetContrastingColor.lua @@ -1,21 +1,21 @@ -local Assert = require(script.Parent.Parent._Util.Assert) -local assertTypeOf = Assert.prepTypeOf("GetContrastingColour") +local Assert = require(script.Parent.Parent.Util.Assert) +local assertTypeOf = Assert.prepTypeOf("GetContrastingColor") +local Darken = require(script.Parent.Parent.Darken) local GetContrastRatio = require(script.Parent.GetContrastRatio) local Lighten = require(script.Parent.Parent.Lighten) -local Darken = require(script.Parent.Parent.Darken) local isDark = require(script.Parent.Parent.isDark) local MIN_RATIO = 4.5 --[=[ - @function GetContrastingColour + @function GetContrastingColor @within WCAG - @param foreground Color3 -- The foreground colour. - @param background Color3 -- The background colour. + @param foreground Color3 -- The foreground color. + @param background Color3 -- The background color. @param ratio? number -- The ratio to check against [0-1] (defaults to 4.5). - @return Color3 -- The contrasting colour. + @return Color3 -- The contrasting color. ]=] return function(foreground: Color3, background: Color3, ratio: number?): Color3 assertTypeOf("foreground", "Color3", foreground) diff --git a/src/WCAG/GetContrastingColour.spec.lua b/src/WCAG/GetContrastingColor.spec.lua similarity index 55% rename from src/WCAG/GetContrastingColour.spec.lua rename to src/WCAG/GetContrastingColor.spec.lua index efae8ca..bb8d2bd 100644 --- a/src/WCAG/GetContrastingColour.spec.lua +++ b/src/WCAG/GetContrastingColor.spec.lua @@ -1,7 +1,7 @@ -local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) +local BasicallyIdentical = require(script.Parent.Parent.Util.BasicallyIdentical) return function() - local GetContrastingColour = require(script.Parent.GetContrastingColour) + local GetContrastingColor = require(script.Parent.GetContrastingColor) local BLACK = Color3.new() local WHITE = Color3.new(1, 1, 1) @@ -16,23 +16,23 @@ return function() local PW_TARGET = Color3.new(0.448, 0, 0.448) it("throws if arguments are not Color3s", function() - expect(pcall(GetContrastingColour, BLACK, true)).to.equal(false) - expect(pcall(GetContrastingColour, true, BLACK)).to.equal(false) - expect(pcall(GetContrastingColour, 100, true)).to.equal(false) + expect(pcall(GetContrastingColor, BLACK, true)).to.equal(false) + expect(pcall(GetContrastingColor, true, BLACK)).to.equal(false) + expect(pcall(GetContrastingColor, 100, true)).to.equal(false) end) it("returns a Color3", function() - local result = GetContrastingColour(BLACK, WHITE) + local result = GetContrastingColor(BLACK, WHITE) expect(typeof(result)).to.equal("Color3") end) - it("adjusts a colour to meet the minimum ratio", function() - local black = GetContrastingColour(BLACK, BLACK) - local white = GetContrastingColour(WHITE, WHITE) - local yellow = GetContrastingColour(YELLOW, WHITE) - local navy = GetContrastingColour(NAVY, BLACK) + it("adjusts a color to meet the minimum ratio", function() + local black = GetContrastingColor(BLACK, BLACK) + local white = GetContrastingColor(WHITE, WHITE) + local yellow = GetContrastingColor(YELLOW, WHITE) + local navy = GetContrastingColor(NAVY, BLACK) - local pink = GetContrastingColour(PINK, WHITE, 7) + local pink = GetContrastingColor(PINK, WHITE, 7) expect(BasicallyIdentical(black, BB_TARGET)).to.equal(true) expect(BasicallyIdentical(white, WW_TARGET)).to.equal(true) diff --git a/src/WCAG/init.lua b/src/WCAG/init.lua index cec2ced..2a0e67e 100644 --- a/src/WCAG/init.lua +++ b/src/WCAG/init.lua @@ -2,6 +2,6 @@ @class WCAG ]=] return { - GetContrastingColour = require(script.GetContrastingColour), + GetContrastingColor = require(script.GetContrastingColor), GetContrastRatio = require(script.GetContrastRatio), } diff --git a/src/_Util/ClampColour.lua b/src/_Util/ClampColour.lua deleted file mode 100644 index 40a1e89..0000000 --- a/src/_Util/ClampColour.lua +++ /dev/null @@ -1,9 +0,0 @@ -local clamp = math.clamp - -return function(colour: Color3): Color3 - local red = clamp(colour.R, 0, 1) - local green = clamp(colour.G, 0, 1) - local blue = clamp(colour.B, 0, 1) - - return Color3.new(red, green, blue) -end diff --git a/src/_Util/Types.lua b/src/_Util/Types.lua deleted file mode 100644 index 1fb61d0..0000000 --- a/src/_Util/Types.lua +++ /dev/null @@ -1,4 +0,0 @@ -export type Dictionary = ({ [K]: V }) -export type Array = (Dictionary) - -return nil diff --git a/src/init.lua b/src/init.lua index 0003257..ea03db8 100644 --- a/src/init.lua +++ b/src/init.lua @@ -1,13 +1,16 @@ +local deprecateWarnOnce = require(script.Util.DeprecateWarnOnce) + +local GetContrastRatioCompat = require(script.GetContrastRatioCompat) +local WCAG = require(script.WCAG) + --[=[ - @class ColourUtils + @class ColorUtils ]=] local module = { -- Methods -- Darken = require(script.Darken), Desaturate = require(script.Desaturate), - Emphasise = require(script.Emphasise), - GetContrastingColour = require(script.GetContrastingColour), - GetContrastRatio = require(script.GetContrastRatio), + Emphasize = require(script.Emphasize), GetLuminance = require(script.GetLuminance), GetPerceivedBrightness = require(script.GetPerceivedBrightness), Invert = require(script.Invert), @@ -27,10 +30,26 @@ local module = { LAB = require(script.LAB), LCH = require(script.LCH), Palette = require(script.Palette), - WCAG = require(script.WCAG), + WCAG = WCAG, } -module.Emphasize = module.Emphasise -module.GetContrastingColor = module.GetContrastingColour +-- Deprecated methods -- +module.Emphasise = + deprecateWarnOnce(module.Emphasize)("ColorUtils.Emphasise", "ColorUtils.Emphasize") :: typeof(module.Emphasize) + +module.GetContrastingColor = deprecateWarnOnce(WCAG.GetContrastingColor)( + "ColorUtils.GetContrastingColor", + "WCAG.GetContrastingColor" +) :: typeof(WCAG.GetContrastingColor) + +module.GetContrastingColour = deprecateWarnOnce(module.GetContrastingColor)( + "ColorUtils.GetContrastingColour", + "WCAG.GetContrastingColor" +) :: typeof(module.GetContrastingColor) + +module.GetContrastRatio = deprecateWarnOnce(GetContrastRatioCompat)( + "ColorUtils.GetContrastRatio", + "WCAG.GetContrastRatio" +) :: typeof(GetContrastRatioCompat) return module diff --git a/src/isDark.lua b/src/isDark.lua index 9e51586..f8031ee 100644 --- a/src/isDark.lua +++ b/src/isDark.lua @@ -1,17 +1,17 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("isDark") local GetLuminance = require(script.Parent.GetLuminance) --[=[ @function isDark - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to check. - @return boolean -- Whether the colour is dark. + @param color Color3 -- The color to check. + @return boolean -- Whether the color is dark. ]=] -return function(colour: Color3): boolean - assertTypeOf("colour", "Color3", colour) +return function(color: Color3): boolean + assertTypeOf("color", "Color3", color) - return GetLuminance(colour) < 0.5 + return GetLuminance(color) < 0.5 end diff --git a/src/isLight.lua b/src/isLight.lua index 9e6e98a..492897f 100644 --- a/src/isLight.lua +++ b/src/isLight.lua @@ -1,17 +1,17 @@ -local Assert = require(script.Parent._Util.Assert) +local Assert = require(script.Parent.Util.Assert) local assertTypeOf = Assert.prepTypeOf("isLight") local isDark = require(script.Parent.isDark) --[=[ @function isLight - @within ColourUtils + @within ColorUtils - @param colour Color3 -- The colour to check. - @return boolean -- Whether the colour is light. + @param color Color3 -- The color to check. + @return boolean -- Whether the color is light. ]=] -return function(colour: Color3): boolean - assertTypeOf("colour", "Color3", colour) +return function(color: Color3): boolean + assertTypeOf("color", "Color3", color) - return not isDark(colour) + return not isDark(color) end diff --git a/test-runner.server.lua b/test-runner.server.lua index 3e2c53a..a7aa6b4 100644 --- a/test-runner.server.lua +++ b/test-runner.server.lua @@ -1,8 +1,8 @@ local ServerScripts = game:GetService("ServerScriptService") local TestService = game:GetService("TestService") -local TestEZ = require(TestService.Packages.TestEZ) +local TestEZ = require(TestService:WaitForChild("Packages", 10).TestEZ) TestEZ.TestBootstrap:run({ - ServerScripts.ColourUtils, + ServerScripts.ColourUtils, }) diff --git a/testez.toml b/testez.toml new file mode 100644 index 0000000..c2c5a98 --- /dev/null +++ b/testez.toml @@ -0,0 +1,66 @@ +[[afterAll.args]] +type = "function" + +[[afterEach.args]] +type = "function" + +[[beforeAll.args]] +type = "function" + +[[beforeEach.args]] +type = "function" + +[[describe.args]] +type = "string" + +[[describe.args]] +type = "function" + +[[describeFOCUS.args]] +type = "string" + +[[describeFOCUS.args]] +type = "function" + +[[describeSKIP.args]] +type = "string" + +[[describeSKIP.args]] +type = "function" + +[[expect.args]] +type = "any" + +[[FIXME.args]] +type = "string" +required = false + +[FOCUS] +args = [] + +[[it.args]] +type = "string" + +[[it.args]] +type = "function" + +[[itFIXME.args]] +type = "string" + +[[itFIXME.args]] +type = "function" + +[[itFOCUS.args]] +type = "string" + +[[itFOCUS.args]] +type = "function" + +[[itSKIP.args]] +type = "string" + +[[itSKIP.args]] +type = "function" + +[SKIP] +args = [] diff --git a/typings/index.d.ts b/typings/index.d.ts index 7bbd240..f6f1997 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,5 +1,5 @@ /// -declare namespace ColourUtils { +declare namespace ColorUtils { // Embedded types type VibrantOptions = { TargetLuminance: number @@ -36,128 +36,138 @@ declare namespace ColourUtils { [700]: Color3 [800]: Color3 [900]: Color3 + [950]: Color3 } /** - * Darkens a colour - * @param {Color3} colour - The Color3 to darken + * Darkens a color + * @param {Color3} color - The Color3 to darken * @param {number} coefficient - A multiplier in the range of 0-1 * @returns {Color3} */ - function Darken(colour: Color3, coefficient: number): Color3 + function Darken(color: Color3, coefficient: number): Color3 /** - * Lightens a colour - * @param {Color3} colour - The Color3 to lighten + * Lightens a color + * @param {Color3} color - The Color3 to lighten * @param {number} coefficient - A multiplier in the range of 0-1 * @returns {Color3} */ - function Lighten(colour: Color3, coefficient: number): Color3 + function Lighten(color: Color3, coefficient: number): Color3 /** - * Automatically darken a light colour or lighten a dark colour, depending on its luminance - * @param {Color3} colour - The Color3 to affect + * Automatically darken a light color or lighten a dark color, depending on its luminance + * @param {Color3} color - The Color3 to affect * @param {number} coefficient - A multiplier in the range of 0-1 * @param {number} [threshold=0.5] - The threshold for luminance * @returns {Color3} */ - function Emphasise( - colour: Color3, + function Emphasize( + color: Color3, coefficient: number, threshold?: number ): Color3 /** * Get the relative brightness of a given Color3, using the formula provided by WCAG - * @param {Color3} colour - The Color3 to get luminance of + * @param {Color3} color - The Color3 to get luminance of * @returns {number} */ - function GetLuminance(colour: Color3): number + function GetLuminance(color: Color3): number /** * - * @param {Color3} colour - The Color3 to get the perceived brightness of + * @param {Color3} color - The Color3 to get the perceived brightness of * @returns {number} */ - function GetPerceivedBrightness(colour: Color3): number + function GetPerceivedBrightness(color: Color3): number - export const GetContrastRatio: typeof WCAG.GetContrastRatio - export const GetContrastingColour: typeof WCAG.GetContrastingColour - export const GetContrastingColor: typeof GetContrastingColour + export const GetContrastRatio: typeof WCAG.GetContrastRatio // DEPRECATED + export const GetContrastingColor: typeof WCAG.GetContrastingColor // DEPRECATED + export const GetContrastingColour: typeof GetContrastingColor // DEPRECATED + export const Emphasise: typeof Emphasize // DEPRECATED /** - * Invert a colour - * @param {Color3} colour - The Color3 to invert + * Invert a color + * @param {Color3} color - The Color3 to invert * @returns {Color3} */ - function Invert(colour: Color3): Color3 + function Invert(color: Color3): Color3 /** - * Determine if a colour is a dark colour - * @param {Color3} colour - The Color3 to analyse + * Determine if a color is a dark color + * @param {Color3} color - The Color3 to analyse * @returns {boolean} */ - function isDark(colour: Color3): boolean + function isDark(color: Color3): boolean /** - * Determine if a colour is a light colour - * @param {Color3} colour - The Color3 to analyse + * Determine if a color is a light color + * @param {Color3} color - The Color3 to analyse * @returns {boolean} */ - function isLight(colour: Color3): boolean + function isLight(color: Color3): boolean /** - * Rotate the hue of a colour by the specified angle - * @param {Color3} colour - The Color3 to be rotated + * Rotate the hue of a color by the specified angle + * @param {Color3} color - The Color3 to be rotated * @param {number} angle - The number of degrees to rotate by (usually between 0-360) * @returns {Color3} */ - function Rotate(colour: Color3, angle: number): Color3 + function Rotate(color: Color3, angle: number): Color3 namespace Hex { /** * Converts a hex string into a Color3. This method accepts hex strings of any length (but will only respect the first 6 characters); with or without a preceding hash (#) - * @param {string} hex - A hex colour string + * @param {string} hex - A hex color string * @returns {Color3} */ function fromHex(hex: string): Color3 /** * Converts an RGBA hex string into a Color3. This method accepts hex strings of any length (the last two characters will be treated as the alpha value); with or without a preceding hash (#) - * @param colour + * @param color */ /** * Converts a Color3 into a hex value. Note that this method does not prepend a hash (#) to the beginning of the string, and the result is always lowercase - * @param {Color3} colour - A Color3 to convert to hex + * @param {Color3} color - A Color3 to convert to hex * @returns {string} */ - function toHex(colour: Color3): string + function toHex(color: Color3): string + + /** + * Creates a Color3 from a hex string with an alpha value. The background doesn't need to be specified, but the resulting Color3 will vary depending on the color of the background, so it's recommended to specify a background unless `Color3.new()` is what you want. + * @param {string} hex - A hex color string + * @param {Color3} background - The background color to use when calculating the resulting Color3 + * @returns {Color3} + */ + function fromHexRGBA(hex: string, background?: Color3): Color3 } namespace Int { /** * Converts an integer into a Color3 - * @param {number} integer - An integer representing a colour + * @param {number} integer - An integer representing a color * @returns {Color3} */ function fromInt(integer: number): Color3 /** * Converts a Color3 into an integer value - * @param {Color3} colour - A Color3 to convert into an integer + * @param {Color3} color - A Color3 to convert into an integer * @returns {number} */ - function toInt(colour: Color3): number + function toInt(color: Color3): number } namespace HSL { /** * Converts a Color3 into a HSL table - * @param {Color3} colour - A Color3 to convert into a HSL table + * @param {Color3} color - A Color3 to convert into a HSL table * @returns {HSL} */ - function toHSL(colour: Color3): HSL + function toHSL(color: Color3): HSL /** * Converts a HSL table into a Color3 @@ -170,10 +180,10 @@ declare namespace ColourUtils { namespace LAB { /** * Converts a Color3 into a LAB table - * @param {Color3} colour - A Color3 to convert into a LAB table + * @param {Color3} color - A Color3 to convert into a LAB table * @returns {LAB} */ - function toLAB(colour: Color3): LAB + function toLAB(color: Color3): LAB /** * Converts a LAB table into a Color3 @@ -181,6 +191,15 @@ declare namespace ColourUtils { * @returns {Color3} */ function fromLAB(lab: LAB): Color3 + + /** + * Interpolates between two Color3s using LAB color space + * @param {Color3} from - The first Color3 to interpolate between + * @param {Color3} to - The second Color3 to interpolate between + * @param {number} alpha - The amount to interpolate between the two colors + * @returns {Color3} + */ + function Lerp(from: Color3, to: Color3, alpha: number): Color3 } namespace LCH { @@ -189,7 +208,7 @@ declare namespace ColourUtils { * @param {Color3} * @returns {LCH} */ - function toLCH(colour: Color3): LCH + function toLCH(color: Color3): LCH /** * Converts a LCH table into a Color3 @@ -201,7 +220,7 @@ declare namespace ColourUtils { namespace APCA { /** - * Calculates the contrast ratio between two colours. The result should be a number between roughly -100 and 100. See {@link https://www.myndex.com/APCA/#general-guidelines-on-levels Myndex's General Guidelines} for more information. + * Calculates the contrast ratio between two colors. The result should be a number between roughly -100 and 100. See {@link https://www.myndex.com/APCA/#general-guidelines-on-levels Myndex's General Guidelines} for more information. * @see https://www.myndex.com/APCA/#general-guidelines-on-levels * @param {Color3} foreground - A Color3 representing the foreground * @param {Color3} background - A Color3 representing the background @@ -226,11 +245,11 @@ declare namespace ColourUtils { LowRed: 2 LowGreen: 4 LowBlue: 6 - LowColour: 8 + LowColor: 8 NoRed: 1 NoGreen: 3 NoBlue: 5 - NoColour: 7 + NoColor: 7 } Group: { Trichroma: 0 @@ -244,12 +263,12 @@ declare namespace ColourUtils { export const Enum: Enums /** - * Simulate colour blindness on a Color3 - * @param {Color3} colour - The Color3 to simulate colour blindness on - * @param {number} blinder - The type of colour blindness to simulate + * Simulate color blindness on a Color3 + * @param {Color3} color - The Color3 to simulate color blindness on + * @param {number} blinder - The type of color blindness to simulate * @returns {Color3} A resulting Color3 from the simulation */ - function Simulate(colour: Color3, blinder: number): Color3 + function Simulate(color: Color3, blinder: number): Color3 } namespace Blend { @@ -294,7 +313,7 @@ declare namespace ColourUtils { function Screen(background: Color3, foreground: Color3): Color3 /** - * Apply transparency to a Color3, based on the background colour + * Apply transparency to a Color3, based on the background color * @param {Color3} background - The bottom Color3 to apply blend to * @param {Color3} foreground - The top Color3 to apply blend to * @param {number} transparency - The transparency to apply (0-1) @@ -352,25 +371,34 @@ declare namespace ColourUtils { function Triadic(base: Color3): Color3[] /** - * Determine the most "vibrant" colour from an array of Color3s + * Determine the most "vibrant" color from an array of Color3s * @param {Color3[]} swatches - An array of Color3s * @param {VibrantOptions} options - Optional dictionary of options to adjust goals - * @returns {Color3} A Color3 matching the most "vibrant" colour + * @returns {Color3} A Color3 matching the most "vibrant" color */ function Vibrant(swatches: Color3[], options?: VibrantOptions): Color3 /** - * Generates a monochromatic palette from a base colour, similar to the + * Generates a monochromatic palette from a base color, similar to the * palettes found in Tailwind CSS * @param {Color3} base - The Color3 to generate palette from * @returns {TailwindPalette} An object containing Color3 values */ function Tailwind(base: Color3): TailwindPalette + + /** + * Given an array of Color3s, returns the color that is + * closest to the given Color3. + * @param {Color3} to - The color to find the nearest color to. + * @param {Color3[]} from - The array of colors to search through. + * @returns {Color3} The nearest color to the given color. + */ + function Nearest(to: Color3, from: Color3[]): Color3 } namespace WCAG { /** - * Calculates the contrast ratio between two colours, using the formula provided by WCAG. The result is a number in the range of 0-21 + * Calculates the contrast ratio between two colors, using the formula provided by WCAG. The result is a number in the range of 0-21 * @param {Color3} foreground - A Color3 representing the foreground * @param {Color3} background - A Color3 representing the background * @returns {number} @@ -384,7 +412,7 @@ declare namespace ColourUtils { * @param {number} ratio - The contrast ratio to use, if not provided a default ratio of 4.5 will be used * @returns {Color3} */ - function GetContrastingColour( + function GetContrastingColor( foreground: Color3, background: Color3, ratio?: number @@ -392,4 +420,4 @@ declare namespace ColourUtils { } } -export = ColourUtils +export = ColorUtils diff --git a/wally.lock b/wally.lock new file mode 100644 index 0000000..3488201 --- /dev/null +++ b/wally.lock @@ -0,0 +1,8 @@ +# This file is automatically @generated by Wally. +# It is not intended for manual editing. +registry = "test" + +[[package]] +name = "csqrl/colour-utils" +version = "1.4.1" +dependencies = [] diff --git a/wally.toml b/wally.toml index 5701e5f..ee8fdb6 100644 --- a/wally.toml +++ b/wally.toml @@ -1,10 +1,5 @@ [package] name = "csqrl/colour-utils" -description = "Colour manipulation utility for Roblox" -version = "1.3.1" -license = "MIT" -authors = ["csqrl (https://github.com/csqrl)"] +version = "1.4.1" registry = "https://github.com/UpliftGames/wally-index" realm = "shared" -exclude = ["**"] -include = ["src", "src/**", "wally.toml", "wally.lock", "default.project.json"]