From 0aba77e830b1152453d22d402d5dcfc1258c11d5 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:46:27 +0000 Subject: [PATCH 01/63] feat: add typescript migration infrastructure and convert tag component Co-Authored-By: Eirik --- .eslintrc.js | 31 ++ MIGRATION_GUIDE.md | 108 +++++ components/tag/d2.config.js | 2 +- components/tag/package.json | 3 +- components/tag/src/index.js | 1 - components/tag/src/index.ts | 2 + .../tag/src/{tag-icon.js => tag-icon.tsx} | 13 +- .../tag/src/{tag-text.js => tag-text.tsx} | 13 +- components/tag/src/tag.e2e.stories.js | 2 +- components/tag/src/tag.prod.stories.js | 2 +- components/tag/src/{tag.js => tag.tsx} | 47 +-- components/tag/tsconfig.json | 8 + package.json | 4 + scripts/post-build-rename.js | 76 ++++ scripts/ts-check.js | 145 +++++++ tsconfig.json | 26 ++ yarn.lock | 380 +++++++++++++++++- 17 files changed, 804 insertions(+), 59 deletions(-) create mode 100644 MIGRATION_GUIDE.md delete mode 100644 components/tag/src/index.js create mode 100644 components/tag/src/index.ts rename components/tag/src/{tag-icon.js => tag-icon.tsx} (61%) rename components/tag/src/{tag-text.js => tag-text.tsx} (56%) rename components/tag/src/{tag.js => tag.tsx} (85%) create mode 100644 components/tag/tsconfig.json create mode 100644 scripts/post-build-rename.js create mode 100644 scripts/ts-check.js create mode 100644 tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index 0bd37b6457..4105c79617 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -39,6 +39,37 @@ const config = { 'import/no-extraneous-dependencies': 'error', }, }, + // TypeScript overrides for migrated components + { + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { jsx: true }, + }, + plugins: ['@typescript-eslint'], + extends: [ + 'plugin:@typescript-eslint/recommended', + ], + settings: { + 'import/resolver': { + typescript: { + project: './tsconfig.json', + }, + }, + }, + rules: { + // Disable JS-only rules that conflict with TS + 'react/prop-types': 'off', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + // Keep consistent with existing code style + 'react/no-unknown-property': ['error', { ignore: ['jsx', 'global'] }], + // Allow .js extension imports in TS files (Babel resolves .tsx -> .js) + 'import/extensions': 'off', + }, + }, ], } diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md new file mode 100644 index 0000000000..ca2e9b60e4 --- /dev/null +++ b/MIGRATION_GUIDE.md @@ -0,0 +1,108 @@ +# dhis2/ui — Incremental TypeScript Migration Strategy + +## Overview + +This document describes the approach for incrementally migrating `@dhis2/ui` components from JavaScript to TypeScript, one component at a time, without breaking the rest of the library. + +## Key Findings + +- **Build system**: `d2-app-scripts build` uses Babel with `@babel/preset-typescript` already included — it can compile `.ts`/`.tsx` out of the box. +- **styled-jsx**: Ships TypeScript definitions that augment React's `StyleHTMLAttributes` with `jsx` and `global` props. Works in `.tsx` files with the `"types": ["styled-jsx"]` tsconfig option. +- **Existing types**: Each component has hand-written `.d.ts` files in a `types/` directory. After migration, these can be auto-generated from source via `tsc --declaration`. +- **ESLint**: The project uses `@dhis2/cli-style` (ESLint 7.x). TypeScript linting works via `@typescript-eslint/parser` v6 + `@typescript-eslint/eslint-plugin` v6. +- **One quirk**: `d2-app-scripts build` doesn't rename `.tsx` → `.js` in build output. A `post-build-rename.js` script handles this. + +## How to Migrate a Component + +### 1. Add a `tsconfig.json` to the component + +```json +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} +``` + +### 2. Convert source files from `.js` → `.tsx` (or `.ts`) + +- Replace `PropTypes` with TypeScript interfaces +- Remove `prop-types` and `@dhis2/prop-types` imports +- Add explicit types for props, state, and function parameters +- Keep `styled-jsx` usage as-is (it works in `.tsx`) +- Keep import paths using `.js` extensions (Babel + Node resolve these to `.tsx`) +- Leave `.stories.js` and `.feature` test files as JavaScript + +### 3. Update `d2.config.js` entry point + +```js +module.exports = { + type: 'lib', + entryPoints: { + lib: 'src/index.ts', // was src/index.js + }, +} +``` + +### 4. Update `package.json` build script + +```json +"build": "d2-app-scripts build && node ../../scripts/post-build-rename.js" +``` + +### 5. Delete old `.js` source files + +Remove the original `.js` files that were converted (keep stories/features as JS). + +### 6. Run the feedback pipeline + +```bash +node scripts/ts-check.js # check one component +node scripts/ts-check.js --all # check all migrated components +node scripts/ts-check.js --fix # auto-fix lint + format +``` + +### 7. Verify the build + +```bash +cd components/ && yarn build +``` + +## Files Added/Modified + +| File | Purpose | +|------|---------| +| `tsconfig.json` (root) | Base TypeScript config for the whole repo | +| `components//tsconfig.json` | Per-component TS config extending root | +| `.eslintrc.js` | Added TypeScript override block for `.ts`/`.tsx` files | +| `scripts/ts-check.js` | Unified feedback pipeline (tsc + eslint + prettier) | +| `scripts/post-build-rename.js` | Renames `.tsx`/`.ts` → `.js` in build output | + +## Dev Dependencies Added + +- `typescript` ~5.4.5 +- `@typescript-eslint/parser` ^6 +- `@typescript-eslint/eslint-plugin` ^6 +- `eslint-import-resolver-typescript` ^3 + +## Migration Order Recommendation + +Start with leaf components (no internal deps) and work up: + +1. **Simple leaf**: `divider`, `cover`, `center`, `required`, `help`, `legend`, `label` +2. **Small with sub-components**: `tag`, `chip`, `card`, `box`, `status-icon`, `user-avatar`, `logo` +3. **Medium**: `loader`, `notice-box`, `alert`, `tooltip`, `popover`, `popper` +4. **Complex**: `button`, `checkbox`, `radio`, `switch`, `input`, `text-area`, `file-input` +5. **Field wrappers**: `field` +6. **Composite**: `select`, `menu`, `tab`, `table`, `pagination`, `modal`, `calendar` +7. **Large/complex**: `header-bar`, `organisation-unit-tree`, `transfer`, `sharing-dialog`, `selector-bar` +8. **Collections**: `collections/ui`, `collections/forms` + +## Notes + +- Stories and E2E feature files can stay as `.js` — they don't need to be migrated immediately. +- The `types/index.d.ts` hand-written files can eventually be replaced by auto-generated declarations from `tsc --declaration`. +- The `import/extensions` ESLint rule is disabled for `.ts`/`.tsx` files because the codebase convention is to import with `.js` extensions (which Babel resolves to the actual `.tsx` files). diff --git a/components/tag/d2.config.js b/components/tag/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/tag/d2.config.js +++ b/components/tag/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/tag/package.json b/components/tag/package.json index 2202ba0e0a..096626bb37 100644 --- a/components/tag/package.json +++ b/components/tag/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/tag/src/index.js b/components/tag/src/index.js deleted file mode 100644 index ecc69fe3fe..0000000000 --- a/components/tag/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Tag } from './tag.js' diff --git a/components/tag/src/index.ts b/components/tag/src/index.ts new file mode 100644 index 0000000000..1e4dde652a --- /dev/null +++ b/components/tag/src/index.ts @@ -0,0 +1,2 @@ +export { Tag } from './tag.tsx' +export type { TagProps } from './tag.tsx' diff --git a/components/tag/src/tag-icon.js b/components/tag/src/tag-icon.tsx similarity index 61% rename from components/tag/src/tag-icon.js rename to components/tag/src/tag-icon.tsx index 3be1487866..18054c6140 100644 --- a/components/tag/src/tag-icon.js +++ b/components/tag/src/tag-icon.tsx @@ -1,7 +1,11 @@ -import PropTypes from 'prop-types' import React from 'react' -export const TagIcon = ({ children, dataTest }) => ( +interface TagIconProps { + dataTest: string + children?: React.ReactNode +} + +export const TagIcon = ({ children, dataTest }: TagIconProps) => (
{children}
) - -TagIcon.propTypes = { - dataTest: PropTypes.string.isRequired, - children: PropTypes.node, -} diff --git a/components/tag/src/tag-text.js b/components/tag/src/tag-text.tsx similarity index 56% rename from components/tag/src/tag-text.js rename to components/tag/src/tag-text.tsx index 30475750d7..ce6e166153 100644 --- a/components/tag/src/tag-text.js +++ b/components/tag/src/tag-text.tsx @@ -1,7 +1,11 @@ -import PropTypes from 'prop-types' import React from 'react' -export const TagText = ({ children, dataTest }) => ( +interface TagTextProps { + dataTest: string + children?: React.ReactNode +} + +export const TagText = ({ children, dataTest }: TagTextProps) => ( {children} ) - -TagText.propTypes = { - dataTest: PropTypes.string.isRequired, - children: PropTypes.node, -} diff --git a/components/tag/src/tag.e2e.stories.js b/components/tag/src/tag.e2e.stories.js index 308f374310..f209576315 100644 --- a/components/tag/src/tag.e2e.stories.js +++ b/components/tag/src/tag.e2e.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Tag } from './tag.js' +import { Tag } from './tag.tsx' export default { title: 'Tag' } export const WithoutIcon = () => Default diff --git a/components/tag/src/tag.prod.stories.js b/components/tag/src/tag.prod.stories.js index d5eb89e75f..0f2e7c8e86 100644 --- a/components/tag/src/tag.prod.stories.js +++ b/components/tag/src/tag.prod.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Tag } from './tag.js' +import { Tag } from './tag.tsx' const subtitle = 'Used to display categorizing labels or information for other elements in a collection.' diff --git a/components/tag/src/tag.js b/components/tag/src/tag.tsx similarity index 85% rename from components/tag/src/tag.js rename to components/tag/src/tag.tsx index 8bc42ebc93..05762b03b4 100644 --- a/components/tag/src/tag.js +++ b/components/tag/src/tag.tsx @@ -1,10 +1,25 @@ -import { mutuallyExclusive } from '@dhis2/prop-types' import { colors } from '@dhis2/ui-constants' import cx from 'classnames' -import PropTypes from 'prop-types' import React from 'react' -import { TagIcon } from './tag-icon.js' -import { TagText } from './tag-text.js' +import { TagIcon } from './tag-icon.tsx' +import { TagText } from './tag-text.tsx' + +export interface TagProps { + /** Use bold tags where it is important that the tag is seen by the user in an information dense interface. Bold tags should be reserved for edge cases and not overused. */ + bold?: boolean + children?: React.ReactNode + className?: string + dataTest?: string + /** Tags can contain icons. Use icons where they will help users easily identify the content of the tag. Tags must have a text label and cannot display only an icon. */ + icon?: React.ReactNode + maxWidth?: string + /** Red 'negative' tags imply an error or a problem. `neutral`, `positive`, and `negative` are mutually exclusive props */ + negative?: boolean + /** Blue 'neutral' tags are used when a tag _could_ have valid or error status but is currently neutral. `neutral`, `positive`, and `negative` are mutually exclusive props */ + neutral?: boolean + /** Green 'valid' tags should be used to indicate validity or success. `neutral`, `positive`, and `negative` are mutually exclusive props */ + positive?: boolean +} export const Tag = ({ maxWidth = '240px', @@ -16,7 +31,7 @@ export const Tag = ({ className, dataTest = 'dhis2-uicore-tag', children, -}) => ( +}: TagProps) => (
) - -const tagVariantPropType = mutuallyExclusive( - ['neutral', 'positive', 'negative'], - PropTypes.bool -) - -Tag.propTypes = { - /** Use bold tags where it is important that the tag is seen by the user in an information dense interface. Bold tags should be reserved for edge cases and not overused. */ - bold: PropTypes.bool, - children: PropTypes.node, - className: PropTypes.string, - dataTest: PropTypes.string, - /** Tags can contain icons. Use icons where they will help users easily identify the content of the tag. Tags must have a text label and cannot display only an icon. */ - icon: PropTypes.node, - maxWidth: PropTypes.string, - /** Red 'negative' tags imply an error or a problem. `neutral`, `positive`, and `negative` are mutually exclusive props */ - negative: tagVariantPropType, - /** Blue 'neutral' tags are used when a tag _could_ have valid or error status but is currently neutral. `neutral`, `positive`, and `negative` are mutually exclusive props */ - neutral: tagVariantPropType, - /** Green 'valid' tags should be used to indicate validity or success. `neutral`, `positive`, and `negative` are mutually exclusive props */ - positive: tagVariantPropType, -} diff --git a/components/tag/tsconfig.json b/components/tag/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/tag/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} diff --git a/package.json b/package.json index 10af27d08c..abc06e447d 100644 --- a/package.json +++ b/package.json @@ -71,16 +71,20 @@ "@testing-library/react-hooks": "^7.0.1", "@testing-library/user-event": "^14.5.2", "@types/react": "^18", + "@typescript-eslint/eslint-plugin": "^6", + "@typescript-eslint/parser": "^6", "ast-types": "^0.14.2", "concurrently": "^6.2.1", "cypress": "^13.8.0", "enzyme": "^3.11.0", + "eslint-import-resolver-typescript": "^3", "execa": "^5.1.1", "fast-glob": "^3.2.7", "find-up": "^5.0.0", "react-dev-utils": "^10.2.1", "react-docgen": "^5.4.0", "rimraf": "^3.0.2", + "typescript": "~5.4.5", "wait-on": "^6.0.0" }, "overrides": { diff --git a/scripts/post-build-rename.js b/scripts/post-build-rename.js new file mode 100644 index 0000000000..034f4ecbd0 --- /dev/null +++ b/scripts/post-build-rename.js @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +/** + * post-build-rename.js + * + * After d2-app-scripts builds a TypeScript component, the output files + * retain their .ts/.tsx extensions despite being compiled to plain JS. + * This script renames them to .js/.jsx and updates internal import paths. + * + * Usage: node post-build-rename.js [buildDir] + * buildDir defaults to ./build + */ + +const fs = require('fs') +const path = require('path') + +const buildDir = process.argv[2] || path.join(process.cwd(), 'build') + +function walk(dir) { + const results = [] + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name) + if (entry.isDirectory()) { + results.push(...walk(fullPath)) + } else { + results.push(fullPath) + } + } + return results +} + +function renameExtension(filePath) { + if (filePath.endsWith('.tsx')) { + return filePath.replace(/\.tsx$/, '.js') + } + if (filePath.endsWith('.ts') && !filePath.endsWith('.d.ts')) { + return filePath.replace(/\.ts$/, '.js') + } + return filePath +} + +function updateImportPaths(content) { + // Update import/export paths: './foo.tsx' -> './foo.js', './foo.ts' -> './foo.js' + return content + .replace(/(from\s+['"])([^'"]*?)\.tsx(['"])/g, '$1$2.js$3') + .replace(/(from\s+['"])([^'"]*?)\.ts(['"])/g, '$1$2.js$3') + .replace(/(require\(['"])([^'"]*?)\.tsx(['"]\))/g, '$1$2.js$3') + .replace(/(require\(['"])([^'"]*?)\.ts(['"]\))/g, '$1$2.js$3') +} + +const files = walk(buildDir) +let renamed = 0 +let updated = 0 + +// First pass: update import paths in all JS/TS files +for (const filePath of files) { + if (/\.[jt]sx?$/.test(filePath)) { + const content = fs.readFileSync(filePath, 'utf8') + const newContent = updateImportPaths(content) + if (content !== newContent) { + fs.writeFileSync(filePath, newContent, 'utf8') + updated++ + } + } +} + +// Second pass: rename .ts/.tsx files to .js +for (const filePath of files) { + const newPath = renameExtension(filePath) + if (newPath !== filePath) { + fs.renameSync(filePath, newPath) + renamed++ + } +} + +console.log(`Renamed ${renamed} file(s), updated imports in ${updated} file(s)`) diff --git a/scripts/ts-check.js b/scripts/ts-check.js new file mode 100644 index 0000000000..2b40b90b1f --- /dev/null +++ b/scripts/ts-check.js @@ -0,0 +1,145 @@ +#!/usr/bin/env node + +/** + * ts-check.js — Feedback pipeline for incrementally migrated TypeScript components + * + * Runs three checks on a single component (or all migrated components): + * 1. TypeScript type-checking (tsc --noEmit) + * 2. ESLint (with @typescript-eslint rules) + * 3. Prettier formatting check + * + * Usage: + * node scripts/ts-check.js # e.g. "tag" + * node scripts/ts-check.js --all # check every component with a tsconfig.json + * node scripts/ts-check.js --fix # auto-fix lint + format issues + */ + +const { execSync } = require('child_process') +const fs = require('fs') +const path = require('path') + +const ROOT = path.resolve(__dirname, '..') +const COMPONENTS_DIR = path.join(ROOT, 'components') +const PRETTIER_CONFIG = path.join( + ROOT, + 'node_modules/@dhis2/cli-style/config/prettier.config.js' +) + +// ─── helpers ─────────────────────────────────────────────────────────── +function run(cmd, cwd = ROOT) { + try { + execSync(cmd, { cwd, stdio: 'pipe', encoding: 'utf8' }) + return { ok: true, output: '' } + } catch (err) { + return { ok: false, output: (err.stdout || '') + (err.stderr || '') } + } +} + +function heading(text) { + const line = '─'.repeat(60) + console.log(`\n${line}`) + console.log(` ${text}`) + console.log(line) +} + +// ─── resolve which components to check ───────────────────────────────── +const args = process.argv.slice(2) +const fix = args.includes('--fix') +const filteredArgs = args.filter((a) => a !== '--fix') +const checkAll = filteredArgs.includes('--all') + +let components = [] + +if (checkAll) { + // Find all components that have a tsconfig.json (i.e. migrated to TS) + for (const name of fs.readdirSync(COMPONENTS_DIR)) { + const tsconfig = path.join(COMPONENTS_DIR, name, 'tsconfig.json') + if (fs.existsSync(tsconfig)) { + components.push(name) + } + } +} else if (filteredArgs.length > 0) { + components = filteredArgs +} else { + console.log( + 'Usage:\n' + + ' node scripts/ts-check.js # e.g. "tag"\n' + + ' node scripts/ts-check.js --all # all migrated components\n' + + ' node scripts/ts-check.js --fix # auto-fix lint+format\n' + ) + process.exit(0) +} + +if (components.length === 0) { + console.log('No migrated components found (no tsconfig.json in any component dir).') + process.exit(0) +} + +// ─── run checks ──────────────────────────────────────────────────────── +let allPassed = true + +for (const name of components) { + const compDir = path.join(COMPONENTS_DIR, name) + const tsconfig = path.join(compDir, 'tsconfig.json') + + if (!fs.existsSync(tsconfig)) { + console.error(`⚠ Component "${name}" has no tsconfig.json — skipping.`) + continue + } + + console.log(`\n${'═'.repeat(60)}`) + console.log(` Checking component: ${name}`) + console.log(`${'═'.repeat(60)}`) + + // 1. TypeScript + heading('1/3 TypeScript (tsc --noEmit)') + const tsc = run(`npx tsc --noEmit --project ${tsconfig}`) + if (tsc.ok) { + console.log(' PASS — no type errors') + } else { + allPassed = false + console.log(' FAIL') + console.log(tsc.output) + } + + // 2. ESLint + heading(`2/3 ESLint${fix ? ' (with --fix)' : ''}`) + const glob = `"${compDir}/src/**/*.{ts,tsx}"` + const eslintCmd = fix + ? `npx eslint --fix ${glob}` + : `npx eslint ${glob}` + const eslint = run(eslintCmd) + if (eslint.ok) { + console.log(' PASS — no lint issues') + } else { + allPassed = false + console.log(' FAIL') + console.log(eslint.output) + } + + // 3. Prettier + heading(`3/3 Prettier${fix ? ' (with --write)' : ''}`) + const prettierCmd = fix + ? `npx prettier --write --config ${PRETTIER_CONFIG} ${glob}` + : `npx prettier --check --config ${PRETTIER_CONFIG} ${glob}` + const prettier = run(prettierCmd) + if (prettier.ok) { + console.log(' PASS — formatting is correct') + } else { + allPassed = false + console.log(' FAIL') + console.log(prettier.output) + } +} + +// ─── summary ─────────────────────────────────────────────────────────── +console.log(`\n${'═'.repeat(60)}`) +if (allPassed) { + console.log(' All checks passed!') +} else { + console.log(' Some checks failed. See output above.') + console.log(' Tip: run with --fix to auto-fix lint and formatting issues.') +} +console.log(`${'═'.repeat(60)}\n`) + +process.exit(allPassed ? 0 : 1) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..6841ae899a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "ESNext", + "moduleResolution": "node", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "allowJs": false, + "resolveJsonModule": true, + "isolatedModules": true, + "baseUrl": ".", + "types": ["styled-jsx"], + "paths": { + "@dhis2/ui-constants": ["./constants/types/index.d.ts"], + "@dhis2-ui/*": ["./components/*/types/index.d.ts"], + "classnames": ["./node_modules/@types/classnames/index.d.ts"] + } + }, + "include": [], + "exclude": ["node_modules", "build", "dist"] +} diff --git a/yarn.lock b/yarn.lock index 695bba2a5f..d7ff8a13c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -196,7 +196,7 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.8.3": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.8.3": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -262,7 +262,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.25.0", "@babel/generator@^7.25.9", "@babel/generator@^7.26.0", "@babel/generator@^7.7.2": +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.25.9", "@babel/generator@^7.26.0", "@babel/generator@^7.7.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.2.tgz#87b75813bec87916210e5e01939a4c823d6bb74f" integrity sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw== @@ -348,7 +348,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.25.2", "@babel/helper-module-transforms@^7.26.0": +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== @@ -408,7 +408,7 @@ "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.24.8", "@babel/helper-string-parser@^7.25.9": +"@babel/helper-string-parser@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== @@ -432,7 +432,7 @@ "@babel/traverse" "^7.25.0" "@babel/types" "^7.25.0" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.25.0", "@babel/helpers@^7.26.0": +"@babel/helpers@^7.12.5", "@babel/helpers@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== @@ -450,7 +450,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.17.0", "@babel/parser@^7.18.8", "@babel/parser@^7.20.7", "@babel/parser@^7.25.0", "@babel/parser@^7.25.3", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.0", "@babel/parser@^7.9.4": +"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.17.0", "@babel/parser@^7.18.8", "@babel/parser@^7.20.7", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.0", "@babel/parser@^7.9.4": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.2.tgz#fd7b6f487cfea09889557ef5d4eeb9ff9a5abd11" integrity sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ== @@ -1394,7 +1394,7 @@ "@babel/parser" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== @@ -3285,6 +3285,28 @@ url-loader "^4.1.1" webpack "^5.73.0" +"@emnapi/core@^1.4.3": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.9.2.tgz#3870265ecffc7352d01ead62d8d83d8358a2d034" + integrity sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA== + dependencies: + "@emnapi/wasi-threads" "1.2.1" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.9.2.tgz#8b469a3db160817cadb1de9050211a9d1ea84fa2" + integrity sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz#28fed21a1ba1ce797c44a070abc94d42f3ae8548" + integrity sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w== + dependencies: + tslib "^2.4.0" + "@esbuild/aix-ppc64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" @@ -3642,11 +3664,23 @@ dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.4.0": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": version "4.11.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== +"@eslint-community/regexpp@^4.5.1": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" @@ -4150,6 +4184,15 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz" @@ -4183,6 +4226,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nolyfill/is-core-module@1.0.39": + version "1.0.39" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" @@ -5086,6 +5134,13 @@ resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + "@types/aria-query@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" @@ -5270,7 +5325,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -5476,6 +5531,11 @@ resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/semver@^7.5.0": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.1.tgz#3ce3af1a5524ef327d2da9e4fd8b6d95c8d70528" + integrity sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA== + "@types/send@*": version "0.17.4" resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz" @@ -5586,6 +5646,23 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^6": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + "@typescript-eslint/experimental-utils@^5.0.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz" @@ -5603,6 +5680,17 @@ "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" +"@typescript-eslint/parser@^6": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== + dependencies: + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz" @@ -5611,6 +5699,14 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/type-utils@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz" @@ -5621,11 +5717,26 @@ debug "^4.3.4" tsutils "^3.21.0" +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== + dependencies: + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + "@typescript-eslint/types@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== + "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz" @@ -5639,6 +5750,20 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + "@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.58.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" @@ -5653,6 +5778,19 @@ eslint-scope "^5.1.1" semver "^7.3.7" +"@typescript-eslint/utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" + "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz" @@ -5661,11 +5799,116 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== + dependencies: + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + "@vitejs/plugin-react@^4.2.1": version "4.3.3" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz#28301ac6d7aaf20b73a418ee5c65b05519b4836c" @@ -8648,6 +8891,13 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.4.0: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz" @@ -9656,6 +9906,19 @@ eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" +eslint-import-resolver-typescript@^3: + version "3.10.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz#23dac32efa86a88e2b8232eb244ac499ad636db2" + integrity sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ== + dependencies: + "@nolyfill/is-core-module" "1.0.39" + debug "^4.4.0" + get-tsconfig "^4.10.0" + is-bun-module "^2.0.0" + stable-hash "^0.0.5" + tinyglobby "^0.2.13" + unrs-resolver "^1.6.2" + eslint-module-utils@^2.8.0: version "2.8.1" resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz" @@ -10320,6 +10583,11 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + feed@^4.2.2: version "4.2.2" resolved "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz" @@ -10847,6 +11115,13 @@ get-symbol-description@^1.0.2: es-errors "^1.3.0" get-intrinsic "^1.2.4" +get-tsconfig@^4.10.0: + version "4.13.7" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.7.tgz#b9d8b199b06033ceeea1a93df7ea5765415089bc" + integrity sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q== + dependencies: + resolve-pkg-maps "^1.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" @@ -12016,6 +12291,13 @@ is-buffer@^2.0.0: resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== +is-bun-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-2.0.0.tgz#4d7859a87c0fcac950c95e666730e745eae8bddd" + integrity sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ== + dependencies: + semver "^7.7.1" + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" @@ -14162,6 +14444,13 @@ minimatch@3.1.2, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch dependencies: brace-expansion "^1.1.7" +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^5.0.1, minimatch@^5.1.6: version "5.1.6" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" @@ -14370,6 +14659,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-postinstall@^0.3.0: + version "0.3.4" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" @@ -15141,6 +15435,11 @@ picomatch@^4.0.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" @@ -17015,6 +17314,11 @@ resolve-pathname@^3.0.0: resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve-pkg@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz" @@ -17394,6 +17698,11 @@ semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semve resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.7.1: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -17951,6 +18260,11 @@ sshpk@^1.14.1, sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +stable-hash@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.5.tgz#94e8837aaeac5b4d0f631d2972adef2924b40269" + integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA== + stable@^0.1.8: version "0.1.8" resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" @@ -18724,6 +19038,14 @@ tiny-warning@^1.0.0: resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tinyglobby@^0.2.13: + version "0.2.16" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6" + integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + tmp@0.2.3, tmp@~0.2.3: version "0.2.3" resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz" @@ -18880,6 +19202,11 @@ tryer@^1.0.1: resolved "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +ts-api-utils@^1.0.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" + integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== + ts-dedent@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz" @@ -19081,6 +19408,11 @@ typescript@^3.6.3: resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== +typescript@~5.4.5: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + typical@^2.4.2, typical@^2.6.0, typical@^2.6.1: version "2.6.1" resolved "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz" @@ -19131,11 +19463,6 @@ underscore@~1.13.2: resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz" integrity sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g== -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - undici-types@~6.19.8: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" @@ -19339,6 +19666,33 @@ unquote@~1.1.1: resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz" integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== +unrs-resolver@^1.6.2: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" From 430d2c0162cb8f8aec9c195bd2be63d8cd30da58 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:01:46 +0000 Subject: [PATCH 02/63] feat: migrate required component to TypeScript Co-Authored-By: henrik.vadet@dhis2.org --- components/required/d2.config.js | 2 +- components/required/package.json | 3 ++- components/required/src/index.js | 1 - components/required/src/index.ts | 2 ++ components/required/src/{required.js => required.tsx} | 11 +++++------ components/required/tsconfig.json | 8 ++++++++ 6 files changed, 18 insertions(+), 9 deletions(-) delete mode 100644 components/required/src/index.js create mode 100644 components/required/src/index.ts rename components/required/src/{required.js => required.tsx} (64%) create mode 100644 components/required/tsconfig.json diff --git a/components/required/d2.config.js b/components/required/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/required/d2.config.js +++ b/components/required/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/required/package.json b/components/required/package.json index d37aab6abc..cd56590d3e 100644 --- a/components/required/package.json +++ b/components/required/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/required/src/index.js b/components/required/src/index.js deleted file mode 100644 index a9460cd65f..0000000000 --- a/components/required/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Required } from './required.js' diff --git a/components/required/src/index.ts b/components/required/src/index.ts new file mode 100644 index 0000000000..5a8d64e4d6 --- /dev/null +++ b/components/required/src/index.ts @@ -0,0 +1,2 @@ +export { Required } from './required.tsx' +export type { RequiredProps } from './required.tsx' diff --git a/components/required/src/required.js b/components/required/src/required.tsx similarity index 64% rename from components/required/src/required.js rename to components/required/src/required.tsx index d61bf29161..8562ae3452 100644 --- a/components/required/src/required.js +++ b/components/required/src/required.tsx @@ -1,8 +1,11 @@ import { spacers } from '@dhis2/ui-constants' -import PropTypes from 'prop-types' import React from 'react' -export const Required = ({ dataTest }) => ( +export interface RequiredProps { + dataTest: string +} + +export const Required = ({ dataTest }: RequiredProps) => ( * ) - -Required.propTypes = { - dataTest: PropTypes.string.isRequired, -} diff --git a/components/required/tsconfig.json b/components/required/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/required/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From fb1503012a6576bdfa871e9df4c4bc9245c83d38 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:02:01 +0000 Subject: [PATCH 03/63] feat: migrate help component to TypeScript Co-Authored-By: Eirik --- components/help/d2.config.js | 2 +- components/help/package.json | 3 ++- components/help/src/help.e2e.stories.js | 2 +- components/help/src/help.prod.stories.js | 2 +- components/help/src/{help.js => help.tsx} | 23 +++++++++++------------ components/help/src/index.js | 1 - components/help/src/index.ts | 2 ++ components/help/tsconfig.json | 8 ++++++++ 8 files changed, 26 insertions(+), 17 deletions(-) rename components/help/src/{help.js => help.tsx} (71%) delete mode 100644 components/help/src/index.js create mode 100644 components/help/src/index.ts create mode 100644 components/help/tsconfig.json diff --git a/components/help/d2.config.js b/components/help/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/help/d2.config.js +++ b/components/help/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/help/package.json b/components/help/package.json index e7c947a773..7b99f30d73 100644 --- a/components/help/package.json +++ b/components/help/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/help/src/help.e2e.stories.js b/components/help/src/help.e2e.stories.js index 09265078aa..c1add0edf4 100644 --- a/components/help/src/help.e2e.stories.js +++ b/components/help/src/help.e2e.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Help } from './help.js' +import { Help } from './help.tsx' export default { title: 'Help' } export const WithChildren = () => I am a child diff --git a/components/help/src/help.prod.stories.js b/components/help/src/help.prod.stories.js index 7b6806af4a..e513b1c3cb 100644 --- a/components/help/src/help.prod.stories.js +++ b/components/help/src/help.prod.stories.js @@ -1,6 +1,6 @@ import { sharedPropTypes } from '@dhis2/ui-constants' import React from 'react' -import { Help } from './help.js' +import { Help } from './help.tsx' const description = ` Small text for giving guiding information or feedback, especially for data entry instructions or form validation feedback. diff --git a/components/help/src/help.js b/components/help/src/help.tsx similarity index 71% rename from components/help/src/help.js rename to components/help/src/help.tsx index 298a03e4c6..b763cfb1e7 100644 --- a/components/help/src/help.js +++ b/components/help/src/help.tsx @@ -1,8 +1,16 @@ -import { spacers, theme, colors, sharedPropTypes } from '@dhis2/ui-constants' +import { spacers, theme, colors } from '@dhis2/ui-constants' import cx from 'classnames' -import PropTypes from 'prop-types' import React from 'react' +export interface HelpProps { + children?: string + className?: string + dataTest?: string + error?: boolean + valid?: boolean + warning?: boolean +} + const Help = ({ children, valid, @@ -10,7 +18,7 @@ const Help = ({ warning, className, dataTest = 'dhis2-uicore-help', -}) => ( +}: HelpProps) => (

) -Help.propTypes = { - children: PropTypes.string, - className: PropTypes.string, - dataTest: PropTypes.string, - error: sharedPropTypes.statusPropType, - valid: sharedPropTypes.statusPropType, - warning: sharedPropTypes.statusPropType, -} - export { Help } diff --git a/components/help/src/index.js b/components/help/src/index.js deleted file mode 100644 index 77b40db8b6..0000000000 --- a/components/help/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Help } from './help.js' diff --git a/components/help/src/index.ts b/components/help/src/index.ts new file mode 100644 index 0000000000..8e583e6abd --- /dev/null +++ b/components/help/src/index.ts @@ -0,0 +1,2 @@ +export { Help } from './help.tsx' +export type { HelpProps } from './help.tsx' diff --git a/components/help/tsconfig.json b/components/help/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/help/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 36ddce849a4bf191ae2a744fc04fdd90baea250d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:02:11 +0000 Subject: [PATCH 04/63] feat: migrate box component to TypeScript Co-Authored-By: Eirik --- components/box/d2.config.js | 2 +- components/box/package.json | 3 ++- components/box/src/box.e2e.stories.js | 2 +- components/box/src/box.prod.stories.js | 2 +- components/box/src/{box.js => box.tsx} | 31 +++++++++++++------------- components/box/src/index.js | 1 - components/box/src/index.ts | 2 ++ components/box/tsconfig.json | 8 +++++++ 8 files changed, 30 insertions(+), 21 deletions(-) rename components/box/src/{box.js => box.tsx} (67%) delete mode 100644 components/box/src/index.js create mode 100644 components/box/src/index.ts create mode 100644 components/box/tsconfig.json diff --git a/components/box/d2.config.js b/components/box/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/box/d2.config.js +++ b/components/box/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/box/package.json b/components/box/package.json index 40f9dc2679..59c3c62e2e 100644 --- a/components/box/package.json +++ b/components/box/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/box/src/box.e2e.stories.js b/components/box/src/box.e2e.stories.js index 498db343ae..7d7cae4946 100644 --- a/components/box/src/box.e2e.stories.js +++ b/components/box/src/box.e2e.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Box } from './box.js' +import { Box } from './box.tsx' export default { title: 'Box' } export const WithChildren = () => I am a child diff --git a/components/box/src/box.prod.stories.js b/components/box/src/box.prod.stories.js index d1c9c78e18..49012fd37b 100644 --- a/components/box/src/box.prod.stories.js +++ b/components/box/src/box.prod.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Box } from './box.js' +import { Box } from './box.tsx' const description = ` A box for creating some layout on the page. diff --git a/components/box/src/box.js b/components/box/src/box.tsx similarity index 67% rename from components/box/src/box.js rename to components/box/src/box.tsx index 0221e1462e..7f6e4df196 100644 --- a/components/box/src/box.js +++ b/components/box/src/box.tsx @@ -1,6 +1,19 @@ -import PropTypes from 'prop-types' import React from 'react' +export interface BoxProps { + children?: React.ReactNode + className?: string + dataTest?: string + height?: string + marginTop?: string + maxHeight?: string + maxWidth?: string + minHeight?: string + minWidth?: string + overflow?: string + width?: string +} + export const Box = ({ overflow, height, @@ -13,7 +26,7 @@ export const Box = ({ children, dataTest = 'dhis2-uicore-box', className, -}) => ( +}: BoxProps) => (

{children}
) - -Box.propTypes = { - children: PropTypes.node, - className: PropTypes.string, - dataTest: PropTypes.string, - height: PropTypes.string, - marginTop: PropTypes.string, - maxHeight: PropTypes.string, - maxWidth: PropTypes.string, - minHeight: PropTypes.string, - minWidth: PropTypes.string, - overflow: PropTypes.string, - width: PropTypes.string, -} diff --git a/components/box/src/index.js b/components/box/src/index.js deleted file mode 100644 index 6bb9722ea8..0000000000 --- a/components/box/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Box } from './box.js' diff --git a/components/box/src/index.ts b/components/box/src/index.ts new file mode 100644 index 0000000000..c1dd9dcdf8 --- /dev/null +++ b/components/box/src/index.ts @@ -0,0 +1,2 @@ +export { Box } from './box.tsx' +export type { BoxProps } from './box.tsx' diff --git a/components/box/tsconfig.json b/components/box/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/box/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 7d65cb9881272bcee7ed5a2439f6378d79f1732e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:02:45 +0000 Subject: [PATCH 05/63] feat: migrate divider component to TypeScript Co-Authored-By: henrik.vadet@dhis2.org --- components/divider/d2.config.js | 2 +- components/divider/package.json | 3 ++- .../divider/src/{divider.js => divider.tsx} | 19 +++++++++---------- components/divider/src/index.js | 1 - components/divider/src/index.ts | 2 ++ components/divider/tsconfig.json | 8 ++++++++ 6 files changed, 22 insertions(+), 13 deletions(-) rename components/divider/src/{divider.js => divider.tsx} (83%) delete mode 100644 components/divider/src/index.js create mode 100644 components/divider/src/index.ts create mode 100644 components/divider/tsconfig.json diff --git a/components/divider/d2.config.js b/components/divider/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/divider/d2.config.js +++ b/components/divider/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/divider/package.json b/components/divider/package.json index b9a5671ced..9d84cc0e2f 100644 --- a/components/divider/package.json +++ b/components/divider/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/divider/src/divider.js b/components/divider/src/divider.tsx similarity index 83% rename from components/divider/src/divider.js rename to components/divider/src/divider.tsx index 10f75165db..452805b85b 100644 --- a/components/divider/src/divider.js +++ b/components/divider/src/divider.tsx @@ -1,8 +1,7 @@ import { colors, spacers } from '@dhis2/ui-constants' -import PropTypes from 'prop-types' import React from 'react' -const flipMargin = (margin) => { +const flipMargin = (margin: string): string => { const splitMargin = margin.split(/\s+/) if (splitMargin?.length === 4) { return [ @@ -15,12 +14,19 @@ const flipMargin = (margin) => { return margin } +export interface DividerProps { + className?: string + dataTest?: string + dense?: boolean + margin?: string +} + const Divider = ({ className, dataTest = 'dhis2-uicore-divider', dense, margin = `${spacers.dp8} 0`, -}) => { +}: DividerProps) => { return (
) - -Content.propTypes = { - children: PropTypes.any, - overflow: PropTypes.bool, -} diff --git a/components/chip/src/icon.js b/components/chip/src/icon.tsx similarity index 81% rename from components/chip/src/icon.js rename to components/chip/src/icon.tsx index 844cb2bc77..4ac050062f 100644 --- a/components/chip/src/icon.js +++ b/components/chip/src/icon.tsx @@ -1,8 +1,13 @@ import { spacers } from '@dhis2/ui-constants' -import PropTypes from 'prop-types' import React from 'react' -export const Icon = ({ icon, dataTest }) => { +export interface IconProps { + dataTest: string + /** the slot for an icon is 24x24px, bigger elements will be clipped */ + icon?: React.ReactElement +} + +export const Icon = ({ icon, dataTest }: IconProps) => { if (!icon) { return null } @@ -29,9 +34,3 @@ export const Icon = ({ icon, dataTest }) => { ) } - -Icon.propTypes = { - dataTest: PropTypes.string.isRequired, - /** the slot for an icon is 24x24px, bigger elements will be clipped */ - icon: PropTypes.element, -} diff --git a/components/chip/src/index.js b/components/chip/src/index.js deleted file mode 100644 index 8214f999ee..0000000000 --- a/components/chip/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Chip } from './chip.js' diff --git a/components/chip/src/index.ts b/components/chip/src/index.ts new file mode 100644 index 0000000000..b559e40106 --- /dev/null +++ b/components/chip/src/index.ts @@ -0,0 +1,2 @@ +export { Chip } from './chip.tsx' +export type { ChipProps } from './chip.tsx' diff --git a/components/chip/src/remove.js b/components/chip/src/remove.tsx similarity index 79% rename from components/chip/src/remove.js rename to components/chip/src/remove.tsx index 87c2f3f7df..1f11d3b95e 100644 --- a/components/chip/src/remove.js +++ b/components/chip/src/remove.tsx @@ -1,9 +1,12 @@ import { colors } from '@dhis2/ui-constants' -import PropTypes from 'prop-types' import React from 'react' -import { css, resolve } from 'styled-jsx/css' +import css from 'styled-jsx/css' -function CancelOutline({ className }) { +interface CancelOutlineProps { + className?: string +} + +function CancelOutline({ className }: CancelOutlineProps) { return ( ) } -CancelOutline.propTypes = { - className: PropTypes.string, -} const containerStyle = css` span { @@ -44,18 +44,26 @@ const containerStyle = css` } ` -const removeIcon = resolve` +const removeIcon = css.resolve` svg { fill: ${colors.grey600}; - height: 16px; - width: 16px; + height: 16px; + width: 16px; cursor: pointer; opacity: 1; pointer-events: all; } ` -export const Remove = ({ onRemove, dataTest }) => { +export interface RemoveProps { + dataTest: string + onRemove?: ( + payload: Record, + event: React.MouseEvent + ) => void +} + +export const Remove = ({ onRemove, dataTest }: RemoveProps) => { if (!onRemove) { return null } @@ -75,8 +83,3 @@ export const Remove = ({ onRemove, dataTest }) => { ) } - -Remove.propTypes = { - dataTest: PropTypes.string.isRequired, - onRemove: PropTypes.func, -} diff --git a/components/chip/tsconfig.json b/components/chip/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/chip/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From e2a50d92abdb02d74718583b18f7a650ec34a75d Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 13:31:59 +0000 Subject: [PATCH 12/63] feat: migrate user-avatar component to TypeScript (#9) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik --- components/user-avatar/d2.config.js | 2 +- components/user-avatar/package.json | 3 +- .../src/{image-avatar.js => image-avatar.tsx} | 19 +++++----- components/user-avatar/src/index.js | 1 - components/user-avatar/src/index.ts | 2 + .../src/{text-avatar.js => text-avatar.tsx} | 31 ++++++++-------- .../src/user-avatar.prod.stories.js | 2 +- .../src/{user-avatar.js => user-avatar.tsx} | 37 ++++++++----------- components/user-avatar/tsconfig.json | 8 ++++ 9 files changed, 54 insertions(+), 51 deletions(-) rename components/user-avatar/src/{image-avatar.js => image-avatar.tsx} (68%) delete mode 100644 components/user-avatar/src/index.js create mode 100644 components/user-avatar/src/index.ts rename components/user-avatar/src/{text-avatar.js => text-avatar.tsx} (76%) rename components/user-avatar/src/{user-avatar.js => user-avatar.tsx} (74%) create mode 100644 components/user-avatar/tsconfig.json diff --git a/components/user-avatar/d2.config.js b/components/user-avatar/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/user-avatar/d2.config.js +++ b/components/user-avatar/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/user-avatar/package.json b/components/user-avatar/package.json index 060deeda01..f1ca0ad728 100644 --- a/components/user-avatar/package.json +++ b/components/user-avatar/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/user-avatar/src/image-avatar.js b/components/user-avatar/src/image-avatar.tsx similarity index 68% rename from components/user-avatar/src/image-avatar.js rename to components/user-avatar/src/image-avatar.tsx index 9bad391fce..7349d24b53 100644 --- a/components/user-avatar/src/image-avatar.js +++ b/components/user-avatar/src/image-avatar.tsx @@ -1,19 +1,23 @@ import { useConfig } from '@dhis2/app-runtime' -import PropTypes from 'prop-types' import React from 'react' -export const useAvatarImgSrc = (avatarId) => { - const { baseUrl } = useConfig() +export const useAvatarImgSrc = (avatarId: string): string | undefined => { + const { baseUrl } = useConfig() as { baseUrl: string } return avatarId ? [baseUrl, 'api/fileResources', avatarId, 'data'] .filter((part) => !!part) .map((part) => part.replace(/^\/+|\/+$/g, '')) .join('/') - : null + : undefined } -export const ImageAvatar = ({ avatarId, dataTest }) => { +export interface ImageAvatarProps { + avatarId: string + dataTest?: string +} + +export const ImageAvatar = ({ avatarId, dataTest }: ImageAvatarProps) => { const src = useAvatarImgSrc(avatarId) return ( @@ -30,8 +34,3 @@ export const ImageAvatar = ({ avatarId, dataTest }) => { ) } - -ImageAvatar.propTypes = { - avatarId: PropTypes.string.isRequired, - dataTest: PropTypes.string, -} diff --git a/components/user-avatar/src/index.js b/components/user-avatar/src/index.js deleted file mode 100644 index 85af5fb919..0000000000 --- a/components/user-avatar/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { UserAvatar } from './user-avatar.js' diff --git a/components/user-avatar/src/index.ts b/components/user-avatar/src/index.ts new file mode 100644 index 0000000000..0d91330ed7 --- /dev/null +++ b/components/user-avatar/src/index.ts @@ -0,0 +1,2 @@ +export { UserAvatar } from './user-avatar.tsx' +export type { UserAvatarProps } from './user-avatar.tsx' diff --git a/components/user-avatar/src/text-avatar.js b/components/user-avatar/src/text-avatar.tsx similarity index 76% rename from components/user-avatar/src/text-avatar.js rename to components/user-avatar/src/text-avatar.tsx index d46e5925df..d5bc8cb1e0 100644 --- a/components/user-avatar/src/text-avatar.js +++ b/components/user-avatar/src/text-avatar.tsx @@ -1,20 +1,29 @@ -import { sharedPropTypes, colors } from '@dhis2/ui-constants' +import { colors } from '@dhis2/ui-constants' import cx from 'classnames' -import PropTypes from 'prop-types' import React from 'react' -export const getInitials = (name) => { +export const getInitials = (name: string): string => { const nameParts = name.split(' ') - let initials = nameParts.shift().charAt(0) + let initials = nameParts.shift()!.charAt(0) if (nameParts.length) { - initials += nameParts.pop().charAt(0) + initials += nameParts.pop()!.charAt(0) } return initials } +export interface TextAvatarProps { + name: string + dataTest?: string + extralarge?: boolean + extrasmall?: boolean + large?: boolean + medium?: boolean + small?: boolean +} + export const TextAvatar = ({ name, dataTest = 'dhis2-uicore-textavatar', @@ -23,7 +32,7 @@ export const TextAvatar = ({ large, medium, small, -}) => ( +}: TextAvatarProps) => (
) - -TextAvatar.propTypes = { - name: PropTypes.string.isRequired, - dataTest: PropTypes.string, - extralarge: sharedPropTypes.sizePropType, - extrasmall: sharedPropTypes.sizePropType, - large: sharedPropTypes.sizePropType, - medium: sharedPropTypes.sizePropType, - small: sharedPropTypes.sizePropType, -} diff --git a/components/user-avatar/src/user-avatar.prod.stories.js b/components/user-avatar/src/user-avatar.prod.stories.js index 73066e01b0..9c7242068f 100644 --- a/components/user-avatar/src/user-avatar.prod.stories.js +++ b/components/user-avatar/src/user-avatar.prod.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { UserAvatar } from './user-avatar.js' +import { UserAvatar } from './user-avatar.tsx' export default { title: 'User Avatar', diff --git a/components/user-avatar/src/user-avatar.js b/components/user-avatar/src/user-avatar.tsx similarity index 74% rename from components/user-avatar/src/user-avatar.js rename to components/user-avatar/src/user-avatar.tsx index 1421b6ce87..150ccad16d 100644 --- a/components/user-avatar/src/user-avatar.js +++ b/components/user-avatar/src/user-avatar.tsx @@ -1,9 +1,7 @@ -import { sharedPropTypes } from '@dhis2/ui-constants' import cx from 'classnames' -import PropTypes from 'prop-types' import React from 'react' -import { ImageAvatar } from './image-avatar.js' -import { TextAvatar } from './text-avatar.js' +import { ImageAvatar } from './image-avatar.tsx' +import { TextAvatar } from './text-avatar.tsx' /** An avatar is a visual icon that represents a user. @@ -17,6 +15,19 @@ import { UserAvatar } from '@dhis2/ui' ``` */ +export interface UserAvatarProps { + name: string + ariaLabel?: string + avatarId?: string + className?: string + dataTest?: string + extralarge?: boolean + extrasmall?: boolean + large?: boolean + medium?: boolean + small?: boolean +} + const UserAvatar = ({ name, avatarId, @@ -28,7 +39,7 @@ const UserAvatar = ({ medium, small, ariaLabel, -}) => ( +}: UserAvatarProps) => (
) -UserAvatar.propTypes = { - // Name could stop being required if we implement an - // SVG fallback with a `IconUser24`. - // This has been discussed and deferred - name: PropTypes.string.isRequired, - ariaLabel: PropTypes.string, - avatarId: PropTypes.string, - className: PropTypes.string, - dataTest: PropTypes.string, - extralarge: sharedPropTypes.sizePropType, - extrasmall: sharedPropTypes.sizePropType, - large: sharedPropTypes.sizePropType, - medium: sharedPropTypes.sizePropType, - small: sharedPropTypes.sizePropType, -} - export { UserAvatar } diff --git a/components/user-avatar/tsconfig.json b/components/user-avatar/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/user-avatar/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 2286a8d0b576c3b1b57bc45b5af3280af795a374 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 13:38:12 +0000 Subject: [PATCH 13/63] fix: update test file imports after user-avatar TypeScript migration (#11) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik --- components/user-avatar/src/image-avatar.test.js | 2 +- components/user-avatar/src/text-avatar.test.js | 2 +- components/user-avatar/src/user-avatar.test.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/user-avatar/src/image-avatar.test.js b/components/user-avatar/src/image-avatar.test.js index 8e867d1c22..25914603ce 100644 --- a/components/user-avatar/src/image-avatar.test.js +++ b/components/user-avatar/src/image-avatar.test.js @@ -1,5 +1,5 @@ import { useConfig } from '@dhis2/app-runtime' -import { useAvatarImgSrc } from './image-avatar.js' +import { useAvatarImgSrc } from './image-avatar.tsx' jest.mock('@dhis2/app-runtime', () => ({ useConfig: jest.fn(), diff --git a/components/user-avatar/src/text-avatar.test.js b/components/user-avatar/src/text-avatar.test.js index b097e886b2..98d810b0d7 100644 --- a/components/user-avatar/src/text-avatar.test.js +++ b/components/user-avatar/src/text-avatar.test.js @@ -1,6 +1,6 @@ import { shallow } from 'enzyme' import React from 'react' -import { getInitials, TextAvatar } from './text-avatar.js' +import { getInitials, TextAvatar } from './text-avatar.tsx' describe('TextAvatar', () => { describe('sizes', () => { diff --git a/components/user-avatar/src/user-avatar.test.js b/components/user-avatar/src/user-avatar.test.js index ddb6ab3c2d..ae3211cdcf 100644 --- a/components/user-avatar/src/user-avatar.test.js +++ b/components/user-avatar/src/user-avatar.test.js @@ -1,8 +1,8 @@ import { shallow } from 'enzyme' import React from 'react' -import { ImageAvatar } from './image-avatar.js' -import { TextAvatar } from './text-avatar.js' -import { UserAvatar } from './user-avatar.js' +import { ImageAvatar } from './image-avatar.tsx' +import { TextAvatar } from './text-avatar.tsx' +import { UserAvatar } from './user-avatar.tsx' describe('UserAvatar', () => { it('renders an ImageAvatar when a avatarId is provided', () => { From f0fef091fa0c0c22f5fa264f761c9cbc13a8da7e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 13:48:27 +0000 Subject: [PATCH 14/63] feat: migrate intersection-detector component to TypeScript Co-Authored-By: Eirik --- components/intersection-detector/d2.config.js | 2 +- components/intersection-detector/package.json | 3 +- components/intersection-detector/src/index.js | 1 - components/intersection-detector/src/index.ts | 2 + .../src/intersection-detector.e2e.stories.js | 2 +- .../src/intersection-detector.prod.stories.js | 2 +- ...-detector.js => intersection-detector.tsx} | 37 ++++++++----------- .../intersection-detector/tsconfig.json | 8 ++++ 8 files changed, 31 insertions(+), 26 deletions(-) delete mode 100644 components/intersection-detector/src/index.js create mode 100644 components/intersection-detector/src/index.ts rename components/intersection-detector/src/{intersection-detector.js => intersection-detector.tsx} (85%) create mode 100644 components/intersection-detector/tsconfig.json diff --git a/components/intersection-detector/d2.config.js b/components/intersection-detector/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/intersection-detector/d2.config.js +++ b/components/intersection-detector/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/intersection-detector/package.json b/components/intersection-detector/package.json index ab607f8228..9b17af6a62 100644 --- a/components/intersection-detector/package.json +++ b/components/intersection-detector/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/intersection-detector/src/index.js b/components/intersection-detector/src/index.js deleted file mode 100644 index 0fe90455b5..0000000000 --- a/components/intersection-detector/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { IntersectionDetector } from './intersection-detector.js' diff --git a/components/intersection-detector/src/index.ts b/components/intersection-detector/src/index.ts new file mode 100644 index 0000000000..3ca38e1a36 --- /dev/null +++ b/components/intersection-detector/src/index.ts @@ -0,0 +1,2 @@ +export { IntersectionDetector } from './intersection-detector.tsx' +export type { IntersectionDetectorProps } from './intersection-detector.tsx' diff --git a/components/intersection-detector/src/intersection-detector.e2e.stories.js b/components/intersection-detector/src/intersection-detector.e2e.stories.js index f500e9aeff..2402d25394 100644 --- a/components/intersection-detector/src/intersection-detector.e2e.stories.js +++ b/components/intersection-detector/src/intersection-detector.e2e.stories.js @@ -1,5 +1,5 @@ import React, { useRef } from 'react' -import { IntersectionDetector } from './intersection-detector.js' +import { IntersectionDetector } from './intersection-detector.tsx' window.onChange = window.Cypress ? window.Cypress.cy.stub() : () => null diff --git a/components/intersection-detector/src/intersection-detector.prod.stories.js b/components/intersection-detector/src/intersection-detector.prod.stories.js index 81a7421648..9afdad1972 100644 --- a/components/intersection-detector/src/intersection-detector.prod.stories.js +++ b/components/intersection-detector/src/intersection-detector.prod.stories.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' import React, { useState, useRef } from 'react' -import { IntersectionDetector } from './intersection-detector.js' +import { IntersectionDetector } from './intersection-detector.tsx' const description = ` A tool to performantly detect when two components intersect, which is often better to use than scroll listeners. A common use case is to detect when a child component is in view inside a scrolling parent. Uses an [\`IntersectionObserver\`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) object internally. diff --git a/components/intersection-detector/src/intersection-detector.js b/components/intersection-detector/src/intersection-detector.tsx similarity index 85% rename from components/intersection-detector/src/intersection-detector.js rename to components/intersection-detector/src/intersection-detector.tsx index 5e63a5e7de..65e96e686e 100644 --- a/components/intersection-detector/src/intersection-detector.js +++ b/components/intersection-detector/src/intersection-detector.tsx @@ -1,6 +1,17 @@ -import PropTypes from 'prop-types' import React, { useEffect, useRef } from 'react' +export interface IntersectionDetectorProps { + /** React ref on other component to detect intersections with */ + rootRef: React.RefObject + /** Called with signature `({ isIntersecting: bool })` */ + onChange: (payload: { isIntersecting: boolean }) => void + children?: React.ReactNode + className?: string + dataTest?: string + /** The [threshold](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) value: a value from 0.0 to 1.0 that controls the point at which an intersecting component is considered 'intersected' or 'visible' and the onChange callback triggers */ + threshold?: number +} + export const IntersectionDetector = ({ threshold = 0, onChange, @@ -8,7 +19,7 @@ export const IntersectionDetector = ({ className, dataTest = 'dhis2-uicore-intersectiondetector', rootRef, -}) => { +}: IntersectionDetectorProps) => { // Use useRef instead of useState to prevent unnecessary re-render: // The state changes won't be reflected in what this component renders, // so there's no need for re-rendering the (potentially computational @@ -17,11 +28,11 @@ export const IntersectionDetector = ({ // @var {Object} // @prop {bool} current - const isIntersecting = useRef() + const isIntersecting = useRef() // @var {Object} // @prop {HTMLElement} current - const intersectionRef = useRef() + const intersectionRef = useRef(null) const onChangeRef = useRef(onChange) onChangeRef.current = onChange @@ -31,7 +42,7 @@ export const IntersectionDetector = ({ const intersectionEl = intersectionRef.current if (rootEl && intersectionEl) { - const onIntersection = (entries) => { + const onIntersection = (entries: IntersectionObserverEntry[]) => { // Currently there's no way to supply multiple thresholds, // so a single entry can be assumed safely const [entry] = entries @@ -79,19 +90,3 @@ export const IntersectionDetector = ({
) } - -IntersectionDetector.propTypes = { - /** React ref on other component to detect intersections with */ - rootRef: PropTypes.shape({ - // not required so `current` can be `null` - current: PropTypes.instanceOf(HTMLElement), - }).isRequired, - /** Called with signature `({ isIntersecting: bool })` */ - onChange: PropTypes.func.isRequired, - - children: PropTypes.any, - className: PropTypes.string, - dataTest: PropTypes.string, - /** The [threshold](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) value: a value from 0.0 to 1.0 that controls the point at which an intersecting component is considered 'intersected' or 'visible' and the onChange callback triggers */ - threshold: PropTypes.number, -} diff --git a/components/intersection-detector/tsconfig.json b/components/intersection-detector/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/intersection-detector/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 19724511f64ba387789dff753a8e1b928b21e395 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 13:48:43 +0000 Subject: [PATCH 15/63] feat: migrate css component to TypeScript Co-Authored-By: Eirik --- components/css/d2.config.js | 2 +- components/css/package.json | 3 +- .../src/css-reset/css-reset.prod.stories.js | 2 +- .../css-reset/{css-reset.js => css-reset.tsx} | 2 +- components/css/src/css-reset/index.js | 1 - components/css/src/css-reset/index.ts | 1 + .../css-variables.e2e.stories.js | 2 +- .../css-variables.prod.stories.js | 2 +- .../{css-variables.js => css-variables.tsx} | 32 +++++++++---------- components/css/src/css-variables/index.js | 1 - components/css/src/css-variables/index.ts | 2 ++ components/css/src/index.js | 2 -- components/css/src/index.ts | 3 ++ components/css/tsconfig.json | 8 +++++ 14 files changed, 37 insertions(+), 26 deletions(-) rename components/css/src/css-reset/{css-reset.js => css-reset.tsx} (98%) delete mode 100644 components/css/src/css-reset/index.js create mode 100644 components/css/src/css-reset/index.ts rename components/css/src/css-variables/{css-variables.js => css-variables.tsx} (58%) delete mode 100644 components/css/src/css-variables/index.js create mode 100644 components/css/src/css-variables/index.ts delete mode 100644 components/css/src/index.js create mode 100644 components/css/src/index.ts create mode 100644 components/css/tsconfig.json diff --git a/components/css/d2.config.js b/components/css/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/css/d2.config.js +++ b/components/css/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/css/package.json b/components/css/package.json index acd7bd6e47..f7d0d1178f 100644 --- a/components/css/package.json +++ b/components/css/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/css/src/css-reset/css-reset.prod.stories.js b/components/css/src/css-reset/css-reset.prod.stories.js index c52e293128..a3088cf18d 100644 --- a/components/css/src/css-reset/css-reset.prod.stories.js +++ b/components/css/src/css-reset/css-reset.prod.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { CssReset } from './index.js' +import { CssReset } from './index.ts' const description = ` A tool for adding a global normalization stylesheet into the DOM that applies DHIS2 styles. diff --git a/components/css/src/css-reset/css-reset.js b/components/css/src/css-reset/css-reset.tsx similarity index 98% rename from components/css/src/css-reset/css-reset.js rename to components/css/src/css-reset/css-reset.tsx index 57a4798798..89a2af1e01 100644 --- a/components/css/src/css-reset/css-reset.js +++ b/components/css/src/css-reset/css-reset.tsx @@ -1,7 +1,7 @@ import { theme } from '@dhis2/ui-constants' import React from 'react' -const CssReset = () => ( +const CssReset = (): React.ReactElement => ( ) - -Label.propTypes = { - children: PropTypes.string, - className: PropTypes.string, - dataTest: PropTypes.string, - disabled: PropTypes.bool, - htmlFor: PropTypes.string, - id: PropTypes.string, - required: PropTypes.bool, -} diff --git a/components/label/tsconfig.json b/components/label/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/label/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From b63109b418ea64bcc3bc2c9191b69c46a5f0c9ad Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:16:05 +0000 Subject: [PATCH 24/63] feat: migrate card component to TypeScript (#20) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik --- components/card/d2.config.js | 2 +- components/card/package.json | 3 ++- components/card/src/card.e2e.stories.js | 2 +- components/card/src/card.prod.stories.js | 2 +- components/card/src/{card.js => card.tsx} | 19 +++++++++++-------- components/card/src/index.js | 1 - components/card/src/index.ts | 2 ++ components/card/tsconfig.json | 8 ++++++++ 8 files changed, 26 insertions(+), 13 deletions(-) rename components/card/src/{card.js => card.tsx} (71%) delete mode 100644 components/card/src/index.js create mode 100644 components/card/src/index.ts create mode 100644 components/card/tsconfig.json diff --git a/components/card/d2.config.js b/components/card/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/card/d2.config.js +++ b/components/card/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/card/package.json b/components/card/package.json index dca61cba4f..3331efa15f 100644 --- a/components/card/package.json +++ b/components/card/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/card/src/card.e2e.stories.js b/components/card/src/card.e2e.stories.js index 2da68f0aa9..b0badc3609 100644 --- a/components/card/src/card.e2e.stories.js +++ b/components/card/src/card.e2e.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Card } from './card.js' +import { Card } from './card.tsx' export default { title: 'Card' } export const WithChildren = () => ( diff --git a/components/card/src/card.prod.stories.js b/components/card/src/card.prod.stories.js index 7421eb4c57..0208538090 100644 --- a/components/card/src/card.prod.stories.js +++ b/components/card/src/card.prod.stories.js @@ -1,6 +1,6 @@ import { Box } from '@dhis2-ui/box' import React from 'react' -import { Card } from './card.js' +import { Card } from './card.tsx' const subtitle = ` A card is a container element for grouping together diff --git a/components/card/src/card.js b/components/card/src/card.tsx similarity index 71% rename from components/card/src/card.js rename to components/card/src/card.tsx index 8de324e841..b0b3c698df 100644 --- a/components/card/src/card.js +++ b/components/card/src/card.tsx @@ -1,9 +1,18 @@ import { colors, elevations } from '@dhis2/ui-constants' import cx from 'classnames' -import PropTypes from 'prop-types' import React from 'react' -const Card = ({ className, children, dataTest = 'dhis2-uicore-card' }) => ( +export interface CardProps { + children?: React.ReactNode + className?: string + dataTest?: string +} + +const Card = ({ + className, + children, + dataTest = 'dhis2-uicore-card', +}: CardProps) => (
{children} @@ -23,10 +32,4 @@ const Card = ({ className, children, dataTest = 'dhis2-uicore-card' }) => (
) -Card.propTypes = { - children: PropTypes.node, - className: PropTypes.string, - dataTest: PropTypes.string, -} - export { Card } diff --git a/components/card/src/index.js b/components/card/src/index.js deleted file mode 100644 index cec521f960..0000000000 --- a/components/card/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Card } from './card.js' diff --git a/components/card/src/index.ts b/components/card/src/index.ts new file mode 100644 index 0000000000..cf559a4979 --- /dev/null +++ b/components/card/src/index.ts @@ -0,0 +1,2 @@ +export { Card } from './card.tsx' +export type { CardProps } from './card.tsx' diff --git a/components/card/tsconfig.json b/components/card/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/card/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 28038df7326b4745cbb5304e04f5773972050af7 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:17:16 +0000 Subject: [PATCH 25/63] feat: migrate legend component to TypeScript (#21) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik --- components/legend/d2.config.js | 2 +- components/legend/package.json | 3 ++- components/legend/src/index.js | 1 - components/legend/src/index.ts | 2 ++ components/legend/src/legend.e2e.stories.js | 2 +- components/legend/src/legend.prod.stories.js | 2 +- .../legend/src/{legend.js => legend.tsx} | 19 +++++++++---------- components/legend/tsconfig.json | 8 ++++++++ 8 files changed, 24 insertions(+), 15 deletions(-) delete mode 100644 components/legend/src/index.js create mode 100644 components/legend/src/index.ts rename components/legend/src/{legend.js => legend.tsx} (77%) create mode 100644 components/legend/tsconfig.json diff --git a/components/legend/d2.config.js b/components/legend/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/legend/d2.config.js +++ b/components/legend/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/legend/package.json b/components/legend/package.json index 15f292d326..b235bf2bf9 100644 --- a/components/legend/package.json +++ b/components/legend/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/legend/src/index.js b/components/legend/src/index.js deleted file mode 100644 index 05890c4220..0000000000 --- a/components/legend/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Legend } from './legend.js' diff --git a/components/legend/src/index.ts b/components/legend/src/index.ts new file mode 100644 index 0000000000..50d47ed761 --- /dev/null +++ b/components/legend/src/index.ts @@ -0,0 +1,2 @@ +export { Legend } from './legend.tsx' +export type { LegendProps } from './legend.tsx' diff --git a/components/legend/src/legend.e2e.stories.js b/components/legend/src/legend.e2e.stories.js index ad4f731aea..ceb5f0c442 100644 --- a/components/legend/src/legend.e2e.stories.js +++ b/components/legend/src/legend.e2e.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Legend } from './legend.js' +import { Legend } from './legend.tsx' export default { title: 'Legend' } export const WithContentAndRequired = () => ( diff --git a/components/legend/src/legend.prod.stories.js b/components/legend/src/legend.prod.stories.js index b236a15546..2fd5db06e2 100644 --- a/components/legend/src/legend.prod.stories.js +++ b/components/legend/src/legend.prod.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { Legend } from './legend.js' +import { Legend } from './legend.tsx' const description = ` Legends are to be used in a Field Set to describe the form fields. They may indicate that the fields are required. diff --git a/components/legend/src/legend.js b/components/legend/src/legend.tsx similarity index 77% rename from components/legend/src/legend.js rename to components/legend/src/legend.tsx index 04b99c658d..8e73475a64 100644 --- a/components/legend/src/legend.js +++ b/components/legend/src/legend.tsx @@ -1,14 +1,21 @@ import { colors } from '@dhis2/ui-constants' import { Required } from '@dhis2-ui/required' -import PropTypes from 'prop-types' import React from 'react' +export interface LegendProps { + children?: React.ReactNode + className?: string + dataTest?: string + /** Indicates the associated field set is required */ + required?: boolean +} + const Legend = ({ className, children, required, dataTest = 'dhis2-uicore-legend', -}) => ( +}: LegendProps) => ( {children} @@ -24,12 +31,4 @@ const Legend = ({ ) -Legend.propTypes = { - children: PropTypes.node, - className: PropTypes.string, - dataTest: PropTypes.string, - /** Indicates the associated field set is required */ - required: PropTypes.bool, -} - export { Legend } diff --git a/components/legend/tsconfig.json b/components/legend/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/legend/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 3ff3f1af97b9719bc1c27408c7842cba91816e3c Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:18:00 +0000 Subject: [PATCH 26/63] feat: migrate pagination component to TypeScript * feat: migrate pagination component to TypeScript Co-Authored-By: Eirik * fix: remove unsafe as casts by providing no-op defaults for onPageChange/onPageSizeChange Co-Authored-By: Eirik --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik --- components/pagination/d2.config.js | 2 +- components/pagination/i18n/en.pot | 18 ++--- components/pagination/package.json | 5 +- .../src/__tests__/get-item-range.test.js | 2 +- .../src/__tests__/page-controls.test.js | 2 +- .../src/__tests__/page-select.test.js | 2 +- .../src/__tests__/page-size-select.test.js | 2 +- .../src/__tests__/page-summary.test.js | 4 +- .../src/__tests__/pagination.test.js | 2 +- ...xt.js => get-default-page-summary-text.ts} | 13 +++- .../{get-item-range.js => get-item-range.ts} | 17 ++++- components/pagination/src/index.js | 1 - components/pagination/src/index.ts | 2 + components/pagination/src/locales/index.d.ts | 3 + .../{page-controls.js => page-controls.tsx} | 30 ++++---- .../src/{page-select.js => page-select.tsx} | 34 ++++----- ...ge-size-select.js => page-size-select.tsx} | 32 +++++---- .../src/{page-summary.js => page-summary.tsx} | 33 ++++----- .../pagination/src/pagination.prod.stories.js | 2 +- .../src/{pagination.js => pagination.tsx} | 70 ++++++++++--------- components/pagination/tsconfig.json | 8 +++ 21 files changed, 163 insertions(+), 121 deletions(-) rename components/pagination/src/{get-default-page-summary-text.js => get-default-page-summary-text.ts} (71%) rename components/pagination/src/{get-item-range.js => get-item-range.ts} (69%) delete mode 100644 components/pagination/src/index.js create mode 100644 components/pagination/src/index.ts create mode 100644 components/pagination/src/locales/index.d.ts rename components/pagination/src/{page-controls.js => page-controls.tsx} (77%) rename components/pagination/src/{page-select.js => page-select.tsx} (65%) rename components/pagination/src/{page-size-select.js => page-size-select.tsx} (68%) rename components/pagination/src/{page-summary.js => page-summary.tsx} (69%) rename components/pagination/src/{pagination.js => pagination.tsx} (73%) create mode 100644 components/pagination/tsconfig.json diff --git a/components/pagination/d2.config.js b/components/pagination/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/pagination/d2.config.js +++ b/components/pagination/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/pagination/i18n/en.pot b/components/pagination/i18n/en.pot index 1472c58cff..ecd6c7ff7a 100644 --- a/components/pagination/i18n/en.pot +++ b/components/pagination/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2022-03-10T20:20:19.392Z\n" -"PO-Revision-Date: 2022-03-10T20:20:19.392Z\n" +"POT-Creation-Date: 2026-04-13T15:06:52.163Z\n" +"PO-Revision-Date: 2026-04-13T15:06:52.164Z\n" msgid "" "Page {{page}} of {{pageCount}}, items {{firstItem}}-{{lastItem}} of " @@ -21,6 +21,13 @@ msgstr "Page {{page}}, items {{firstItem}}-{{lastItem}}" msgid "Page {{page}}" msgstr "Page {{page}}" +msgid "" +"You are at page {{page}} showing items {{firstItem}}-{{lastItem}}, but " +"there are {{pageCount}} pages and {{total}} items" +msgstr "" +"You are at page {{page}} showing items {{firstItem}}-{{lastItem}}, but " +"there are {{pageCount}} pages and {{total}} items" + msgid "Next" msgstr "Next" @@ -32,10 +39,3 @@ msgstr "Items per page" msgid "Previous" msgstr "Previous" - -msgid "" -"You are at page {{page}} showing items {{firstItem}}-{{lastItem}}, but " -"there are {{pageCount}} pages and {{total}} items" -msgstr "" -"You are at page {{page}} showing items {{firstItem}}-{{lastItem}}, but " -"there are {{pageCount}} pages and {{total}} items" diff --git a/components/pagination/package.json b/components/pagination/package.json index a47950b5a2..f3819e3ee3 100644 --- a/components/pagination/package.json +++ b/components/pagination/package.json @@ -23,8 +23,9 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", - "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js", + "typecheck": "tsc --noEmit" }, "peerDependencies": { "@dhis2/d2-i18n": "^1", diff --git a/components/pagination/src/__tests__/get-item-range.test.js b/components/pagination/src/__tests__/get-item-range.test.js index 38b55da1f3..019387a36f 100644 --- a/components/pagination/src/__tests__/get-item-range.test.js +++ b/components/pagination/src/__tests__/get-item-range.test.js @@ -1,5 +1,5 @@ import * as mockPagers from '../__fixtures__/index.js' -import { getItemRange } from '../get-item-range.js' +import { getItemRange } from '../get-item-range.ts' describe('getItemRange', () => { it('calculates the firstItem and lastItem correctly', () => { diff --git a/components/pagination/src/__tests__/page-controls.test.js b/components/pagination/src/__tests__/page-controls.test.js index d208f79c12..c62295b43a 100644 --- a/components/pagination/src/__tests__/page-controls.test.js +++ b/components/pagination/src/__tests__/page-controls.test.js @@ -1,6 +1,6 @@ import { shallow } from 'enzyme' import React from 'react' -import { PageControls } from '../page-controls.js' +import { PageControls } from '../page-controls.tsx' describe('', () => { const mockOnClick = jest.fn() diff --git a/components/pagination/src/__tests__/page-select.test.js b/components/pagination/src/__tests__/page-select.test.js index daa9580128..2566ee7b84 100644 --- a/components/pagination/src/__tests__/page-select.test.js +++ b/components/pagination/src/__tests__/page-select.test.js @@ -2,7 +2,7 @@ import { SingleSelect } from '@dhis2-ui/select' import { shallow } from 'enzyme' import React from 'react' import * as mockPagers from '../__fixtures__/index.js' -import { PageSelect, createAvailablePages } from '../page-select.js' +import { PageSelect, createAvailablePages } from '../page-select.tsx' describe('', () => { const mockOnSelect = jest.fn() diff --git a/components/pagination/src/__tests__/page-size-select.test.js b/components/pagination/src/__tests__/page-size-select.test.js index 3f4af42635..e6d5ea2b70 100644 --- a/components/pagination/src/__tests__/page-size-select.test.js +++ b/components/pagination/src/__tests__/page-size-select.test.js @@ -2,7 +2,7 @@ import { SingleSelect } from '@dhis2-ui/select' import { shallow } from 'enzyme' import React from 'react' import * as mockPagers from '../__fixtures__/index.js' -import { PageSizeSelect } from '../page-size-select.js' +import { PageSizeSelect } from '../page-size-select.tsx' describe('', () => { const mockOnSelect = jest.fn() diff --git a/components/pagination/src/__tests__/page-summary.test.js b/components/pagination/src/__tests__/page-summary.test.js index 6fb263472d..d6d28728a5 100644 --- a/components/pagination/src/__tests__/page-summary.test.js +++ b/components/pagination/src/__tests__/page-summary.test.js @@ -1,7 +1,7 @@ import { shallow } from 'enzyme' import React from 'react' -import { getDefaultPageSummaryText } from '../get-default-page-summary-text.js' -import { PageSummary } from '../page-summary.js' +import { getDefaultPageSummaryText } from '../get-default-page-summary-text.ts' +import { PageSummary } from '../page-summary.tsx' describe('', () => { const props = { diff --git a/components/pagination/src/__tests__/pagination.test.js b/components/pagination/src/__tests__/pagination.test.js index 8fc244bb9e..b67afc3da0 100644 --- a/components/pagination/src/__tests__/pagination.test.js +++ b/components/pagination/src/__tests__/pagination.test.js @@ -2,7 +2,7 @@ import '@testing-library/dom' import { render } from '@testing-library/react' import React from 'react' import * as mockPagers from '../__fixtures__/index.js' -import { Pagination } from '../pagination.js' +import { Pagination } from '../pagination.tsx' describe('', () => { describe('Pagination with total and totalPages', () => { diff --git a/components/pagination/src/get-default-page-summary-text.js b/components/pagination/src/get-default-page-summary-text.ts similarity index 71% rename from components/pagination/src/get-default-page-summary-text.js rename to components/pagination/src/get-default-page-summary-text.ts index e697e09921..80831820a7 100644 --- a/components/pagination/src/get-default-page-summary-text.js +++ b/components/pagination/src/get-default-page-summary-text.ts @@ -1,6 +1,15 @@ import i18n from './locales/index.js' -const isValidNumber = (input) => typeof input === 'number' && !isNaN(input) +const isValidNumber = (input: unknown): input is number => + typeof input === 'number' && !isNaN(input) + +export interface PageSummaryTextOptions { + firstItem?: number + lastItem?: number + page: number + pageCount?: number + total?: number +} export const getDefaultPageSummaryText = ({ firstItem, @@ -8,7 +17,7 @@ export const getDefaultPageSummaryText = ({ page, pageCount, total, -}) => { +}: PageSummaryTextOptions): string => { if (isValidNumber(total) && isValidNumber(lastItem)) { return i18n.t( 'Page {{page}} of {{pageCount}}, items {{firstItem}}-{{lastItem}} of {{total}}', diff --git a/components/pagination/src/get-item-range.js b/components/pagination/src/get-item-range.ts similarity index 69% rename from components/pagination/src/get-item-range.js rename to components/pagination/src/get-item-range.ts index 1021e6eb3f..60dd7b865f 100644 --- a/components/pagination/src/get-item-range.js +++ b/components/pagination/src/get-item-range.ts @@ -1,10 +1,23 @@ +export interface GetItemRangeOptions { + isLastPage?: boolean + page: number + pageLength?: number + pageSize: number + total?: number +} + +export interface ItemRange { + firstItem: number + lastItem: number +} + export const getItemRange = ({ isLastPage, page, pageLength, pageSize, total, -}) => { +}: GetItemRangeOptions): ItemRange => { // page is 1-based let firstItem = (page - 1) * pageSize + 1 let lastItem = firstItem + pageSize - 1 @@ -26,7 +39,7 @@ export const getItemRange = ({ lastItem = firstItem + pageLength - 1 } - if (isLastPage && isNaN(total) && isNaN(pageLength)) { + if (isLastPage && isNaN(total as number) && isNaN(pageLength as number)) { // impossible to accurately determine the last item lastItem = NaN } diff --git a/components/pagination/src/index.js b/components/pagination/src/index.js deleted file mode 100644 index fbca37bf74..0000000000 --- a/components/pagination/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Pagination } from './pagination.js' diff --git a/components/pagination/src/index.ts b/components/pagination/src/index.ts new file mode 100644 index 0000000000..cf6c9af36f --- /dev/null +++ b/components/pagination/src/index.ts @@ -0,0 +1,2 @@ +export { Pagination } from './pagination.tsx' +export type { PaginationProps } from './pagination.tsx' diff --git a/components/pagination/src/locales/index.d.ts b/components/pagination/src/locales/index.d.ts new file mode 100644 index 0000000000..614d9ce001 --- /dev/null +++ b/components/pagination/src/locales/index.d.ts @@ -0,0 +1,3 @@ +import i18next from 'i18next' +declare const i18n: typeof i18next +export default i18n diff --git a/components/pagination/src/page-controls.js b/components/pagination/src/page-controls.tsx similarity index 77% rename from components/pagination/src/page-controls.js rename to components/pagination/src/page-controls.tsx index 957f247ca8..821dd1db59 100644 --- a/components/pagination/src/page-controls.js +++ b/components/pagination/src/page-controls.tsx @@ -1,10 +1,12 @@ import { spacers } from '@dhis2/ui-constants' import { IconChevronLeft16, IconChevronRight16 } from '@dhis2/ui-icons' import { Button } from '@dhis2-ui/button' -import PropTypes from 'prop-types' import React from 'react' -const translate = (prop, interpolationObject) => { +const translate = ( + prop: string | ((interpolationObject?: Record) => string), + interpolationObject?: Record +): string => { if (typeof prop === 'function') { return prop(interpolationObject) } @@ -12,6 +14,16 @@ const translate = (prop, interpolationObject) => { return prop } +export interface PageControlsProps { + dataTest: string + nextPageText: string | ((interpolationObject?: Record) => string) + page: number + previousPageText: string | ((interpolationObject?: Record) => string) + onClick: (page: number) => void + isNextDisabled?: boolean + isPreviousDisabled?: boolean +} + const PageControls = ({ dataTest, isNextDisabled, @@ -20,7 +32,7 @@ const PageControls = ({ page, previousPageText, onClick, -}) => ( +}: PageControlsProps) => (
) -export const Toggle = ({ open, onOpen, onClose, dataTest }) => { +export interface ToggleProps { + dataTest: string + open?: boolean + onClose?: ( + payload: { open: boolean }, + event: React.MouseEvent + ) => void + onOpen?: ( + payload: { open: boolean }, + event: React.MouseEvent + ) => void +} + +export const Toggle = ({ open, onOpen, onClose, dataTest }: ToggleProps) => { const onClick = open ? onClose : onOpen return (
onClick && onClick({ open: !open }, event)} + onClick={(event) => + onClick && onClick({ open: !open }, event) + } > @@ -84,10 +98,3 @@ export const Toggle = ({ open, onOpen, onClose, dataTest }) => {
) } - -Toggle.propTypes = { - dataTest: PropTypes.string.isRequired, - open: PropTypes.bool, - onClose: PropTypes.func, - onOpen: PropTypes.func, -} diff --git a/components/node/tsconfig.json b/components/node/tsconfig.json new file mode 100644 index 0000000000..083f7c60d0 --- /dev/null +++ b/components/node/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "**/*.stories.*", "**/*.test.*", "**/*.e2e.*"] +} From 212b856276480ba2bc959df8dbd31a843e134df6 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:48:29 +0000 Subject: [PATCH 32/63] feat: migrate text-area component to TypeScript Co-Authored-By: Eirik --- components/text-area/d2.config.js | 2 +- components/text-area/package.json | 3 +- components/text-area/src/index.js | 2 - components/text-area/src/index.ts | 4 + .../__tests__/text-area-field.test.js | 2 +- .../text-area/src/text-area-field/index.js | 1 - .../text-area/src/text-area-field/index.ts | 2 + .../text-area-field.e2e.stories.js | 2 +- .../text-area-field.prod.stories.js | 2 +- ...text-area-field.js => text-area-field.tsx} | 110 ++++++------ .../src/text-area/__tests__/text-area.test.js | 2 +- components/text-area/src/text-area/index.js | 1 - components/text-area/src/text-area/index.ts | 2 + .../src/text-area/text-area.e2e.stories.js | 2 +- .../src/text-area/text-area.prod.stories.js | 2 +- ...ext-area.styles.js => text-area.styles.ts} | 0 .../text-area/{text-area.js => text-area.tsx} | 166 ++++++++++-------- components/text-area/tsconfig.json | 8 + 18 files changed, 170 insertions(+), 143 deletions(-) delete mode 100644 components/text-area/src/index.js create mode 100644 components/text-area/src/index.ts delete mode 100644 components/text-area/src/text-area-field/index.js create mode 100644 components/text-area/src/text-area-field/index.ts rename components/text-area/src/text-area-field/{text-area-field.js => text-area-field.tsx} (75%) delete mode 100644 components/text-area/src/text-area/index.js create mode 100644 components/text-area/src/text-area/index.ts rename components/text-area/src/text-area/{text-area.styles.js => text-area.styles.ts} (100%) rename components/text-area/src/text-area/{text-area.js => text-area.tsx} (68%) create mode 100644 components/text-area/tsconfig.json diff --git a/components/text-area/d2.config.js b/components/text-area/d2.config.js index 9973893afc..026fb9f036 100644 --- a/components/text-area/d2.config.js +++ b/components/text-area/d2.config.js @@ -1,6 +1,6 @@ module.exports = { type: 'lib', entryPoints: { - lib: 'src/index.js', + lib: 'src/index.ts', }, } diff --git a/components/text-area/package.json b/components/text-area/package.json index 5b842f36eb..0e8074d7b9 100644 --- a/components/text-area/package.json +++ b/components/text-area/package.json @@ -23,7 +23,8 @@ }, "scripts": { "start": "storybook dev -c ../../storybook/config --port 5000", - "build": "d2-app-scripts build", + "build": "d2-app-scripts build && node ../../scripts/post-build-rename.js", + "typecheck": "tsc --noEmit", "test": "d2-app-scripts test --jestConfig ../../jest.config.shared.js" }, "peerDependencies": { diff --git a/components/text-area/src/index.js b/components/text-area/src/index.js deleted file mode 100644 index 5df87a123f..0000000000 --- a/components/text-area/src/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { TextArea } from './text-area/index.js' -export { TextAreaField } from './text-area-field/index.js' diff --git a/components/text-area/src/index.ts b/components/text-area/src/index.ts new file mode 100644 index 0000000000..fa31dc04a5 --- /dev/null +++ b/components/text-area/src/index.ts @@ -0,0 +1,4 @@ +export { TextArea } from './text-area/index.ts' +export type { TextAreaProps } from './text-area/index.ts' +export { TextAreaField } from './text-area-field/index.ts' +export type { TextAreaFieldProps } from './text-area-field/index.ts' diff --git a/components/text-area/src/text-area-field/__tests__/text-area-field.test.js b/components/text-area/src/text-area-field/__tests__/text-area-field.test.js index ae2e85f123..ae461eed29 100644 --- a/components/text-area/src/text-area-field/__tests__/text-area-field.test.js +++ b/components/text-area/src/text-area-field/__tests__/text-area-field.test.js @@ -1,6 +1,6 @@ import { render, fireEvent, screen } from '@testing-library/react' import React from 'react' -import { TextAreaField } from '../text-area-field.js' +import { TextAreaField } from '../text-area-field.tsx' describe('