Skip to content
Draft
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
38 changes: 38 additions & 0 deletions .changeset/lucide-react-1-43-0-retired-trash2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
'@object-ui/plugin-detail': patch
'@object-ui/components': patch
'@object-ui/types': patch
'@object-ui/cli': patch
---

Move `lucide-react` from `^1.31.0` to `^1.43.0` and repair the one spelling the jump
retires, so the delete affordances that resolve their icon from a STRING keep drawing a
glyph.

Measured against the installed artifact rather than the upstream changelog. Across the
whole 1.31.0 to 1.43.0 jump lucide removes **zero** public names — 6072 to 6230 names in
`lucide-react`'s type surface with none dropped, 6068 to 6224 runtime exports with none
dropped, and nothing at all removed from `lucide-react/dynamic.mjs`. Every one of the 333
value names and the one type name this repository imports resolves in both versions
(controls: `Trash` resolves in both, a bogus name resolves in neither). So no import
breaks and no type breaks.

Exactly one key leaves the runtime `icons` record: `Trash2`. lucide retired it in favour
of `trash`, and it survives as a DEPRECATED EXPORT of the same object — which is why
nothing goes red on the compiler or on a component render, and only STRING lookups
through `renderers/action/resolve-icon.ts` are affected, because those read record
MEMBERSHIP. Repaired at all four sites that reach that resolver, three schema-catalog
documents and `DetailView`'s system delete action.

What a user sees change:

