Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changesets

This directory was generated to track release notes and versioning.
Run `npm run changeset` to add a new changeset when you modify public APIs.
8 changes: 8 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"linked": [],
"access": "public",
"baseBranch": "main"
}
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run check:exports
npm test

npm run lint:staged
22 changes: 20 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
"name": "@radui/ui",
"version": "0.0.47",
"description": "",
"main": "dist",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
"./themes/default.css": "./dist/themes/default.css",
"./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
},
Comment on lines +10 to 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Fix broken exports JSON (missing brace/comma) — causes npm ci parse error.

The "." export object isn’t closed before the next keys, breaking JSON (see pipeline errors). Close the object and add a comma.

   "exports": {
-    ".": {
-      "import": "./dist/index.js",
-      "require": "./dist/index.cjs",
-      "types": "./dist/index.d.ts"
-    "./themes/default.css": "./dist/themes/default.css",
-    "./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
-  },
+    ".": {
+      "import": "./dist/index.js",
+      "require": "./dist/index.cjs",
+      "types": "./dist/index.d.ts"
+    },
+    "./themes/default.css": "./dist/themes/default.css",
+    "./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
+  },

Quick check script:


🏁 Script executed:

#!/bin/bash
python - <<'PY'
import json,sys
json.load(open("package.json"))
print("package.json parses OK")
PY

Length of output: 738


Fix broken exports JSON in package.json (missing brace/comma)

Close the "." export object and add a comma before the following export entries — package.json fails to parse (json.decoder.JSONDecodeError at line 14 column 5).

   "exports": {
-    ".": {
-      "import": "./dist/index.js",
-      "require": "./dist/index.cjs",
-      "types": "./dist/index.d.ts"
-    "./themes/default.css": "./dist/themes/default.css",
-    "./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
-  },
+    ".": {
+      "import": "./dist/index.js",
+      "require": "./dist/index.cjs",
+      "types": "./dist/index.d.ts"
+    },
+    "./themes/default.css": "./dist/themes/default.css",
+    "./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
+  },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
"./themes/default.css": "./dist/themes/default.css",
"./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
},
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./themes/default.css": "./dist/themes/default.css",
"./themes/tailwind-presets/default.js": "./dist/themes/tailwind-presets/default.js"
},
🧰 Tools
🪛 Biome (2.1.2)

[error] 14-14: expected , but instead found "./themes/default.css"

Remove "./themes/default.css"

(parse)

🤖 Prompt for AI Agents
In package.json around lines 10 to 16, the exports map for "." is missing a
closing brace and a separating comma which breaks JSON parsing; close the "."
object's block with a }, then add a comma after that closing brace before the
next export entries (./themes/default.css and
./themes/tailwind-presets/default.js) so the exports object is properly
separated and the JSON is valid.

Expand All @@ -27,6 +33,7 @@
"process-components": "node scripts/process-components.cjs",
"prebuild": "npm run test && npm run clean",
"build:generate-exports": "node scripts/generate-exports.cjs",
"check:exports": "node scripts/generate-exports.cjs --check",
"build:css": "npm run generate-tokens && npm run bundle-tokens && npm run build-css",
"build:components": "npm run compile-components && npm run process-components",
"build:rollup": "NODE_OPTIONS='--max-old-space-size=8192' npm run build:rollup:process",
Expand All @@ -35,13 +42,21 @@
"check:types": "tsc --noEmit",
"build-components:esbuild": "npm run compile-components:esbuild && npm run process-components",
"build:esbuild": "npm run prebuild && npm run build:css && npm run build-components:esbuild",
"release": "npm publish --access public",
"release": "npm run build:generate-exports && changeset publish",
"changeset": "changeset",
"version-packages": "changeset version",
"size": "size-limit",
Comment on lines +45 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Release flow can publish unbuilt artifacts and skip versioning/size checks.

  • changeset publish won’t build by itself; wire build+size checks via prepack.
  • Include versioning before publish, letting prepack run on npm publish automatically.

Apply:

-    "release": "npm run build:generate-exports && changeset publish",
+    "release": "npm run version-packages && changeset publish",

Add (outside this hunk):

{
  "scripts": {
    "prepack": "npm run build:rollup:process && npm run size && npm test"
  }
}

This ensures the package is built, budget-checked, and tested during publish.

