From 632ee138cb2d29fa58337f70233df2ea2c6a74f2 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Mon, 6 Jul 2026 13:29:52 -0500 Subject: [PATCH] Replaced CJS react-world-flags with ESM country-flag-icons in Flag ref https://linear.app/ghost/issue/PLA-96/spike-rolldown-vite-drop-in-build-benchmarks country-flag-icons is true ESM, so the Flag component no longer needs the CJS interop shim added in #29137 to work around react-world-flags's {__esModule, default} shape under Rolldown; supersedes #29137. --- apps/shade/package.json | 3 +- apps/shade/src/components/ui/flag.stories.tsx | 2 +- apps/shade/src/components/ui/flag.tsx | 28 ++++--- pnpm-lock.yaml | 81 +++---------------- pnpm-workspace.yaml | 1 + 5 files changed, 33 insertions(+), 82 deletions(-) diff --git a/apps/shade/package.json b/apps/shade/package.json index d1e14ff6557..ce4561a6698 100644 --- a/apps/shade/package.json +++ b/apps/shade/package.json @@ -88,7 +88,6 @@ "@tailwindcss/postcss": "catalog:", "@testing-library/react": "catalog:", "@types/node": "catalog:", - "@types/react-world-flags": "1.6.0", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", "@vitejs/plugin-react": "catalog:", @@ -147,6 +146,7 @@ "clsx": "catalog:", "cmdk": "1.1.1", "color": "5.0.3", + "country-flag-icons": "catalog:", "lucide-react": "catalog:", "moment-timezone": "^0.5.48", "react": "catalog:", @@ -154,7 +154,6 @@ "react-dom": "catalog:", "react-dropzone": "14.4.1", "react-hook-form": "7.80.0", - "react-world-flags": "1.6.0", "recharts": "2.15.4", "sonner": "catalog:", "tailwind-merge": "3.6.0", diff --git a/apps/shade/src/components/ui/flag.stories.tsx b/apps/shade/src/components/ui/flag.stories.tsx index 6f157bc2eb4..42668337a16 100644 --- a/apps/shade/src/components/ui/flag.stories.tsx +++ b/apps/shade/src/components/ui/flag.stories.tsx @@ -8,7 +8,7 @@ const meta = { parameters: { docs: { description: { - component: 'Display country flags using ISO country codes. Built on react-world-flags with customizable sizing and fallback support for invalid or missing country codes.' + component: 'Display country flags using ISO country codes. Built on country-flag-icons with customizable sizing and fallback support for invalid or missing country codes.' } } }, diff --git a/apps/shade/src/components/ui/flag.tsx b/apps/shade/src/components/ui/flag.tsx index 9698f9f1c52..feb5917c998 100644 --- a/apps/shade/src/components/ui/flag.tsx +++ b/apps/shade/src/components/ui/flag.tsx @@ -1,6 +1,7 @@ import {cn} from '@/lib/utils'; import React from 'react'; -import ReactFlag from 'react-world-flags'; +import {hasFlag} from 'country-flag-icons'; +import * as Flags from 'country-flag-icons/react/3x2'; interface FlagProps { width?: string; @@ -10,6 +11,8 @@ interface FlagProps { fallback?: React.ReactNode | null | undefined; } +type FlagComponent = React.ComponentType>; + const Flag: React.FC = ({ className, countryCode, @@ -22,17 +25,24 @@ const Flag: React.FC = ({ height: height }; + const code = countryCode ? countryCode.toUpperCase() : ''; + const FlagIcon = code && hasFlag(code) ? (Flags as Record)[code] : undefined; + + const defaultFallback = fallback || ; + return (
- } - style={{ - height: height - }} /> + {FlagIcon + ? ( + + ) + : defaultFallback}
); }; -export {Flag}; \ No newline at end of file +export {Flag}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb23f5fdab1..0e3ef041b19 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -174,6 +174,9 @@ catalogs: concurrently: specifier: 10.0.3 version: 10.0.3 + country-flag-icons: + specifier: 1.6.20 + version: 1.6.20 cross-fetch: specifier: 4.1.0 version: 4.1.0 @@ -1694,6 +1697,9 @@ importers: color: specifier: 5.0.3 version: 5.0.3 + country-flag-icons: + specifier: 'catalog:' + version: 1.6.20 lucide-react: specifier: 'catalog:' version: 1.23.0(react@18.3.1) @@ -1715,9 +1721,6 @@ importers: react-hook-form: specifier: 7.80.0 version: 7.80.0(react@18.3.1) - react-world-flags: - specifier: 1.6.0 - version: 1.6.0(react@18.3.1) recharts: specifier: 2.15.4 version: 2.15.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1755,9 +1758,6 @@ importers: '@types/node': specifier: 'catalog:' version: 22.20.0 - '@types/react-world-flags': - specifier: 1.6.0 - version: 1.6.0 '@typescript-eslint/eslint-plugin': specifier: 'catalog:' version: 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.4(jiti@2.7.0))(supports-color@5.5.0)(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(supports-color@5.5.0)(typescript@5.9.3) @@ -9615,9 +9615,6 @@ packages: peerDependencies: '@types/react': '*' - '@types/react-world-flags@1.6.0': - resolution: {integrity: sha512-j/uVy2fnG8gX3Ckic4sccYm9XjieasUsJDMqBDtdPdcwe3aFfz+iBbds+wxOiTzfe5BErVGjdFu6NO1hCg/7lw==} - '@types/react@17.0.93': resolution: {integrity: sha512-KM4Ty/ZTLZupiYxZVAlP+InNJS3De6uBMdq0ePa6/04+eG9Y7ftnWfst1xTLQ5rwAhgHwQ4momt/O4KepdGBTw==} @@ -11942,10 +11939,6 @@ packages: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} @@ -12454,6 +12447,9 @@ packages: resolution: {integrity: sha512-3upkVtUfZgdp5xOQI/Deg1ye73ae6bygJMO4UvtUi6wLjwcj7cBqx2PzSZ1VL8i5iveBbjhsQp2Judx7kPKivA==} engines: {node: '>=8.x', npm: '>=5.x'} + country-flag-icons@1.6.20: + resolution: {integrity: sha512-py8JiEKzjhYw6HPJ0L7SxLgCYim36UPRTZX43/kqGueUCZLSvnrqAiwW8HtQibur7mdkFQUkjOgdK+o/9FBtaw==} + cpu-features@0.0.10: resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} engines: {node: '>=10.0.0'} @@ -12592,10 +12588,6 @@ packages: resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -17137,9 +17129,6 @@ packages: mdn-data@2.0.28: resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - mdn-data@2.0.4: resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} @@ -19689,11 +19678,6 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' - react-world-flags@1.6.0: - resolution: {integrity: sha512-eutSeAy5YKoVh14js/JUCSlA6EBk1n4k+bDaV+NkNB50VhnG+f4QDTpYycnTUTsZ5cqw/saPmk0Z4Fa0VVZ1Iw==} - peerDependencies: - react: '>=0.14' - react@17.0.2: resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} engines: {node: '>=0.10.0'} @@ -20903,9 +20887,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svg-country-flags@1.2.10: - resolution: {integrity: sha512-xrqwo0TYf/h2cfPvGpjdSuSguUbri4vNNizBnwzoZnX0xGo3O5nGJMlbYEp7NOYcnPGBm6LE2axqDWSB847bLw==} - svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -20924,11 +20905,6 @@ packages: deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x. hasBin: true - svgo@3.3.3: - resolution: {integrity: sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==} - engines: {node: '>=14.0.0'} - hasBin: true - svgo@4.0.1: resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} engines: {node: '>=16'} @@ -22194,9 +22170,6 @@ packages: workerpool@9.3.4: resolution: {integrity: sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==} - world-countries@5.1.0: - resolution: {integrity: sha512-CXR6EBvTbArDlDDIWU3gfKb7Qk0ck2WNZ234b/A0vuecPzIfzzxH+O6Ejnvg1sT8XuiZjVlzOH0h08ZtaO7g0w==} - wrap-ansi@10.0.0: resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} engines: {node: '>=20'} @@ -29925,10 +29898,6 @@ snapshots: dependencies: '@types/react': 18.3.31 - '@types/react-world-flags@1.6.0': - dependencies: - '@types/react': 18.3.31 - '@types/react@17.0.93': dependencies: '@types/prop-types': 15.7.15 @@ -33537,8 +33506,6 @@ snapshots: commander@6.2.1: {} - commander@7.2.0: {} - commander@8.3.0: {} commander@9.5.0: {} @@ -33767,6 +33734,8 @@ snapshots: countries-and-timezones@3.9.0: {} + country-flag-icons@1.6.20: {} + cpu-features@0.0.10: dependencies: buildcheck: 0.0.7 @@ -33977,11 +33946,6 @@ snapshots: mdn-data: 2.0.28 source-map-js: 1.2.1 - css-tree@2.3.1: - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.1 - css-tree@3.2.1: dependencies: mdn-data: 2.27.1 @@ -40978,8 +40942,6 @@ snapshots: mdn-data@2.0.28: {} - mdn-data@2.0.30: {} - mdn-data@2.0.4: {} mdn-data@2.27.1: {} @@ -44040,13 +44002,6 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-world-flags@1.6.0(react@18.3.1): - dependencies: - react: 18.3.1 - svg-country-flags: 1.2.10 - svgo: 3.3.3 - world-countries: 5.1.0 - react@17.0.2: dependencies: loose-envify: 1.4.0 @@ -45628,8 +45583,6 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svg-country-flags@1.2.10: {} - svg-parser@2.0.4: {} svg-tags@1.0.0: {} @@ -45666,16 +45619,6 @@ snapshots: unquote: 1.1.1 util.promisify: 1.0.1 - svgo@3.3.3: - dependencies: - commander: 7.2.0 - css-select: 5.2.2 - css-tree: 2.3.1 - css-what: 6.2.2 - csso: 5.0.5 - picocolors: 1.1.1 - sax: 1.6.0 - svgo@4.0.1: dependencies: commander: 11.1.0 @@ -47333,8 +47276,6 @@ snapshots: workerpool@9.3.4: {} - world-countries@5.1.0: {} - wrap-ansi@10.0.0: dependencies: ansi-styles: 6.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 36d08ca68de..c1cdf3c3627 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -83,6 +83,7 @@ catalog: chalk: 4.1.2 clsx: 2.1.1 concurrently: 10.0.3 + country-flag-icons: 1.6.20 cross-fetch: 4.1.0 dequal: 2.0.3 dompurify: 3.4.11