- `DetailView`'s delete action (`icon: 'trash-2'` to `'trash'`) draws its icon again
instead of a label with nothing beside it. The glyph is unchanged: lucide 1.43.0's
`trash` icon node is byte-identical to 1.31.0's `trash-2` icon node.
- Icons that lucide has since renamed now carry an extra class per retired alias — a
spinner renders `class="lucide lucide-loader-circle lucide-loader-2 ..."`. This is
additive (248 of 1818 icon modules carry an alias), so a `.lucide-loader-circle`
selector still matches; a selector asserting the exact, complete class string does not.
- The workspace stops installing two copies of the icon library. `main` resolves
`lucide-react` twice — 1.31.0 for this workspace and 1.35.0 for `fumadocs-ui` — and
both collapse onto 1.43.0 here.
2 changes: 1 addition & 1 deletion apps/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"@vitest/ui": "^4.1.10",
"autoprefixer": "^10.5.4",
"happy-dom": "^20.11.2",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"postcss": "^8.5.26",
"react": "19.2.8",
"react-dom": "19.2.8",
Expand Down
2 changes: 1 addition & 1 deletion apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"fumadocs-core": "16.15.4",
"fumadocs-mdx": "15.2.3",
"fumadocs-ui": "16.15.4",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"next": "16.3.3",
"react": "19.2.8",
"react-dom": "19.2.8",
Expand Down
2 changes: 1 addition & 1 deletion content/docs/api/schema-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ A single-record detail view with grouped fields, actions, and tabs.
],
"actions": [
{ "type": "action", "label": "Edit", "icon": "Pencil", "level": "primary" },
{ "type": "action", "label": "Delete", "icon": "Trash2", "level": "danger", "actionType": "confirm" }
{ "type": "action", "label": "Delete", "icon": "trash", "level": "danger", "actionType": "confirm" }
],
"tabs": [
{
Expand Down
2 changes: 1 addition & 1 deletion content/docs/guide/schema-playground.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ A data grid with sortable columns and row actions:
],
"actions": [
{ "label": "Edit", "icon": "pencil", "action": "edit" },
{ "label": "Delete", "icon": "trash-2", "action": "delete", "variant": "destructive" }
{ "label": "Delete", "icon": "trash", "action": "delete", "variant": "destructive" }
],
"pagination": {
"pageSize": 10,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"type": "button",
"label": "Delete",
"variant": "destructive",
"icon": "trash-2"
"icon": "trash"
},
{
"type": "button",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"type": "button",
"label": "Yes, Delete",
"variant": "destructive",
"icon": "trash-2"
"icon": "trash"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"label": "Delete",
"variant": "destructive",
"size": "sm",
"icon": "trash-2"
"icon": "trash"
}
]
}
Expand Down
14 changes: 12 additions & 2 deletions examples/schema-catalog/test/svg-host-dom-leak-5632.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,23 @@ describe('schema-catalog — no SVG-hosted renderer leaks an authored prop to th
// `SpinnerSchema.size` is an ENUM consumed through `sizeClasses`. Spreading
// it handed the string to lucide's numeric `size` prop, which is how
// `width="lg" height="lg"` reached every sized spinner in the catalog.
// `class` carries lucide's own two classes AND both of this renderer's —
// `class` carries lucide's own classes AND both of this renderer's —
// `animate-spin` and the size class. Before this slice it carried ONLY
// lucide's: the spread's `className` overrode the computed one, so a
// `ui:spinner` rendered through `SchemaRenderer` did not spin.
//
// `lucide-loader-2` is lucide's own RETIRED-ALIAS class, not a leak. It
// appeared when `createLucideIcon` was reshaped to take an icon-data object
// carrying `aliases` (lucide-react 1.43.0; absent in 1.31.0, where icon
// modules have no `aliases` field at all) and it now emits one class per
// alias. Measured on the installed artifact: 248 of 1818 icon modules carry
// aliases, so any icon with one gains a class here. The assertion stays
// EXACT on purpose — this list is what catches an authored prop reaching
// the DOM, which is the whole point of objectui#5632; loosening it to a
// substring match would retire the check rather than update it.
expect(attributesOf({ type: 'spinner', size: 'lg' })).toEqual([
'aria-hidden="true"',
'class="lucide lucide-loader-circle animate-spin h-8 w-8"',
'class="lucide lucide-loader-circle lucide-loader-2 animate-spin h-8 w-8"',
'data-obj-type="spinner"',
'fill="none"',
'height="24"',
Expand Down
2 changes: 1 addition & 1 deletion packages/app-shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"@objectstack/spec": "^17.0.0",
"@sentry/react": "^10.70.0",
"jsonc-parser": "^3.3.1",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"qrcode": "^1.5.4",
"sonner": "^2.0.8",
"zod": "^4.4.3"
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/utils/app-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ function buildRoutedAppDependencies(): Record<string, string> {
react: REACT_RANGE,
'react-dom': REACT_RANGE,
'react-router-dom': '^7.18.2',
'lucide-react': '^1.31.0',
'lucide-react': '^1.43.0',
...Object.fromEntries(PLATFORM_RUNTIME_PACKAGES.map((name) => [name, range]))
};
}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"date-fns": "^4.4.0",
"embla-carousel-react": "^8.6.0",
"input-otp": "^1.4.2",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"next-themes": "^0.4.6",
"react-day-picker": "^10.0.1",
"react-hook-form": "^7.85.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/renderers/action/action-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* location: 'record_header',
* actions: [
* { name: 'mark_complete', label: 'Mark Complete', type: 'script', icon: 'check', component: 'action:button' },
* { name: 'delete', label: 'Delete', type: 'api', icon: 'trash-2', variant: 'destructive', component: 'action:button' },
* { name: 'delete', label: 'Delete', type: 'api', icon: 'trash', variant: 'destructive', component: 'action:button' },
* ],
* }} />
* ```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,21 @@ describe('ui:button icon resolution (objectui#5993)', () => {
// The single entry both maps carried. It is the one input whose answer
// would have changed had the dedupe dropped the alias on the floor.
const button = renderButton({ icon: 'home' });
expect(button.querySelector('svg.lucide-house')).not.toBeNull();
expect(button.querySelector('svg.lucide-home')).toBeNull();
const house = button.querySelector('svg.lucide-house');
expect(house).not.toBeNull();
// The negative half used to read `querySelector('svg.lucide-home')` is
// null. That form RETIRED on lucide-react 1.43.0, which reshaped
// `createLucideIcon` to take an icon-data object carrying `aliases` and
// to emit one class PER ALIAS: `house` now renders
// `class="lucide lucide-house lucide-home ..."` itself, so the class no
// longer says which glyph was drawn (measured: 248 of 1818 icon modules
// carry aliases; 1.31.0 icon modules have no `aliases` field at all).
// The discriminating form is below and still fires for the same defect:
// `Home` is not a key of the runtime record, so had the rename been
// dropped this button would render NO glyph at all, and any SECOND glyph
// would be a different element from `house`.
expect(button.querySelectorAll('svg')).toHaveLength(1);
expect(button.querySelector('svg.lucide-home')).toBe(house);
});

it('renders NO glyph for a retired spelling — the RECORD surface, not a fallback', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/fields/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"react-markdown": "^10.1.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^4.0.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/layout/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"react": "19.2.8"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@object-ui/components": "workspace:*",
"@object-ui/core": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"devDependencies": {
"@types/node": "^26.2.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-calendar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@object-ui/plugin-detail": "workspace:*",
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@object-ui/i18n": "workspace:*",
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"recharts": "^3.10.1"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-chatbot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@radix-ui/react-use-controllable-state": "^1.2.6",
"ai": "^7.0.65",
"class-variance-authority": "^0.7.1",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"motion": "^13.2.0",
"nanoid": "^6.0.1",
"shiki": "^4.4.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@object-ui/permissions": "workspace:*",
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"react": "19.2.8"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-designer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"clsx": "^2.1.1",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"sonner": "^2.0.8",
"tailwind-merge": "^3.6.0"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-detail/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"@object-ui/i18n": "workspace:*",
"@objectstack/spec": "^17.1.0",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"@object-ui/components": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-detail/src/DetailView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
items.push({
name: 'sys_delete',
label: t('detail.delete'),
icon: 'trash-2',
icon: 'trash',
type: 'script',
variant: 'destructive',
tags: ['separator-before'],
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-form/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-gantt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"sonner": "^2.0.8"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-grid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@objectstack/spec": "^17.0.0",
"@tanstack/react-virtual": "^3.14.9",
"exceljs": "^4.4.0",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-kanban/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@tanstack/react-virtual": "^3.14.9",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-list/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"lint": "eslint ."
},
"dependencies": {
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"@object-ui/components": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-report/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@object-ui/i18n": "workspace:*",
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-tree/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-view/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^17.0.0",
"class-variance-authority": "^0.7.1",
"lucide-react": "^1.31.0"
"lucide-react": "^1.43.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@object-ui/plugin-kanban": "workspace:*",
"@object-ui/react": "workspace:*",
"@object-ui/types": "workspace:*",
"lucide-react": "^1.31.0",
"lucide-react": "^1.43.0",
"react": "19.2.8",
"react-dom": "19.2.8",
"tailwindcss-animate": "^1.0.7"
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/objectql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export interface BulkActionDef {
name: string;
/** Human-readable label shown on the button + dialog header. */
label?: string;
/** Lucide icon name (e.g. 'user-check', 'trash-2'); falls back to a generic icon. */
/** Lucide icon name (e.g. 'user-check', 'trash'); falls back to a generic icon. */
icon?: string;
/** Visual treatment of the action button. */
variant?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'outline';
Expand Down
Loading
Loading