🤖 Prompt for AI Agents
In package.json around lines 44 to 47, the current release flow runs changeset
publish directly which can publish unbuilt artifacts and skip versioning/size
checks; add a "prepack" script at top-level scripts that runs the build, size
check and tests (e.g. run the rollup build, npm run size, and npm test) so npm
publish will automatically build and validate, and update the release flow to
run changeset version before publish (or ensure the release script invokes the
versioning step prior to changeset publish) so packages are versioned before
publishing.

"lint": "eslint --ext .js,.jsx,.ts,.tsx . --fix && stylelint \"**/*.{css,scss,sass}\" --fix",
"lint:staged": "lint-staged",
"update-rad": "npm update @radui/ui",
"setup:dependencies": "npm install --force",
"setup": "npm run setup:dependencies"
},
"size-limit": [
{
"path": "dist/components/*.js"
}
],
Comment on lines +55 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

size-limit config lacks required "limit" and will fail.

Add a budget; otherwise npm run size errors with a missing/invalid limit.

Apply:

   "size-limit": [
     {
-      "path": "dist/components/*.js"
+      "path": "dist/components/*.js",
+      "limit": "30 KB"
     }
   ],

If you prefer per-entry budgets, split by component or add a second entry for the root bundle (e.g., dist/index.js).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"size-limit": [
{
"path": "dist/components/*.js"
}
],
"size-limit": [
{
"path": "dist/components/*.js",
"limit": "30 KB"
}
],
🤖 Prompt for AI Agents
In package.json around lines 54 to 58, the size-limit entry for
"dist/components/*.js" is missing the required "limit" field and will cause `npm
run size` to fail; add a "limit" property (e.g., "10 KB" or an appropriate
byte/KB/MB value) to that object, or replace the single glob with multiple
entries each containing a "path" and "limit" (for per-component budgets) and/or
add an additional entry for the root bundle (e.g., "dist/index.js" with its own
"limit").

"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix"
Expand Down Expand Up @@ -87,6 +102,8 @@
"@types/jest": "^29.5.14",
"@types/react": "^18.3.1",
"@typescript-eslint/eslint-plugin": "7.0.0",
"@changesets/cli": "^2.27.1",
"@size-limit/preset-small-lib": "^11.1.2",
"autoprefixer": "10.4.15",
"axe-core": "^4.10.2",
"babel-plugin-module-resolver": "5.0.2",
Expand All @@ -112,6 +129,7 @@
"rollup-plugin-postcss": "^4.0.2",
"sass": "^1.77.2",
"sass-loader": "16.0.4",
"size-limit": "^11.1.2",
"storybook": "^8.6.11",
"stylelint": "^16.12.0",
"stylelint-config-standard": "^36.0.1",
Expand Down
26 changes: 23 additions & 3 deletions scripts/generate-exports.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
const fs = require('fs');
const path = require('path');
const RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
const isCheck = process.argv.includes('--check');
Comment on lines 42 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Guard missing RELEASED_COMPONENTS to avoid hard crashes.

