chore: add ansible backend docker frontend-prep

This commit is contained in:
2026-01-21 13:05:13 +01:00
parent 5a280b6b01
commit 943fe4de7d
14930 changed files with 2341433 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
# Changelog
All notable changes to this project will be documented in this file. See
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.1.1](https://github.com/FortAwesome/react-fontawesome/compare/v3.1.0...v3.1.1) (2025-11-28)
### Bug Fixes
* **WCAG:** allow custom role attribute on svgs like previous versions ([ef4986b](https://github.com/FortAwesome/react-fontawesome/commit/ef4986b06a3ef922b21d12453fc0b8fc62e2bcd0))
### Documentation
* remove irrelevant upgrade guide from 0.1-0.2x ([7d41077](https://github.com/FortAwesome/react-fontawesome/commit/7d4107742ce7d58a239a1b87b7f95606c576c182))
### Chores
* **deps:** fix GH advisory GHSA-5j98-mcp5-4vw2 ([2cd0c3f](https://github.com/FortAwesome/react-fontawesome/commit/2cd0c3f838bb97f9e0f8ec13339cd5ef445f15fe))
* **deps:** regenerate lockfile ([779488e](https://github.com/FortAwesome/react-fontawesome/commit/779488ed84d4ecf18b0aadeb830272a4f2eb5f34))
* **deps:** upgrade all dev deps ([b92e5a7](https://github.com/FortAwesome/react-fontawesome/commit/b92e5a703fedc311f38007fd5e83f3b09145b8d9))
* **release:** explicit registry in publish script ([2aee952](https://github.com/FortAwesome/react-fontawesome/commit/2aee952ec61f00c31e4cfc2893042faac553ee9d))
* **release:** fix semantic release config missing npm plugin ([ebabf46](https://github.com/FortAwesome/react-fontawesome/commit/ebabf46f81dd03cea2d1b429be9253754daca34d))
## [3.1.0](https://github.com/FortAwesome/react-fontawesome/compare/v3.0.2...v3.1.0) (2025-10-03)
### Features
- custom cssPrefix support ([ad42835](https://github.com/FortAwesome/react-fontawesome/commit/ad42835fccc8d5d5eb1af9da4417ad9c51612bd6))
- **layers:** add support for layers with FontAwesomeLayers component ([2c84902](https://github.com/FortAwesome/react-fontawesome/commit/2c84902442bf36a564896ef51d56f3551bf0b303))
### Bug Fixes
- better export path for CustomPrefixProvider ([663cd25](https://github.com/FortAwesome/react-fontawesome/commit/663cd25881af8b631cf2212bb50970be339f9af2))
- **browser-support:** don't use string.replaceAll to fix safari 12 support ([1776e3a](https://github.com/FortAwesome/react-fontawesome/commit/1776e3a35bfc1e0ad17d783036cd16bc3791add3))
### Testing
- **layers:** add unit tests for FontAwesomeLayers ([d31480b](https://github.com/FortAwesome/react-fontawesome/commit/d31480b118855fc727ed1c8a2dd1fdbf9ddc426e))
- **utils:** unit tests for withPrefix utility ([982f649](https://github.com/FortAwesome/react-fontawesome/commit/982f649820d0ea14537d7a21812e561ec4dc8b9d))
### Documentation
- add inline documentation for CustomPrefixProvider ([46f69d4](https://github.com/FortAwesome/react-fontawesome/commit/46f69d4509e71a0db56ac8e90757cde6628fc375))
- remove .env requirement ([c942c6a](https://github.com/FortAwesome/react-fontawesome/commit/c942c6a5f054fa298e8e6d5214635e38fea78e1e))
### Chores
- **release:** use @semantic-release/exec for multi-publish rather than third-party plugin ([5a47e13](https://github.com/FortAwesome/react-fontawesome/commit/5a47e1398b2de84e460b5b666dee884b123fb62e))
## [3.1.0](https://github.com/FortAwesome/react-fontawesome/compare/v3.0.2...v3.1.0) (2025-10-03)
### Features
- custom cssPrefix support ([ad42835](https://github.com/FortAwesome/react-fontawesome/commit/ad42835fccc8d5d5eb1af9da4417ad9c51612bd6))
- **layers:** add support for layers with FontAwesomeLayers component ([2c84902](https://github.com/FortAwesome/react-fontawesome/commit/2c84902442bf36a564896ef51d56f3551bf0b303))
### Bug Fixes
- better export path for CustomPrefixProvider ([663cd25](https://github.com/FortAwesome/react-fontawesome/commit/663cd25881af8b631cf2212bb50970be339f9af2))
- **browser-support:** don't use string.replaceAll to fix safari 12 support ([1776e3a](https://github.com/FortAwesome/react-fontawesome/commit/1776e3a35bfc1e0ad17d783036cd16bc3791add3))
### Testing
- **layers:** add unit tests for FontAwesomeLayers ([d31480b](https://github.com/FortAwesome/react-fontawesome/commit/d31480b118855fc727ed1c8a2dd1fdbf9ddc426e))
- **utils:** unit tests for withPrefix utility ([982f649](https://github.com/FortAwesome/react-fontawesome/commit/982f649820d0ea14537d7a21812e561ec4dc8b9d))
### Documentation
- add inline documentation for CustomPrefixProvider ([46f69d4](https://github.com/FortAwesome/react-fontawesome/commit/46f69d4509e71a0db56ac8e90757cde6628fc375))
- remove .env requirement ([c942c6a](https://github.com/FortAwesome/react-fontawesome/commit/c942c6a5f054fa298e8e6d5214635e38fea78e1e))
### Chores
- **release:** use @semantic-release/exec for multi-publish rather than third-party plugin ([5a47e13](https://github.com/FortAwesome/react-fontawesome/commit/5a47e1398b2de84e460b5b666dee884b123fb62e))
## [3.0.2](https://github.com/FortAwesome/react-fontawesome/compare/v3.0.1...v3.0.2) (2025-09-01)
### Bug Fixes
- **constants:** resolve JSON import errors for vite/remix users ([850a804](https://github.com/FortAwesome/react-fontawesome/commit/850a804011ad4852b10241ecad195b5f7aa46e4e))
- **test:** flaky converter performance test in CI ([8f43f0e](https://github.com/FortAwesome/react-fontawesome/commit/8f43f0eb9a1e853417c9bf901adf7a2c7c372f60))
- **WCAG:** correctly read aria-label and ensure aria-hidden is false when label present ([19ddeb3](https://github.com/FortAwesome/react-fontawesome/commit/19ddeb337e0b3630e8a933e77b5327888c13314d))
### Testing
- **converter:** fix unit test for aria-label handling ([8c49cdc](https://github.com/FortAwesome/react-fontawesome/commit/8c49cdc477eadfbe32a406a069ebdea3da303381))
- remove flaky test ([f9605ab](https://github.com/FortAwesome/react-fontawesome/commit/f9605ab25a402d1da0787eaa96a22bebd9f164a4))
- remove unnecessary test conditionals for v5 ([fd5bf9b](https://github.com/FortAwesome/react-fontawesome/commit/fd5bf9b025c7ba5cbff7da66221ae9e8487499cd))
### Chores
- don't include release notes in release commit ([78ce3f8](https://github.com/FortAwesome/react-fontawesome/commit/78ce3f82df9dab290687a2413def844bdf0c88f6))
- **dx:** integrate semantic-release and commitlint ([de5b958](https://github.com/FortAwesome/react-fontawesome/commit/de5b958305654076b41f8328fed03ec009015921))
- remove dependency on semver ([066019b](https://github.com/FortAwesome/react-fontawesome/commit/066019b30f4983be7189267dd75499f265294759))
- update release config for better changelogs ([7d2c242](https://github.com/FortAwesome/react-fontawesome/commit/7d2c242ff4dc66e33a2d3c2694ed45da479d2b90))
### CI/CD
- **actions:** refactor CI workflow to split some jobs out of matrix ([d0d1fb6](https://github.com/FortAwesome/react-fontawesome/commit/d0d1fb61bc571cb3d476fec57d7b66a4508a1938))
- **actions:** use commitlint github action ([4ab8726](https://github.com/FortAwesome/react-fontawesome/commit/4ab8726ca91799c95cadb2f95334e8a66049c4c6))
- use public npm registry for npm ci ([69ea57b](https://github.com/FortAwesome/react-fontawesome/commit/69ea57b6b411e74ce027612959c113ff3404886e))
---
## [3.0.1](https://github.com/FortAwesome/react-fontawesome/releases/tag/3.0.1) - 2025-08-27
### Bug Fixes
- Added additional module resolution configs in `package.json` (b078d99)
- Refactored SVGCore version checks to use dynamic import to fix #589 (bc7cad0)
---
## [3.0.0](https://github.com/FortAwesome/react-fontawesome/releases/tag/3.0.0) - 2025-08-22
### BREAKING
- Dropped support for end-of-life FontAwesome versions (below v6), Node versions (below 20.x) and React versions (below 18.x)
- Dropped support for browser versions that don't support the ES2020 standard, namely [JavaScript built-in: globalThis](https://caniuse.com/mdn-javascript_builtins_globalthis)
### Changes
- Rewrote the entire library from plain JavaScript to TypeScript
- Replaced `rollup` with `tsup` for providing both ESM and CJS exports from one TypeScript source
- Removed `prop-types` in favour of colocated typings for React component props
- Added better type definitions to each prop including examples of usage
- Upgraded `eslint` from v6 to v9, rewrote config as Flat Config, modernised ESLint config, plugins and rules
- Refactored all unit tests from the deprecated `react-test-renderer` to the industry standard `@testing-library/react`
- Upgraded all other development dependencies to latest versions as of release date
- Optimised `FontAwesomeIcon` by reducing per-render function calls and memory allocations
- Optimised `classList` function by removing runtime semver checks and array operations
- Optimised `converter` with a full rewrite for significant performance increases (~70%)
- Moved inline class strings from `getClassListFromProps` to pre-computed maps
### Bug Fixes
- Fixed accessibility ID generation (`titleId, maskId`) for SSR ensuring a consistent ID across server and client renders (#93, #550, #573)
- Fixed TypeScript errors when styling duotone icons with CSS variables (#509)
- Fixed `aria-hidden` so it is `false` if there is a non-empty `aria-label` attribute (#126)
- Resolved large number of `npm audit` issues by removing and updating dependencies
---
## 0.2.x
**Previous [0.2.x change log available here](https://github.com/FortAwesome/react-fontawesome/blob/0.2.x/CHANGELOG.md)**
---
## 0.1.x
**Previous [0.1.x change log available here](https://github.com/FortAwesome/react-fontawesome/blob/0.1.x/CHANGELOG.md)**
---
@@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <mailto:hello@fontawesome.com>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
@@ -0,0 +1,54 @@
This is the repository for the _official_ Font Awesome React component, _initialized_ by the team behind Font Awesome,
but intended to evolve over time with _community_ contributions.
# Ways to Contribute
## Ask a Question
Trying to figure out how to make it work? Or how to use it in your scenario?
1. Review the [README](README.md)
2. Get familiar with the documentation for the [SVG with JavaScript](https://fontawesome.com/how-to-use/svg-with-js) implementation,
the framework upon which this component is built. Sometimes the answers you need may be there.
3. Post any remaining questions on [StackOverflow](https://stackoverflow.com/questions/tagged/react-fontawesome) with the tag `react-fontawesome`.
## Report a Bug
1. Create a test case that reproduces the unexpected behavior
2. [Open a new issue with this template](https://github.com/FortAwesome/react-fontawesome/issues/new?template=bug-report.md),
and be sure to include a link to the reproduction you made with StackBlitz.
## Submit a Pull Request
Add tests if you add code.
## Everything Else
- [Request a feature](https://github.com/FortAwesome/react-fontawesome/issues/new??title=Feature%20request:feature-name&template=feature-request.md)
- [Request a new icon](https://github.com/FortAwesome/Font-Awesome/issues/new?title=Icon%20request:%20icon-name&template=icon-request.md)
# Project Goals
1. Achieve and maintain feature parity with Font Awesome's [SVG with JavaScript](https://fontawesome.com/how-to-use/svg-with-js) method.
2. Keep with best practices in the React development community.
3. Stay current with major developments in React
4. Maintain a reasonable level of consistency between this component and the other Font Awesome official JavaScript
framework components ([Vue](https://github.com/FortAwesome/vue-fontawesome), [Angular](https://github.com/FortAwesome/angular-fontawesome), [Ember](https://github.com/FortAwesome/react-fontawesome))
5. Sharing responsibility: The Font Awesome team will continue to be involved in ongoing development, hoping to _propel_
the project's momentum as we make _our_ contributions, while minimizing any bottle-necking that may happen as we balance
our own priorities across various projects. Ideally, members of the community will enjoy lending a hand to help keep
the project moving forward by responding to issues, answering questions on StackOverflow, reviewing and merging pull
requests, and publishing npm updates.
# Code of Conduct
We'll contribute according to the [Code of Conduct](CODE_OF_CONDUCT.md).
# Wanted: Core Contributors
We're seeking core contributors to help drive this project. Core contributors:
1. Share these goals
2. Demonstrate competence through contributions
3. Contribute with conduct fitting with our code of conduct
4. Want to make this project awesome
@@ -0,0 +1,67 @@
# Developing React Fontawesome
## Tasks
The following commands are available through `npm run`
| Command | Purpose |
| --------------- | -------------------------------------------------------------- |
| build | Build this project with TSUP |
| format:check | Check formatting of all files with Prettier |
| format:fix | Auto-fix formatting of all files with Prettier |
| format:staged | Auto-fix formatting of current staged files with Prettier |
| lint | Check linting using ESLint |
| lint:commits | Lint commits against conventional-commits specs |
| test | Run tests |
| test:watch | Run tests in 'watch' mode |
| test:prepublish | Run tests against both v6 and v7 peer dependencies |
| validate-types | Validate types and check that TypeScript compiles successfully |
## Releasing a new version
<a name="release"></a>
This project has been configured to use [semantic-release](https://semantic-release.gitbook.io/semantic-release) for automated version management and package publishing. However, we do not run semantic-release in the CI - we prefer to run it locally since each maintainer has their own access tokens for npm and our private PRO registry.
Running semantic-release will:
- analyse our recent commits to determine what the next release version should be according to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and [Semantic Versioning](http://semver.org/)
- set the new version in `package.json` & `package-lock.json`
- generate release notes and update the `CHANGELOG.md` file
- publish the updated package to both public and private npm registries
- create relevant tags and release notes on GitHub
- push release-related changes to GitHub with `chore(release): vX.X.X [skip ci]`
### Release Step-by-step Process
1. Add any new contributors to the `contributors` section in `package.json` (if relevant)
2. Update the `README.md` contributors section (if relevant)
3. Ensure the tests pass with both v6 and v7 peer dependencies:
- `npm run test:prepublish`
4. Build the distributable with `npm run build`
5. Run semantic-release dry-run first to ensure everything looks correct:
- `npx semantic-release --dry-run`
6. If the output of the dry-run looks good, run it for real:
- `npx semantic-release`
7. Check the GitHub repository, npm listing and Cloudsmith packages to ensure everything has published correctly and as expected
8. Go and relax!
## Authenticating with the npm.fontawesome.com registry
Contributors with authorization to publish to npm.fontawesome.com will receive an invite
from a Font Awesome project owner.
1. Respond to the invite in your email
2. Let the owner know when you've setup your account
3. Owner will add you to the team
You can then run:
```
npm login --registry https://npm.fontawesome.com
```
- The username is the "slug" for your Cloudsmith account. For example mine is "rob-madole".
- Enter the password that you setup just a few minutes ago.
- It says that your email is PUBLIC. Pretty sure that's false since the auth is through Cloudsmith.
- This doesn't overwrite your standard login, just adds to your `~/.npmrc`
+19
View File
@@ -0,0 +1,19 @@
Copyright 2018 Fonticons, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+89
View File
@@ -0,0 +1,89 @@
<a href="https://fontawesome.com">
<img align="right" width="100" height="100" alt="Official Javascript Component" src="https://img.fortawesome.com/349cfdf6/official-javascript-component.svg">
</a>
# react-fontawesome
[![npm](https://img.shields.io/npm/v/@fortawesome/react-fontawesome.svg?style=flat-square)](https://www.npmjs.com/package/@fortawesome/react-fontawesome)
> Font Awesome React component using SVG with JS
<!-- toc -->
- [react-fontawesome](#react-fontawesome)
- [Documentation](#documentation)
- [Compatibility](#compatibility)
- [How to Help](#how-to-help)
- [Contributors](#contributors)
- [Releasing this project (only project owners can do this)](#releasing-this-project-only-project-owners-can-do-this)
<!-- tocstop -->
## Documentation
Version 3.0.0 is a major update for `react-fontawesome` with the library being rewritten from plain JS to TypeScript,
amongst a number of performance improvements and optimisations to the `FontAwesomeIcon` React component.
While it is a major update, there should be no breaking changes aside from those noted in the Compatibility section below.
## Compatibility
With the release of FontAwesome v7, we have marked v5 as End-of-Life. Both v6 and v7 will continue to be supported.
In `react-fontawesome v3.0.0` we have also dropped support for End-of-Life versions of React and Node.js as well as IE11 browser support.
If you need to use `react-fontawesome` with legacy versions, please consult the table below.
| React version | react-fontawesome version | FontAwesome Core versions | Node versions |
| ------------- | ------------------------- | ------------------------- | ---------------- |
| >= 18.0.0 | 3.x.x | 6.x, 7.x | 20.x, 22.x, 24.x |
| >= 16.3.0 | 0.2.x | 5.x, 6.x, 7.x | 18.x, 20.x |
| < 16.3.0 | 0.1.x | 5.x, 6.x | 14.x, 16.x |
Official documentation is hosted at fontawesome.com:
[Check it out here](https://docs.fontawesome.com/web/use-with/react)
## How to Help
Review the following docs before diving in:
- [CONTRIBUTING.md](CONTRIBUTING.md)
- [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
And then:
- Check the [existing issues](https://github.com/FortAwesome/react-fontawesome/issues) and see if you can help!
## Contributors
The following contributors have either helped to start this project, have contributed
code, are actively maintaining it (including documentation), or in other ways
being awesome contributors to this project. **We'd like to take a moment to recognize them.**
| Name | GitHub |
| ----------------- | ---------------------------------------------------------- |
| Nate Radebaugh | [@NateRadebaugh](https://github.com/NateRadebaugh) |
| Kirk Ross | [@kirkbross](https://github.com/kirkbross) |
| Prateek Goel | [@prateekgoel](https://github.com/prateekgoel) |
| Naor Torgeman | [@naortor](https://github.com/naortor) |
| Matthew Hand | [@mmhand123](https://github.com/mmhand123) |
| calvinf | [@calvinf](https://github.com/calvinf) |
| Bill Parrott | [@chimericdream](https://github.com/chimericdream) |
| Mike Lynch | [@baelec](https://github.com/baelec) |
| Lukáš Rod | [@rodlukas](https://github.com/rodlukas) |
| Proudust | [@proudust](https://github.com/proudust) |
| Tiago Sousa | [@TiagoPortfolio](https://github.com/TiagoPortfolio) |
| Alexey Victorov | [@AliMamed](https://github.com/AliMamed) |
| Calum Smith | [@cpmsmith](https://github.com/cpmsmith) |
| squiaios | [@squiaios](https://github.com/squiaios) |
| WyvernDrexx | [@WyvernDrexx](https://github.com/WyvernDrexx) |
| Jon Defresne | [@jdufresne](https://github.com/jdufresne) |
| Charles Harwood | [@charles4221](https://github.com/charles4221) |
| Font Awesome Team | [@FortAwesome](https://github.com/orgs/FortAwesome/people) |
If we've missed someone (which is quite likely) submit a Pull Request to us and we'll get it resolved.
## Releasing this project (only project owners can do this)
See [DEVELOPMENT.md](DEVELOPMENT.md#release)
@@ -0,0 +1,35 @@
"use strict";
"use client";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var CustomPrefixProvider_exports = {};
__export(CustomPrefixProvider_exports, {
CustomPrefixProvider: () => CustomPrefixProvider
});
module.exports = __toCommonJS(CustomPrefixProvider_exports);
var import_fontawesome_svg_core = require("@fortawesome/fontawesome-svg-core");
const CustomPrefixProvider = ({
customPrefix
}) => {
import_fontawesome_svg_core.config.cssPrefix = customPrefix;
return null;
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CustomPrefixProvider
});
@@ -0,0 +1,47 @@
interface CustomPrefixProviderProps {
customPrefix: string;
}
/**
* React component that provides a custom CSS prefix for Font Awesome icons.
*
* Use this if your React application uses server-side rendering (e.g. NextJS, Vite/Remix, Astro, etc.)
* to ensure the `cssPrefix` is set correctly in the client-side prior to hydration.
*
* To ensure this works correctly, be sure to render this provider at the top level of your application.
* It has been built with `"use client"` but not as a typical provider that would wrap the application.
* This means you don't have to worry about turning your whole application into a client component when using this provider
* at the top level.
*
* @example
* ```tsx
* // In Next.js App Router - `app/layout.tsx`
* import '@fortawesome/fontawesome-svg-core/styles.css'
* import { config } from '@fortawesome/fontawesome-svg-core'
* import { CustomPrefixProvider } from '@fortawesome/react-fontawesome/CustomPrefixProvider'
*
* const CUSTOM_FA_CSS_PREFIX = 'my-custom-prefix'
*
* config.autoAddCss = false
* // First set the prefix here so it is used during server-side rendering
* config.cssPrefix = CUSTOM_FA_CSS_PREFIX
*
* export default function RootLayout({ children }) {
* return (
* <html>
* {
* // Render the component in isolation before the opening <body> tag
* }
* <CustomPrefixProvider customPrefix={CUSTOM_FA_CSS_PREFIX} />
* <body>
* {children}
* </body>
* </html>
* )
* }
* ```
*
* @returns null - This is a "void" component used purely for side effects.
*/
declare const CustomPrefixProvider: ({ customPrefix, }: CustomPrefixProviderProps) => null;
export { CustomPrefixProvider };
@@ -0,0 +1,47 @@
interface CustomPrefixProviderProps {
customPrefix: string;
}
/**
* React component that provides a custom CSS prefix for Font Awesome icons.
*
* Use this if your React application uses server-side rendering (e.g. NextJS, Vite/Remix, Astro, etc.)
* to ensure the `cssPrefix` is set correctly in the client-side prior to hydration.
*
* To ensure this works correctly, be sure to render this provider at the top level of your application.
* It has been built with `"use client"` but not as a typical provider that would wrap the application.
* This means you don't have to worry about turning your whole application into a client component when using this provider
* at the top level.
*
* @example
* ```tsx
* // In Next.js App Router - `app/layout.tsx`
* import '@fortawesome/fontawesome-svg-core/styles.css'
* import { config } from '@fortawesome/fontawesome-svg-core'
* import { CustomPrefixProvider } from '@fortawesome/react-fontawesome/CustomPrefixProvider'
*
* const CUSTOM_FA_CSS_PREFIX = 'my-custom-prefix'
*
* config.autoAddCss = false
* // First set the prefix here so it is used during server-side rendering
* config.cssPrefix = CUSTOM_FA_CSS_PREFIX
*
* export default function RootLayout({ children }) {
* return (
* <html>
* {
* // Render the component in isolation before the opening <body> tag
* }
* <CustomPrefixProvider customPrefix={CUSTOM_FA_CSS_PREFIX} />
* <body>
* {children}
* </body>
* </html>
* )
* }
* ```
*
* @returns null - This is a "void" component used purely for side effects.
*/
declare const CustomPrefixProvider: ({ customPrefix, }: CustomPrefixProviderProps) => null;
export { CustomPrefixProvider };
@@ -0,0 +1,11 @@
"use client";
import { config } from "@fortawesome/fontawesome-svg-core";
const CustomPrefixProvider = ({
customPrefix
}) => {
config.cssPrefix = customPrefix;
return null;
};
export {
CustomPrefixProvider
};
@@ -0,0 +1,435 @@
'use strict';
var React = require('react');
var fontawesomeSvgCore = require('@fortawesome/fontawesome-svg-core');
var jsxRuntime = require('react/jsx-runtime');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React__default = /*#__PURE__*/_interopDefault(React);
// src/components/FontAwesomeIcon.tsx
// src/utils/camelize.ts
function _isNumerical(object) {
object = object - 0;
return object === object;
}
function camelize(string) {
if (_isNumerical(string)) {
return string;
}
string = string.replace(/[_-]+(.)?/g, (_, chr) => {
return chr ? chr.toUpperCase() : "";
});
return string.charAt(0).toLowerCase() + string.slice(1);
}
// src/converter.ts
function capitalize(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
var styleCache = /* @__PURE__ */ new Map();
var STYLE_CACHE_LIMIT = 1e3;
function styleToObject(style) {
if (styleCache.has(style)) {
return styleCache.get(style);
}
const result = {};
let start = 0;
const len = style.length;
while (start < len) {
const semicolonIndex = style.indexOf(";", start);
const end = semicolonIndex === -1 ? len : semicolonIndex;
const pair = style.slice(start, end).trim();
if (pair) {
const colonIndex = pair.indexOf(":");
if (colonIndex > 0) {
const rawProp = pair.slice(0, colonIndex).trim();
const value = pair.slice(colonIndex + 1).trim();
if (rawProp && value) {
const prop = camelize(rawProp);
result[prop.startsWith("webkit") ? capitalize(prop) : prop] = value;
}
}
}
start = end + 1;
}
if (styleCache.size === STYLE_CACHE_LIMIT) {
const oldestKey = styleCache.keys().next().value;
if (oldestKey) {
styleCache.delete(oldestKey);
}
}
styleCache.set(style, result);
return result;
}
function convert(createElement, element, extraProps = {}) {
if (typeof element === "string") {
return element;
}
const children = (element.children || []).map((child) => {
return convert(createElement, child);
});
const elementAttributes = element.attributes || {};
const attrs = {};
for (const [key, val] of Object.entries(elementAttributes)) {
switch (true) {
case key === "class": {
attrs.className = val;
break;
}
case key === "style": {
attrs.style = styleToObject(String(val));
break;
}
case key.startsWith("aria-"):
case key.startsWith("data-"): {
attrs[key.toLowerCase()] = val;
break;
}
default: {
attrs[camelize(key)] = val;
}
}
}
const {
style: existingStyle,
role: existingRole,
"aria-label": ariaLabel,
...remaining
} = extraProps;
if (existingStyle) {
attrs.style = attrs.style ? { ...attrs.style, ...existingStyle } : existingStyle;
}
if (existingRole) {
attrs.role = existingRole;
}
if (ariaLabel) {
attrs["aria-label"] = ariaLabel;
attrs["aria-hidden"] = "false";
}
return createElement(element.tag, { ...remaining, ...attrs }, ...children);
}
var makeReactConverter = convert.bind(null, React__default.default.createElement);
var useAccessibilityId = (id, hasAccessibleProps) => {
const generatedId = React.useId();
return id || (hasAccessibleProps ? generatedId : void 0);
};
// src/logger.ts
var Logger = class {
constructor(scope = "react-fontawesome") {
this.enabled = false;
let IS_DEV = false;
try {
IS_DEV = typeof process !== "undefined" && process.env.NODE_ENV === "development";
} catch {
}
this.scope = scope;
this.enabled = IS_DEV;
}
/**
* Logs messages to the console if not in production.
* @param args - The message and/or data to log.
*/
log(...args) {
if (!this.enabled) return;
console.log(`[${this.scope}]`, ...args);
}
/**
* Logs warnings to the console if not in production.
* @param args - The warning message and/or data to log.
*/
warn(...args) {
if (!this.enabled) return;
console.warn(`[${this.scope}]`, ...args);
}
/**
* Logs errors to the console if not in production.
* @param args - The error message and/or data to log.
*/
error(...args) {
if (!this.enabled) return;
console.error(`[${this.scope}]`, ...args);
}
};
typeof process !== "undefined" && process.env.FA_VERSION || "7.0.0";
var SVG_CORE_VERSION = (
// @ts-expect-error TS2872 - Expression is always truthy - This is true when v7 of SVGCore is used, but not when v6 is used.
// This is the point of this check - if the property exists on config, we have v7, otherwise we have v6.
// TS is checking this against the dev dependencies which uses v7, so it reports a false error here.
("searchPseudoElementsFullScan" in fontawesomeSvgCore.config ? "7.0.0" : "6.0.0")
);
var IS_VERSION_7_OR_LATER = Number.parseInt(SVG_CORE_VERSION) >= 7;
var DEFAULT_CLASSNAME_PREFIX = "fa";
var ANIMATION_CLASSES = {
beat: "fa-beat",
fade: "fa-fade",
beatFade: "fa-beat-fade",
bounce: "fa-bounce",
shake: "fa-shake",
spin: "fa-spin",
spinPulse: "fa-spin-pulse",
spinReverse: "fa-spin-reverse",
pulse: "fa-pulse"
};
var PULL_CLASSES = {
left: "fa-pull-left",
right: "fa-pull-right"
};
var ROTATE_CLASSES = {
"90": "fa-rotate-90",
"180": "fa-rotate-180",
"270": "fa-rotate-270"
};
var SIZE_CLASSES = {
"2xs": "fa-2xs",
xs: "fa-xs",
sm: "fa-sm",
lg: "fa-lg",
xl: "fa-xl",
"2xl": "fa-2xl",
"1x": "fa-1x",
"2x": "fa-2x",
"3x": "fa-3x",
"4x": "fa-4x",
"5x": "fa-5x",
"6x": "fa-6x",
"7x": "fa-7x",
"8x": "fa-8x",
"9x": "fa-9x",
"10x": "fa-10x"
};
var STYLE_CLASSES = {
border: "fa-border",
/** @deprecated */
fixedWidth: "fa-fw",
flip: "fa-flip",
flipHorizontal: "fa-flip-horizontal",
flipVertical: "fa-flip-vertical",
inverse: "fa-inverse",
rotateBy: "fa-rotate-by",
swapOpacity: "fa-swap-opacity",
widthAuto: "fa-width-auto"
};
var LAYER_CLASSES = {
default: "fa-layers"
};
// src/utils/get-class-list-from-props.ts
function withPrefix(cls) {
const prefix = fontawesomeSvgCore.config.cssPrefix || fontawesomeSvgCore.config.familyPrefix || DEFAULT_CLASSNAME_PREFIX;
return prefix === DEFAULT_CLASSNAME_PREFIX ? cls : cls.replace(
new RegExp(String.raw`(?<=^|\s)${DEFAULT_CLASSNAME_PREFIX}-`, "g"),
`${prefix}-`
);
}
function getClassListFromProps(props) {
const {
beat,
fade,
beatFade,
bounce,
shake,
spin,
spinPulse,
spinReverse,
pulse,
fixedWidth,
inverse,
border,
flip,
size,
rotation,
pull,
swapOpacity,
rotateBy,
widthAuto,
className
} = props;
const result = [];
if (className) result.push(...className.split(" "));
if (beat) result.push(ANIMATION_CLASSES.beat);
if (fade) result.push(ANIMATION_CLASSES.fade);
if (beatFade) result.push(ANIMATION_CLASSES.beatFade);
if (bounce) result.push(ANIMATION_CLASSES.bounce);
if (shake) result.push(ANIMATION_CLASSES.shake);
if (spin) result.push(ANIMATION_CLASSES.spin);
if (spinReverse) result.push(ANIMATION_CLASSES.spinReverse);
if (spinPulse) result.push(ANIMATION_CLASSES.spinPulse);
if (pulse) result.push(ANIMATION_CLASSES.pulse);
if (fixedWidth) result.push(STYLE_CLASSES.fixedWidth);
if (inverse) result.push(STYLE_CLASSES.inverse);
if (border) result.push(STYLE_CLASSES.border);
if (flip === true) result.push(STYLE_CLASSES.flip);
if (flip === "horizontal" || flip === "both") {
result.push(STYLE_CLASSES.flipHorizontal);
}
if (flip === "vertical" || flip === "both") {
result.push(STYLE_CLASSES.flipVertical);
}
if (size !== void 0 && size !== null) result.push(SIZE_CLASSES[size]);
if (rotation !== void 0 && rotation !== null && rotation !== 0) {
result.push(ROTATE_CLASSES[rotation]);
}
if (pull !== void 0 && pull !== null) result.push(PULL_CLASSES[pull]);
if (swapOpacity) result.push(STYLE_CLASSES.swapOpacity);
if (!IS_VERSION_7_OR_LATER) return result;
if (rotateBy) result.push(STYLE_CLASSES.rotateBy);
if (widthAuto) result.push(STYLE_CLASSES.widthAuto);
const prefix = fontawesomeSvgCore.config.cssPrefix || fontawesomeSvgCore.config.familyPrefix || DEFAULT_CLASSNAME_PREFIX;
return prefix === DEFAULT_CLASSNAME_PREFIX ? result : (
// TODO: see if we can achieve custom prefix support without iterating
// eslint-disable-next-line unicorn/no-array-callback-reference
result.map(withPrefix)
);
}
var isIconDefinition = (icon) => typeof icon === "object" && "icon" in icon && !!icon.icon;
function normalizeIconArgs(icon) {
if (!icon) {
return void 0;
}
if (isIconDefinition(icon)) {
return icon;
}
return fontawesomeSvgCore.parse.icon(icon);
}
// src/utils/typed-object-keys.ts
function typedObjectKeys(obj) {
return Object.keys(obj);
}
// src/components/FontAwesomeIcon.tsx
var logger = new Logger("FontAwesomeIcon");
var DEFAULT_PROPS = {
border: false,
className: "",
mask: void 0,
maskId: void 0,
fixedWidth: false,
inverse: false,
flip: false,
icon: void 0,
listItem: false,
pull: void 0,
pulse: false,
rotation: void 0,
rotateBy: false,
size: void 0,
spin: false,
spinPulse: false,
spinReverse: false,
beat: false,
fade: false,
beatFade: false,
bounce: false,
shake: false,
symbol: false,
title: "",
titleId: void 0,
transform: void 0,
swapOpacity: false,
widthAuto: false
};
var DEFAULT_PROP_KEYS = new Set(Object.keys(DEFAULT_PROPS));
var FontAwesomeIcon = React__default.default.forwardRef((props, ref) => {
const allProps = { ...DEFAULT_PROPS, ...props };
const {
icon: iconArgs,
mask: maskArgs,
symbol,
title,
titleId: titleIdFromProps,
maskId: maskIdFromProps,
transform
} = allProps;
const maskId = useAccessibilityId(maskIdFromProps, Boolean(maskArgs));
const titleId = useAccessibilityId(titleIdFromProps, Boolean(title));
const iconLookup = normalizeIconArgs(iconArgs);
if (!iconLookup) {
logger.error("Icon lookup is undefined", iconArgs);
return null;
}
const classList = getClassListFromProps(allProps);
const transformProps = typeof transform === "string" ? fontawesomeSvgCore.parse.transform(transform) : transform;
const normalizedMaskArgs = normalizeIconArgs(maskArgs);
const renderedIcon = fontawesomeSvgCore.icon(iconLookup, {
...classList.length > 0 && { classes: classList },
...transformProps && { transform: transformProps },
...normalizedMaskArgs && { mask: normalizedMaskArgs },
symbol,
title,
titleId,
maskId
});
if (!renderedIcon) {
logger.error("Could not find icon", iconLookup);
return null;
}
const { abstract } = renderedIcon;
const extraProps = { ref };
for (const key of typedObjectKeys(allProps)) {
if (DEFAULT_PROP_KEYS.has(key)) {
continue;
}
extraProps[key] = allProps[key];
}
return makeReactConverter(abstract[0], extraProps);
});
FontAwesomeIcon.displayName = "FontAwesomeIcon";
var DEFAULT_CLASSNAMES = `${LAYER_CLASSES.default} ${STYLE_CLASSES.fixedWidth}`;
var FontAwesomeLayers = ({
children,
className,
size,
...attributes
}) => {
const prefixedDefaultClasses = withPrefix(DEFAULT_CLASSNAMES);
const classes = className ? `${prefixedDefaultClasses} ${className}` : prefixedDefaultClasses;
const element = /* @__PURE__ */ jsxRuntime.jsx("span", { ...attributes, className: classes, children });
if (size) {
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: withPrefix(`fa-${size}`), children: element });
}
return element;
};
var LayersText = ({
text,
className,
inverse,
transform,
style,
...attributes
}) => {
const textAbstractElement = React.useMemo(() => {
const textObject = fontawesomeSvgCore.text(text, {
classes: [
...className?.split(" ") || [],
...inverse ? [STYLE_CLASSES.inverse] : []
],
transform: typeof transform === "string" ? fontawesomeSvgCore.parse.transform(transform) : transform
});
return textObject.abstract[0];
}, [text, transform, className, inverse]);
return makeReactConverter(textAbstractElement, { ...attributes, style });
};
var LayersCounter = ({
count,
className,
style,
...attributes
}) => {
const counterAbstractElement = React.useMemo(
() => fontawesomeSvgCore.counter(count, {
classes: className?.split(" ")
}).abstract[0],
[count, className]
);
return makeReactConverter(counterAbstractElement, { ...attributes, style });
};
exports.FontAwesomeIcon = FontAwesomeIcon;
exports.FontAwesomeLayers = FontAwesomeLayers;
exports.LayersCounter = LayersCounter;
exports.LayersText = LayersText;
@@ -0,0 +1,344 @@
import React, { SVGAttributes, RefAttributes, CSSProperties } from 'react';
import { FlipProp, PullProp, RotateProp, Transform, FaSymbol, IconProp, SizeProp } from '@fortawesome/fontawesome-svg-core';
import * as react_jsx_runtime from 'react/jsx-runtime';
interface AnimationProps {
/**
* Makes the icon spin 360deg clockwise continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin}
*/
spin?: boolean | undefined;
/**
* Makes the icon spin 360deg clockwise in 8 incremental steps.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin}
*/
spinPulse?: boolean | undefined;
/**
* When used in conjunction with {@link spin} or {@link spinPulse}, makes the icon spin in reverse.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin-utilities}
*/
spinReverse?: boolean | undefined;
/**
* @deprecated
* Will be removed in a future version.
* Please use {@link spinPulse} instead.
*
* Makes the icon spin 360deg clockwise in 8 incremental steps.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin-utilities}
*/
pulse?: boolean | undefined;
/**
* Makes the icon scale in and out continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#beat}
*/
beat?: boolean | undefined;
/**
* Makes the icon fade in and out continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#fade}
*/
fade?: boolean | undefined;
/**
* Applies both scaling and fading animations from {@link beat} and {@link fade}.
* @see {@link https://docs.fontawesome.com/web/style/animate#beat-fade}
*/
beatFade?: boolean | undefined;
/**
* Makes the icon bounce up and down.
* @see {@link https://docs.fontawesome.com/web/style/animate#bounce}
*/
bounce?: boolean | undefined;
/**
* Makes the icon shake.
* @see {@link https://docs.fontawesome.com/web/style/animate#shake}
*/
shake?: boolean | undefined;
}
/**
* Adds support for FA's CSS variables to the React `style` prop.
*
* TODO: Move this to `fontawesome-common-types`
* @see https://github.com/FortAwesome/react-fontawesome/pull/581#discussion_r2291185167
*/
interface CSSVariables extends FontFamilyVariables {
'--fa-family'?: string | undefined;
'--fa-style'?: string | undefined;
'--fa-display'?: string | undefined;
'--fa-inverse'?: string | undefined;
'--fa-width'?: string | undefined;
'--fa-li-margin'?: string | undefined;
'--fa-li-width'?: string | undefined;
'--fa-rotate-angle'?: string | undefined;
'--fa-animation-delay'?: string | undefined;
'--fa-animation-direction'?: string | undefined;
'--fa-animation-duration'?: string | undefined;
'--fa-animation-iteration-count'?: string | undefined;
'--fa-animation-timing'?: string | undefined;
'--fa-beat-scale'?: string | undefined;
'--fa-fade-opacity'?: string | undefined;
'--fa-beat-fade-opacity'?: string | undefined;
'--fa-beat-fade-scale'?: string | undefined;
'--fa-flip-x'?: string | undefined;
'--fa-flip-y'?: string | undefined;
'--fa-flip-z'?: string | undefined;
'--fa-flip-angle'?: string | undefined;
'--fa-border-color'?: string | undefined;
'--fa-border-padding'?: string | undefined;
'--fa-border-radius'?: string | undefined;
'--fa-border-style'?: string | undefined;
'--fa-border-width'?: string | undefined;
'--fa-pull-margin'?: string | undefined;
'--fa-stack-z-index'?: string | undefined;
'--fa-primary-color'?: string | undefined;
'--fa-primary-opacity'?: string | undefined;
'--fa-secondary-color'?: string | undefined;
'--fa-secondary-opacity'?: string | undefined;
}
type FontFamilyVariables = {
[K in `--fa-font-${string}`]?: string | undefined;
};
interface TransformProps {
/**
* @deprecated Simply wrap the icon instead, no need to pass this property.
*
* @example
* ```tsx
* <ul className='fa-ul'>
* <li>
* <span className='fa-li'>
* <FontAwesomeIcon icon={['fas', 'check']} />
* </span>
* List item with icon
* </li>
* </ul>
* ```
*
* @see {@link https://docs.fontawesome.com/web/style/lists}
*/
listItem?: boolean | undefined;
/** Flip the icon horizontally, vertically or both. */
flip?: FlipProp | boolean | undefined;
/** Wrap text around the icon by pulling it left or right. */
pull?: PullProp | undefined;
/**
* The rotation property is used to rotate the icon by 90, 180, or 270 degrees.
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#rotation}
*/
rotation?: RotateProp | undefined;
/**
* Custom rotation is used to rotate the icon by a specific number of degrees,
* rather than the standard 90, 180, or 270 degrees available in the `rotation` property.
*
* To use this feature, set `rotateBy` to `true` and provide a CSS variable `--fa-rotate-angle`
* with the desired rotation angle in degrees.
*
* @example
* ```tsx
* <FontAwesomeIcon
* icon="fa-solid fa-coffee"
* rotateBy
* style={{ '--fa-rotate-angle': '329deg' }}
* />
* ```
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#custom-rotation}
* @since 7.0.0
*/
rotateBy?: boolean | undefined;
/**
* Apply a custom transform to the icon either using the built-in {@link Transform} config,
* or a CSS transform string.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#power-transforms}
*/
transform?: string | Transform | undefined;
/**
* The icon should render as an SVG symbol rather than a regular element.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#use-svg-symbols}
*/
symbol?: FaSymbol | undefined;
}
interface FontAwesomeIconProps extends AnimationProps, TransformProps, Omit<SVGAttributes<SVGSVGElement>, 'children' | 'mask' | 'transform'>, RefAttributes<SVGSVGElement> {
/**
* The icon to render.
* @see {@link https://docs.fontawesome.com/web/use-with/react/add-icons}
*/
icon: IconProp;
/** The size of the icon from a predefined set of sizes. */
size?: SizeProp | undefined;
/**
* Grab the Mask utility when you want to layer two icons but have the inner icon cut out from the icon below so the parent elements background shows through.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#mask}
*/
mask?: IconProp | undefined;
/** Accessibility ID for the mask element */
maskId?: string | undefined;
/** Any additional CSS classes to apply to the icon */
className?: string | undefined;
/** The color of the icon. Can be any valid CSS color value */
color?: string | undefined;
/**
* Applies a border to the icon
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#bordered-icons}
*/
border?: boolean | undefined;
/**
* @deprecated
* @since 7.0.0
*
* Starting in FontAwesome 7.0.0, all icons are fixed width by default.
* This property will be removed in a future version.
*
* If you want to remove the fixed width to replicate the behavior of
* previous versions, you can set the new {@link widthAuto} property to `true`.
*
* @see {@link FontAwesomeIconProps.widthAuto}
*/
fixedWidth?: boolean | undefined;
/**
* Invert the icon color.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#invert-the-icon-color-to-white}
*/
inverse?: boolean | undefined;
/** Any custom styles or CSS variable overrides for the icon element. */
style?: (CSSProperties & CSSVariables) | undefined;
tabIndex?: number | undefined;
/** An accessibility title for the icon to be read by screen-readers or assistive technologies. */
title?: string | undefined;
/** A unique ID for the accessibility title element. */
titleId?: string | undefined;
/**
* When using Duotone icons, this property will swap the opacity of the two colors.
* The first color will be rendered with the opacity of the second color, and vice versa
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#duotone-icons}
*/
swapOpacity?: boolean | undefined;
/**
* When set to `true`, the icon will automatically adjust its width to
* only the interior symbol and not the entire Icon Canvas.
*
* @see {@link https://docs.fontawesome.com/web/style/icon-canvas}
* @since 7.0.0
*/
widthAuto?: boolean | undefined;
}
/**
* FontAwesomeIcon component.
*/
declare const FontAwesomeIcon: React.ForwardRefExoticComponent<Omit<FontAwesomeIconProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
type Attributes = React.HTMLAttributes<HTMLSpanElement>;
interface FontAwesomeLayersProps extends Attributes {
children: React.ReactNode;
className?: string | undefined;
size?: SizeProp | undefined;
}
/**
* React Component that allows you to stack multiple Font Awesome icons on top of each other,
* or to layer with text or a counter.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/react-fontawesome'
* import { faBookmark, faCircle, faCheck, faHeart, faMoon, faPlay, faStar, faSun } from '@fortawesome/free-solid-svg-icons'
*
* // React versions of the examples from the FontAwesome Web Docs
* export const Examples = () => (
* <div className="fa-4x">
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCircle} color="tomato" />
* <FontAwesomeIcon icon={faCheck} inverse transform="shrink-6" />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faBookmark} />
* <FontAwesomeIcon icon={faHeart} color="tomato" transform="shrink-10 up-2" />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faPlay} transform="rotate--90 grow-4" />
* <FontAwesomeIcon icon={faSun} inverse transform="shrink-10 up-2" />
* <FontAwesomeIcon icon={faMoon} inverse transform="shrink-11 down-4.2 left-4" />
* <FontAwesomeIcon icon={faStar} inverse transform="shrink-11 down-4.2 right-4" />
* </FontAwesomeLayers>
* </div>
* )
* ```
*
* For examples using Text or Counter components:
* @see {@link LayersText}
* @see {@link LayersCounter}
*/
declare const FontAwesomeLayers: ({ children, className, size, ...attributes }: FontAwesomeLayersProps) => react_jsx_runtime.JSX.Element;
/**
* Text component to be used within a `FontAwesomeLayers` component.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeLayers, LayersText } from '@fortawesome/react-fontawesome'
* import { faCalendar, faCertificate } from '@fortawesome/free-solid-svg-icons'
*
* // React versions of the examples from the FontAwesome Web Docs
* export const Examples = () => (
* <div className="fa-4x">
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCalendar} />
* <LayersText
* text="27"
* inverse
* style={{ fontWeight: '900' }}
* transform="shrink-8 down-3"
* />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCertificate} />
* <LayersText
* text="NEW"
* inverse
* style={{ fontWeight: '900' }}
* transform="shrink-11.5 rotate--30"
* />
* </FontAwesomeLayers>
* </div>
* )
* ```
*/
declare const LayersText: ({ text, className, inverse, transform, style, ...attributes }: Attributes & {
text: string;
className?: string | undefined;
inverse?: boolean | undefined;
transform?: string | Transform | undefined;
style?: (React.CSSProperties & CSSVariables) | undefined;
}) => React.JSX.Element;
/**
* Counter component to be used within a `FontAwesomeLayers` component.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeLayers, LayersCounter } from '@fortawesome/react-fontawesome'
* import { faEnvelope } from '@fortawesome/free-solid-svg-icons'
*
* // React version of the example from the FontAwesome Web Docs
* export const Example = ({ count = 1419 }) => (
* <FontAwesomeLayers size="4x">
* <FontAwesomeIcon icon={faEnvelope} />
* <LayersCounter count={count.toLocaleString()} style={{ backgroundColor: 'tomato' }} />
* </FontAwesomeLayers>
* )
* ```
*/
declare const LayersCounter: ({ count, className, style, ...attributes }: Attributes & {
count: number | string;
className?: string | undefined;
style?: (React.CSSProperties & CSSVariables) | undefined;
}) => React.JSX.Element;
export { type AnimationProps, FontAwesomeIcon, type FontAwesomeIconProps, FontAwesomeLayers, LayersCounter, LayersText, type TransformProps };
@@ -0,0 +1,344 @@
import React, { SVGAttributes, RefAttributes, CSSProperties } from 'react';
import { FlipProp, PullProp, RotateProp, Transform, FaSymbol, IconProp, SizeProp } from '@fortawesome/fontawesome-svg-core';
import * as react_jsx_runtime from 'react/jsx-runtime';
interface AnimationProps {
/**
* Makes the icon spin 360deg clockwise continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin}
*/
spin?: boolean | undefined;
/**
* Makes the icon spin 360deg clockwise in 8 incremental steps.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin}
*/
spinPulse?: boolean | undefined;
/**
* When used in conjunction with {@link spin} or {@link spinPulse}, makes the icon spin in reverse.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin-utilities}
*/
spinReverse?: boolean | undefined;
/**
* @deprecated
* Will be removed in a future version.
* Please use {@link spinPulse} instead.
*
* Makes the icon spin 360deg clockwise in 8 incremental steps.
* @see {@link https://docs.fontawesome.com/web/style/animate#spin-utilities}
*/
pulse?: boolean | undefined;
/**
* Makes the icon scale in and out continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#beat}
*/
beat?: boolean | undefined;
/**
* Makes the icon fade in and out continuously.
* @see {@link https://docs.fontawesome.com/web/style/animate#fade}
*/
fade?: boolean | undefined;
/**
* Applies both scaling and fading animations from {@link beat} and {@link fade}.
* @see {@link https://docs.fontawesome.com/web/style/animate#beat-fade}
*/
beatFade?: boolean | undefined;
/**
* Makes the icon bounce up and down.
* @see {@link https://docs.fontawesome.com/web/style/animate#bounce}
*/
bounce?: boolean | undefined;
/**
* Makes the icon shake.
* @see {@link https://docs.fontawesome.com/web/style/animate#shake}
*/
shake?: boolean | undefined;
}
/**
* Adds support for FA's CSS variables to the React `style` prop.
*
* TODO: Move this to `fontawesome-common-types`
* @see https://github.com/FortAwesome/react-fontawesome/pull/581#discussion_r2291185167
*/
interface CSSVariables extends FontFamilyVariables {
'--fa-family'?: string | undefined;
'--fa-style'?: string | undefined;
'--fa-display'?: string | undefined;
'--fa-inverse'?: string | undefined;
'--fa-width'?: string | undefined;
'--fa-li-margin'?: string | undefined;
'--fa-li-width'?: string | undefined;
'--fa-rotate-angle'?: string | undefined;
'--fa-animation-delay'?: string | undefined;
'--fa-animation-direction'?: string | undefined;
'--fa-animation-duration'?: string | undefined;
'--fa-animation-iteration-count'?: string | undefined;
'--fa-animation-timing'?: string | undefined;
'--fa-beat-scale'?: string | undefined;
'--fa-fade-opacity'?: string | undefined;
'--fa-beat-fade-opacity'?: string | undefined;
'--fa-beat-fade-scale'?: string | undefined;
'--fa-flip-x'?: string | undefined;
'--fa-flip-y'?: string | undefined;
'--fa-flip-z'?: string | undefined;
'--fa-flip-angle'?: string | undefined;
'--fa-border-color'?: string | undefined;
'--fa-border-padding'?: string | undefined;
'--fa-border-radius'?: string | undefined;
'--fa-border-style'?: string | undefined;
'--fa-border-width'?: string | undefined;
'--fa-pull-margin'?: string | undefined;
'--fa-stack-z-index'?: string | undefined;
'--fa-primary-color'?: string | undefined;
'--fa-primary-opacity'?: string | undefined;
'--fa-secondary-color'?: string | undefined;
'--fa-secondary-opacity'?: string | undefined;
}
type FontFamilyVariables = {
[K in `--fa-font-${string}`]?: string | undefined;
};
interface TransformProps {
/**
* @deprecated Simply wrap the icon instead, no need to pass this property.
*
* @example
* ```tsx
* <ul className='fa-ul'>
* <li>
* <span className='fa-li'>
* <FontAwesomeIcon icon={['fas', 'check']} />
* </span>
* List item with icon
* </li>
* </ul>
* ```
*
* @see {@link https://docs.fontawesome.com/web/style/lists}
*/
listItem?: boolean | undefined;
/** Flip the icon horizontally, vertically or both. */
flip?: FlipProp | boolean | undefined;
/** Wrap text around the icon by pulling it left or right. */
pull?: PullProp | undefined;
/**
* The rotation property is used to rotate the icon by 90, 180, or 270 degrees.
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#rotation}
*/
rotation?: RotateProp | undefined;
/**
* Custom rotation is used to rotate the icon by a specific number of degrees,
* rather than the standard 90, 180, or 270 degrees available in the `rotation` property.
*
* To use this feature, set `rotateBy` to `true` and provide a CSS variable `--fa-rotate-angle`
* with the desired rotation angle in degrees.
*
* @example
* ```tsx
* <FontAwesomeIcon
* icon="fa-solid fa-coffee"
* rotateBy
* style={{ '--fa-rotate-angle': '329deg' }}
* />
* ```
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#custom-rotation}
* @since 7.0.0
*/
rotateBy?: boolean | undefined;
/**
* Apply a custom transform to the icon either using the built-in {@link Transform} config,
* or a CSS transform string.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#power-transforms}
*/
transform?: string | Transform | undefined;
/**
* The icon should render as an SVG symbol rather than a regular element.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#use-svg-symbols}
*/
symbol?: FaSymbol | undefined;
}
interface FontAwesomeIconProps extends AnimationProps, TransformProps, Omit<SVGAttributes<SVGSVGElement>, 'children' | 'mask' | 'transform'>, RefAttributes<SVGSVGElement> {
/**
* The icon to render.
* @see {@link https://docs.fontawesome.com/web/use-with/react/add-icons}
*/
icon: IconProp;
/** The size of the icon from a predefined set of sizes. */
size?: SizeProp | undefined;
/**
* Grab the Mask utility when you want to layer two icons but have the inner icon cut out from the icon below so the parent elements background shows through.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#mask}
*/
mask?: IconProp | undefined;
/** Accessibility ID for the mask element */
maskId?: string | undefined;
/** Any additional CSS classes to apply to the icon */
className?: string | undefined;
/** The color of the icon. Can be any valid CSS color value */
color?: string | undefined;
/**
* Applies a border to the icon
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#bordered-icons}
*/
border?: boolean | undefined;
/**
* @deprecated
* @since 7.0.0
*
* Starting in FontAwesome 7.0.0, all icons are fixed width by default.
* This property will be removed in a future version.
*
* If you want to remove the fixed width to replicate the behavior of
* previous versions, you can set the new {@link widthAuto} property to `true`.
*
* @see {@link FontAwesomeIconProps.widthAuto}
*/
fixedWidth?: boolean | undefined;
/**
* Invert the icon color.
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#invert-the-icon-color-to-white}
*/
inverse?: boolean | undefined;
/** Any custom styles or CSS variable overrides for the icon element. */
style?: (CSSProperties & CSSVariables) | undefined;
tabIndex?: number | undefined;
/** An accessibility title for the icon to be read by screen-readers or assistive technologies. */
title?: string | undefined;
/** A unique ID for the accessibility title element. */
titleId?: string | undefined;
/**
* When using Duotone icons, this property will swap the opacity of the two colors.
* The first color will be rendered with the opacity of the second color, and vice versa
*
* @see {@link https://docs.fontawesome.com/web/use-with/react/style#duotone-icons}
*/
swapOpacity?: boolean | undefined;
/**
* When set to `true`, the icon will automatically adjust its width to
* only the interior symbol and not the entire Icon Canvas.
*
* @see {@link https://docs.fontawesome.com/web/style/icon-canvas}
* @since 7.0.0
*/
widthAuto?: boolean | undefined;
}
/**
* FontAwesomeIcon component.
*/
declare const FontAwesomeIcon: React.ForwardRefExoticComponent<Omit<FontAwesomeIconProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
type Attributes = React.HTMLAttributes<HTMLSpanElement>;
interface FontAwesomeLayersProps extends Attributes {
children: React.ReactNode;
className?: string | undefined;
size?: SizeProp | undefined;
}
/**
* React Component that allows you to stack multiple Font Awesome icons on top of each other,
* or to layer with text or a counter.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/react-fontawesome'
* import { faBookmark, faCircle, faCheck, faHeart, faMoon, faPlay, faStar, faSun } from '@fortawesome/free-solid-svg-icons'
*
* // React versions of the examples from the FontAwesome Web Docs
* export const Examples = () => (
* <div className="fa-4x">
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCircle} color="tomato" />
* <FontAwesomeIcon icon={faCheck} inverse transform="shrink-6" />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faBookmark} />
* <FontAwesomeIcon icon={faHeart} color="tomato" transform="shrink-10 up-2" />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faPlay} transform="rotate--90 grow-4" />
* <FontAwesomeIcon icon={faSun} inverse transform="shrink-10 up-2" />
* <FontAwesomeIcon icon={faMoon} inverse transform="shrink-11 down-4.2 left-4" />
* <FontAwesomeIcon icon={faStar} inverse transform="shrink-11 down-4.2 right-4" />
* </FontAwesomeLayers>
* </div>
* )
* ```
*
* For examples using Text or Counter components:
* @see {@link LayersText}
* @see {@link LayersCounter}
*/
declare const FontAwesomeLayers: ({ children, className, size, ...attributes }: FontAwesomeLayersProps) => react_jsx_runtime.JSX.Element;
/**
* Text component to be used within a `FontAwesomeLayers` component.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeLayers, LayersText } from '@fortawesome/react-fontawesome'
* import { faCalendar, faCertificate } from '@fortawesome/free-solid-svg-icons'
*
* // React versions of the examples from the FontAwesome Web Docs
* export const Examples = () => (
* <div className="fa-4x">
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCalendar} />
* <LayersText
* text="27"
* inverse
* style={{ fontWeight: '900' }}
* transform="shrink-8 down-3"
* />
* </FontAwesomeLayers>
* <FontAwesomeLayers>
* <FontAwesomeIcon icon={faCertificate} />
* <LayersText
* text="NEW"
* inverse
* style={{ fontWeight: '900' }}
* transform="shrink-11.5 rotate--30"
* />
* </FontAwesomeLayers>
* </div>
* )
* ```
*/
declare const LayersText: ({ text, className, inverse, transform, style, ...attributes }: Attributes & {
text: string;
className?: string | undefined;
inverse?: boolean | undefined;
transform?: string | Transform | undefined;
style?: (React.CSSProperties & CSSVariables) | undefined;
}) => React.JSX.Element;
/**
* Counter component to be used within a `FontAwesomeLayers` component.
*
* @see https://docs.fontawesome.com/web/style/layer
*
* @example
* ```tsx
* import { FontAwesomeLayers, LayersCounter } from '@fortawesome/react-fontawesome'
* import { faEnvelope } from '@fortawesome/free-solid-svg-icons'
*
* // React version of the example from the FontAwesome Web Docs
* export const Example = ({ count = 1419 }) => (
* <FontAwesomeLayers size="4x">
* <FontAwesomeIcon icon={faEnvelope} />
* <LayersCounter count={count.toLocaleString()} style={{ backgroundColor: 'tomato' }} />
* </FontAwesomeLayers>
* )
* ```
*/
declare const LayersCounter: ({ count, className, style, ...attributes }: Attributes & {
count: number | string;
className?: string | undefined;
style?: (React.CSSProperties & CSSVariables) | undefined;
}) => React.JSX.Element;
export { type AnimationProps, FontAwesomeIcon, type FontAwesomeIconProps, FontAwesomeLayers, LayersCounter, LayersText, type TransformProps };
+426
View File
@@ -0,0 +1,426 @@
import React, { useId, useMemo } from 'react';
import { parse, icon, config, text, counter } from '@fortawesome/fontawesome-svg-core';
import { jsx } from 'react/jsx-runtime';
// src/components/FontAwesomeIcon.tsx
// src/utils/camelize.ts
function _isNumerical(object) {
object = object - 0;
return object === object;
}
function camelize(string) {
if (_isNumerical(string)) {
return string;
}
string = string.replace(/[_-]+(.)?/g, (_, chr) => {
return chr ? chr.toUpperCase() : "";
});
return string.charAt(0).toLowerCase() + string.slice(1);
}
// src/converter.ts
function capitalize(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
var styleCache = /* @__PURE__ */ new Map();
var STYLE_CACHE_LIMIT = 1e3;
function styleToObject(style) {
if (styleCache.has(style)) {
return styleCache.get(style);
}
const result = {};
let start = 0;
const len = style.length;
while (start < len) {
const semicolonIndex = style.indexOf(";", start);
const end = semicolonIndex === -1 ? len : semicolonIndex;
const pair = style.slice(start, end).trim();
if (pair) {
const colonIndex = pair.indexOf(":");
if (colonIndex > 0) {
const rawProp = pair.slice(0, colonIndex).trim();
const value = pair.slice(colonIndex + 1).trim();
if (rawProp && value) {
const prop = camelize(rawProp);
result[prop.startsWith("webkit") ? capitalize(prop) : prop] = value;
}
}
}
start = end + 1;
}
if (styleCache.size === STYLE_CACHE_LIMIT) {
const oldestKey = styleCache.keys().next().value;
if (oldestKey) {
styleCache.delete(oldestKey);
}
}
styleCache.set(style, result);
return result;
}
function convert(createElement, element, extraProps = {}) {
if (typeof element === "string") {
return element;
}
const children = (element.children || []).map((child) => {
return convert(createElement, child);
});
const elementAttributes = element.attributes || {};
const attrs = {};
for (const [key, val] of Object.entries(elementAttributes)) {
switch (true) {
case key === "class": {
attrs.className = val;
break;
}
case key === "style": {
attrs.style = styleToObject(String(val));
break;
}
case key.startsWith("aria-"):
case key.startsWith("data-"): {
attrs[key.toLowerCase()] = val;
break;
}
default: {
attrs[camelize(key)] = val;
}
}
}
const {
style: existingStyle,
role: existingRole,
"aria-label": ariaLabel,
...remaining
} = extraProps;
if (existingStyle) {
attrs.style = attrs.style ? { ...attrs.style, ...existingStyle } : existingStyle;
}
if (existingRole) {
attrs.role = existingRole;
}
if (ariaLabel) {
attrs["aria-label"] = ariaLabel;
attrs["aria-hidden"] = "false";
}
return createElement(element.tag, { ...remaining, ...attrs }, ...children);
}
var makeReactConverter = convert.bind(null, React.createElement);
var useAccessibilityId = (id, hasAccessibleProps) => {
const generatedId = useId();
return id || (hasAccessibleProps ? generatedId : void 0);
};
// src/logger.ts
var Logger = class {
constructor(scope = "react-fontawesome") {
this.enabled = false;
let IS_DEV = false;
try {
IS_DEV = typeof process !== "undefined" && process.env.NODE_ENV === "development";
} catch {
}
this.scope = scope;
this.enabled = IS_DEV;
}
/**
* Logs messages to the console if not in production.
* @param args - The message and/or data to log.
*/
log(...args) {
if (!this.enabled) return;
console.log(`[${this.scope}]`, ...args);
}
/**
* Logs warnings to the console if not in production.
* @param args - The warning message and/or data to log.
*/
warn(...args) {
if (!this.enabled) return;
console.warn(`[${this.scope}]`, ...args);
}
/**
* Logs errors to the console if not in production.
* @param args - The error message and/or data to log.
*/
error(...args) {
if (!this.enabled) return;
console.error(`[${this.scope}]`, ...args);
}
};
typeof process !== "undefined" && process.env.FA_VERSION || "7.0.0";
var SVG_CORE_VERSION = (
// @ts-expect-error TS2872 - Expression is always truthy - This is true when v7 of SVGCore is used, but not when v6 is used.
// This is the point of this check - if the property exists on config, we have v7, otherwise we have v6.
// TS is checking this against the dev dependencies which uses v7, so it reports a false error here.
("searchPseudoElementsFullScan" in config ? "7.0.0" : "6.0.0")
);
var IS_VERSION_7_OR_LATER = Number.parseInt(SVG_CORE_VERSION) >= 7;
var DEFAULT_CLASSNAME_PREFIX = "fa";
var ANIMATION_CLASSES = {
beat: "fa-beat",
fade: "fa-fade",
beatFade: "fa-beat-fade",
bounce: "fa-bounce",
shake: "fa-shake",
spin: "fa-spin",
spinPulse: "fa-spin-pulse",
spinReverse: "fa-spin-reverse",
pulse: "fa-pulse"
};
var PULL_CLASSES = {
left: "fa-pull-left",
right: "fa-pull-right"
};
var ROTATE_CLASSES = {
"90": "fa-rotate-90",
"180": "fa-rotate-180",
"270": "fa-rotate-270"
};
var SIZE_CLASSES = {
"2xs": "fa-2xs",
xs: "fa-xs",
sm: "fa-sm",
lg: "fa-lg",
xl: "fa-xl",
"2xl": "fa-2xl",
"1x": "fa-1x",
"2x": "fa-2x",
"3x": "fa-3x",
"4x": "fa-4x",
"5x": "fa-5x",
"6x": "fa-6x",
"7x": "fa-7x",
"8x": "fa-8x",
"9x": "fa-9x",
"10x": "fa-10x"
};
var STYLE_CLASSES = {
border: "fa-border",
/** @deprecated */
fixedWidth: "fa-fw",
flip: "fa-flip",
flipHorizontal: "fa-flip-horizontal",
flipVertical: "fa-flip-vertical",
inverse: "fa-inverse",
rotateBy: "fa-rotate-by",
swapOpacity: "fa-swap-opacity",
widthAuto: "fa-width-auto"
};
var LAYER_CLASSES = {
default: "fa-layers"
};
// src/utils/get-class-list-from-props.ts
function withPrefix(cls) {
const prefix = config.cssPrefix || config.familyPrefix || DEFAULT_CLASSNAME_PREFIX;
return prefix === DEFAULT_CLASSNAME_PREFIX ? cls : cls.replace(
new RegExp(String.raw`(?<=^|\s)${DEFAULT_CLASSNAME_PREFIX}-`, "g"),
`${prefix}-`
);
}
function getClassListFromProps(props) {
const {
beat,
fade,
beatFade,
bounce,
shake,
spin,
spinPulse,
spinReverse,
pulse,
fixedWidth,
inverse,
border,
flip,
size,
rotation,
pull,
swapOpacity,
rotateBy,
widthAuto,
className
} = props;
const result = [];
if (className) result.push(...className.split(" "));
if (beat) result.push(ANIMATION_CLASSES.beat);
if (fade) result.push(ANIMATION_CLASSES.fade);
if (beatFade) result.push(ANIMATION_CLASSES.beatFade);
if (bounce) result.push(ANIMATION_CLASSES.bounce);
if (shake) result.push(ANIMATION_CLASSES.shake);
if (spin) result.push(ANIMATION_CLASSES.spin);
if (spinReverse) result.push(ANIMATION_CLASSES.spinReverse);
if (spinPulse) result.push(ANIMATION_CLASSES.spinPulse);
if (pulse) result.push(ANIMATION_CLASSES.pulse);
if (fixedWidth) result.push(STYLE_CLASSES.fixedWidth);
if (inverse) result.push(STYLE_CLASSES.inverse);
if (border) result.push(STYLE_CLASSES.border);
if (flip === true) result.push(STYLE_CLASSES.flip);
if (flip === "horizontal" || flip === "both") {
result.push(STYLE_CLASSES.flipHorizontal);
}
if (flip === "vertical" || flip === "both") {
result.push(STYLE_CLASSES.flipVertical);
}
if (size !== void 0 && size !== null) result.push(SIZE_CLASSES[size]);
if (rotation !== void 0 && rotation !== null && rotation !== 0) {
result.push(ROTATE_CLASSES[rotation]);
}
if (pull !== void 0 && pull !== null) result.push(PULL_CLASSES[pull]);
if (swapOpacity) result.push(STYLE_CLASSES.swapOpacity);
if (!IS_VERSION_7_OR_LATER) return result;
if (rotateBy) result.push(STYLE_CLASSES.rotateBy);
if (widthAuto) result.push(STYLE_CLASSES.widthAuto);
const prefix = config.cssPrefix || config.familyPrefix || DEFAULT_CLASSNAME_PREFIX;
return prefix === DEFAULT_CLASSNAME_PREFIX ? result : (
// TODO: see if we can achieve custom prefix support without iterating
// eslint-disable-next-line unicorn/no-array-callback-reference
result.map(withPrefix)
);
}
var isIconDefinition = (icon) => typeof icon === "object" && "icon" in icon && !!icon.icon;
function normalizeIconArgs(icon) {
if (!icon) {
return void 0;
}
if (isIconDefinition(icon)) {
return icon;
}
return parse.icon(icon);
}
// src/utils/typed-object-keys.ts
function typedObjectKeys(obj) {
return Object.keys(obj);
}
// src/components/FontAwesomeIcon.tsx
var logger = new Logger("FontAwesomeIcon");
var DEFAULT_PROPS = {
border: false,
className: "",
mask: void 0,
maskId: void 0,
fixedWidth: false,
inverse: false,
flip: false,
icon: void 0,
listItem: false,
pull: void 0,
pulse: false,
rotation: void 0,
rotateBy: false,
size: void 0,
spin: false,
spinPulse: false,
spinReverse: false,
beat: false,
fade: false,
beatFade: false,
bounce: false,
shake: false,
symbol: false,
title: "",
titleId: void 0,
transform: void 0,
swapOpacity: false,
widthAuto: false
};
var DEFAULT_PROP_KEYS = new Set(Object.keys(DEFAULT_PROPS));
var FontAwesomeIcon = React.forwardRef((props, ref) => {
const allProps = { ...DEFAULT_PROPS, ...props };
const {
icon: iconArgs,
mask: maskArgs,
symbol,
title,
titleId: titleIdFromProps,
maskId: maskIdFromProps,
transform
} = allProps;
const maskId = useAccessibilityId(maskIdFromProps, Boolean(maskArgs));
const titleId = useAccessibilityId(titleIdFromProps, Boolean(title));
const iconLookup = normalizeIconArgs(iconArgs);
if (!iconLookup) {
logger.error("Icon lookup is undefined", iconArgs);
return null;
}
const classList = getClassListFromProps(allProps);
const transformProps = typeof transform === "string" ? parse.transform(transform) : transform;
const normalizedMaskArgs = normalizeIconArgs(maskArgs);
const renderedIcon = icon(iconLookup, {
...classList.length > 0 && { classes: classList },
...transformProps && { transform: transformProps },
...normalizedMaskArgs && { mask: normalizedMaskArgs },
symbol,
title,
titleId,
maskId
});
if (!renderedIcon) {
logger.error("Could not find icon", iconLookup);
return null;
}
const { abstract } = renderedIcon;
const extraProps = { ref };
for (const key of typedObjectKeys(allProps)) {
if (DEFAULT_PROP_KEYS.has(key)) {
continue;
}
extraProps[key] = allProps[key];
}
return makeReactConverter(abstract[0], extraProps);
});
FontAwesomeIcon.displayName = "FontAwesomeIcon";
var DEFAULT_CLASSNAMES = `${LAYER_CLASSES.default} ${STYLE_CLASSES.fixedWidth}`;
var FontAwesomeLayers = ({
children,
className,
size,
...attributes
}) => {
const prefixedDefaultClasses = withPrefix(DEFAULT_CLASSNAMES);
const classes = className ? `${prefixedDefaultClasses} ${className}` : prefixedDefaultClasses;
const element = /* @__PURE__ */ jsx("span", { ...attributes, className: classes, children });
if (size) {
return /* @__PURE__ */ jsx("div", { className: withPrefix(`fa-${size}`), children: element });
}
return element;
};
var LayersText = ({
text: text$1,
className,
inverse,
transform,
style,
...attributes
}) => {
const textAbstractElement = useMemo(() => {
const textObject = text(text$1, {
classes: [
...className?.split(" ") || [],
...inverse ? [STYLE_CLASSES.inverse] : []
],
transform: typeof transform === "string" ? parse.transform(transform) : transform
});
return textObject.abstract[0];
}, [text$1, transform, className, inverse]);
return makeReactConverter(textAbstractElement, { ...attributes, style });
};
var LayersCounter = ({
count,
className,
style,
...attributes
}) => {
const counterAbstractElement = useMemo(
() => counter(count, {
classes: className?.split(" ")
}).abstract[0],
[count, className]
);
return makeReactConverter(counterAbstractElement, { ...attributes, style });
};
export { FontAwesomeIcon, FontAwesomeLayers, LayersCounter, LayersText };
+158
View File
@@ -0,0 +1,158 @@
{
"name": "@fortawesome/react-fontawesome",
"description": "Official React component for Font Awesome",
"version": "3.1.1",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"jsnext:main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
},
"./CustomPrefixProvider": {
"types": "./dist/CustomPrefixProvider.d.ts",
"import": "./dist/CustomPrefixProvider.js",
"require": "./dist/CustomPrefixProvider.cjs",
"default": "./dist/CustomPrefixProvider.js"
},
"./package.json": "./package.json"
},
"homepage": "https://github.com/FortAwesome/react-fontawesome",
"repository": {
"type": "git",
"url": "git+https://github.com/FortAwesome/react-fontawesome.git"
},
"bugs": {
"url": "https://github.com/FortAwesome/react-fontawesome/issues"
},
"contributors": [
"Travis Chase <travis@fontawesome.com>",
"Rob Madole <rob@fontawesome.com>",
"Mike Wilkerson <mwilkerson@gmail.com>",
"Nate Radebaugh <github.com/NateRadebaugh>",
"Kirk Ross <github.com/kirkbross>",
"Prateek Goel <github.com/prateekgoel>",
"Naor Torgeman <github.com/naortor>",
"Matthew Hand <github.com/mmhand123>",
"Calvin Freitas <github.com/calvinf>",
"Bill Parrott <github.com/chimericdream>",
"Mike Lynch <github.com/baelec>",
"Lukáš Rod <github.com/rodlukas>",
"Proudust <github.com/proudust>",
"Tiago Sousa <github.com/TiagoPortfolio>",
"Alexey Victorov <github.com/AliMamed>",
"Calum Smith <github.com/cpmsmith>",
"squiaios <github.com/squiaios>",
"WyvernDrexx <github.com/WyvernDrexx>",
"Jason Lundien <github.com/jasonlundien>",
"Jon Defresne <github.com/jdufresne>",
"Charles Harwood <github.com/charles4221>"
],
"license": "MIT",
"scripts": {
"build": "tsup",
"lint": "eslint .",
"lint:commits": "commitlint --config commitlint.config.ts --edit",
"format:check": "prettier --check .",
"format:fix": "prettier --write .",
"format:staged": "pretty-quick --pattern src/** --staged",
"prepack": "npm run build",
"test": "jest",
"test:watch": "jest --watch",
"test:prepublish": "npm run install.6 && npm run test && npm run install.7 && npm run test",
"validate": "npm run lint && npm run format:check && npm run validate-types && npm run test",
"validate-types": "tsc --noEmit",
"install.6": "npm --no-save install @fortawesome/fontawesome-svg-core@6.x @fortawesome/free-solid-svg-icons@6.x",
"install.7": "npm --no-save install @fortawesome/fontawesome-svg-core@7.x @fortawesome/free-solid-svg-icons@7.x",
"clean": "rimraf dist",
"prepare": "husky"
},
"engines": {
"node": ">=20"
},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "~6 || ~7",
"react": "^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@babel/core": "^7.28.5",
"@babel/plugin-external-helpers": "^7.27.1",
"@babel/preset-env": "^7.28.5",
"@babel/preset-react": "^7.28.5",
"@babel/preset-typescript": "^7.28.5",
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
"@eslint/js": "^9.39.1",
"@fortawesome/fontawesome-svg-core": "^7.1.0",
"@fortawesome/free-brands-svg-icons": "^7.1.0",
"@fortawesome/free-solid-svg-icons": "^7.1.0",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/jest": "^30.0.0",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"browserslist": "^4.28.0",
"caniuse-lite": "^1.0.30001757",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"eslint": "^9.39.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^29.2.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-testing-library": "^7.13.5",
"eslint-plugin-unicorn": "^62.0.0",
"globals": "^16.5.0",
"husky": "^9.1.7",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
"prettier": "^3.6.2",
"pretty-quick": "^4.2.2",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"rimraf": "^6.1.2",
"semantic-release": "^25.0.2",
"ts-jest": "^29.4.5",
"ts-node": "^10.9.2",
"tsup": "^8.5.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.48.0"
},
"files": [
"./dist",
"./CHANGELOG.md",
"./CODE_OF_CONDUCT.md",
"./CONTRIBUTING.md",
"./DEVELOPMENT.md",
"./LICENSE.txt",
"./README.md",
"./UPGRADING.md"
],
"browserslist": [
"> 1%",
"last 2 versions"
],
"keywords": [
"fontawesome",
"font-awesome",
"react",
"javascript",
"svg",
"icons"
],
"publishConfig": {
"tag": "latest"
}
}