-const RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
+let RELEASED_COMPONENTS = [];
+try {
+  RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
+} catch (e) {
+  console.warn('Warning: RELEASED_COMPONENTS.cjs not found; treating all discovered components as unreleased.');
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
const isCheck = process.argv.includes('--check');
let RELEASED_COMPONENTS = [];
try {
RELEASED_COMPONENTS = require('./RELEASED_COMPONENTS.cjs');
} catch (e) {
console.warn('Warning: RELEASED_COMPONENTS.cjs not found; treating all discovered components as unreleased.');
}
const isCheck = process.argv.includes('--check');
🤖 Prompt for AI Agents
In scripts/generate-exports.cjs around lines 42-43, the direct
require('./RELEASED_COMPONENTS.cjs') can crash if the file is missing; wrap the
require in a try/catch (or check fs.existsSync first), on failure set
RELEASED_COMPONENTS to a safe default (e.g., an empty array/object as expected
by the rest of the script) and emit a clear console.warn or error message; do
not let the exception propagate and crash the process.


// Component exports
const distPath = path.resolve(__dirname, '../dist/components');
Expand All @@ -53,6 +54,13 @@ try {

const exportsMap = {};

// Root export
exportsMap['.'] = {
import: './dist/index.js',
require: './dist/index.cjs',
types: './dist/index.d.ts'
};

// Add theme exports
exportsMap['./themes/default.css'] = './dist/themes/default.css';
exportsMap['./themes/tailwind-presets/default.js'] = './dist/themes/tailwind-presets/default.js';
Expand All @@ -72,6 +80,7 @@ files.forEach(file => {

exportsMap[`./${name}`] = {
import: `./dist/components/${name}.js`,
require: `./dist/components/${name}.cjs`,
types: `./dist/components/${name}.d.ts`
};
}
Expand All @@ -85,9 +94,20 @@ const pkgPath = path.resolve(__dirname, '../package.json');

try {
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
pkg.exports = exportsMap;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
console.log('✅ package.json exports updated!');

if (isCheck) {
const current = JSON.stringify(pkg.exports, null, 2);
const expected = JSON.stringify(exportsMap, null, 2);
if (current !== expected) {
console.error('❌ package.json exports are out of date. Run npm run build:generate-exports to update.');
process.exit(1);
}
console.log('✅ package.json exports are up to date.');
} else {
Comment on lines +98 to +106
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid brittle string-equality; compare semantically and allow extra custom exports.

Exact JSON string compare fails on key order and blocks legitimate extra entries like "./package.json".

-    if (isCheck) {
-        const current = JSON.stringify(pkg.exports, null, 2);
-        const expected = JSON.stringify(exportsMap, null, 2);
-        if (current !== expected) {
-            console.error('❌ package.json exports are out of date. Run npm run build:generate-exports to update.');
-            process.exit(1);
-        }
-        console.log('✅ package.json exports are up to date.');
-    } else {
+    if (isCheck) {
+        const deepEqual = (a, b) => {
+          if (a === b) return true;
+          if (typeof a !== typeof b) return false;
+          if (Array.isArray(a)) return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
+          if (a && typeof a === 'object') {
+            const ak = Object.keys(a);
+            const bk = Object.keys(b);
+            if (ak.length !== bk.length) return false;
+            return ak.every(k => deepEqual(a[k], b[k]));
+          }
+          return false;
+        };
+        const current = pkg.exports || {};
+        const expected = exportsMap;
+        const mismatches = [];
+        for (const k of Object.keys(expected)) {
+          if (!deepEqual(current[k], expected[k])) mismatches.push(k);
+        }
+        if (mismatches.length) {
+          console.error(`❌ package.json exports are out of date for keys: ${mismatches.join(', ')}. Run npm run build:generate-exports to update.`);
+          process.exit(1);
+        }
+        console.log('✅ package.json exports are up to date.');
+    } else {
         pkg.exports = exportsMap;
         fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
         console.log('✅ package.json exports updated!');
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (isCheck) {
const current = JSON.stringify(pkg.exports, null, 2);
const expected = JSON.stringify(exportsMap, null, 2);
if (current !== expected) {
console.error('❌ package.json exports are out of date. Run npm run build:generate-exports to update.');
process.exit(1);
}
console.log('✅ package.json exports are up to date.');
} else {
if (isCheck) {
const deepEqual = (a, b) => {
if (a === b) return true;
if (typeof a !== typeof b) return false;
if (Array.isArray(a)) return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
if (a && typeof a === 'object') {
const ak = Object.keys(a);
const bk = Object.keys(b);
if (ak.length !== bk.length) return false;
return ak.every(k => deepEqual(a[k], b[k]));
}
return false;
};
const current = pkg.exports || {};
const expected = exportsMap;
const mismatches = [];
for (const k of Object.keys(expected)) {
if (!deepEqual(current[k], expected[k])) mismatches.push(k);
}
if (mismatches.length) {
console.error(`❌ package.json exports are out of date for keys: ${mismatches.join(', ')}. Run npm run build:generate-exports to update.`);
process.exit(1);
}
console.log('✅ package.json exports are up to date.');
} else {
🤖 Prompt for AI Agents
scripts/generate-exports.cjs around lines 98 to 106: the current check uses
JSON.stringify equality which is brittle (key order) and rejects valid extra
exports; replace the string-equality with a semantic comparison that ensures
every key in exportsMap exists in package.json exports and that their values
deeply equal, while allowing additional keys (e.g., "./package.json") in
pkg.exports; on mismatch, print a clear message listing missing/mismatched keys
and exit non-zero, otherwise report up-to-date.

pkg.exports = exportsMap;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
console.log('✅ package.json exports updated!');
}
} catch (error) {
console.error('❌ Failed to update package.json exports:', error.message);
process.exit(1);
Expand Down
Loading