NumberField: Runaway onChange loop when spam-tapping increment/decrement buttons (iOS)
# NumberField: Runaway onChange loop when spam-tapping increment/decrement buttons (iOS) **Category:** Bug **Severity:** High **Component:** `NumberField` (heroui-native-pro) --- ## Description When using `NumberField` in controlled mode (`value` + `onChange`), rapidly tapping the increment (+) or decrement (-) button on iOS causes `onChange` to fire in an infinite loop. The value runs away to `maxValue` or `minValue` and does not stop even after tapping stops. This is also reproducible in the official **HeroUI Native iOS app**. ## Environment - heroui-native-pro: 1.0.0-beta.4 (also reproduced on beta.3) - heroui-native: ^1.0.3 - expo: ~55.0.26 - react-native: 0.83 - Platform: iOS ## Steps to Reproduce 1. Render a `NumberField` in controlled mode with `value`, `onChange`, `step={50}`, `minValue={0}`, `maxValue={10000}` 2. On iOS, rapidly tap (spam-press) the increment (+) or decrement (-) button 3. Observe the value — it keeps incrementing/decrementing on its own and does not stop ## Expected Behavior Each tap increments/decrements by `step` once. Rapid taps should increment once per tap. The value should stop changing when tapping stops. ## Actual Behavior After rapid taps, `onChange` continues firing in a loop. The value runs away to `maxValue`/`minValue` without stopping. ## Root Cause (from source inspection) Two issues in `useLongPressRepeat`: ### 1. Timer leak on rapid press-in `onPressIn` sets `timerRef.current` to a new `setTimeout` **without clearing the previous one**. During spam-tapping, if two `onPressIn` events fire before `onPressOut` clears them (iOS touch coalescing), the first timeout is leaked — its ref was overwritten, so `clear()` can never cancel it. That orphaned timeout spawns a `setInterval` that runs indefinitely. ```js // useLongPressRepeat.js — current code const onPressIn = useCallback(() => { actionRef.current(); timerRef.current = setTimeout(() => { // ← overwrites without clearing intervalRef.current = setInterval(() => { // ← also overwrites without clearing actionRef.current(); }, interval); }, delay); }, [delay, interval]); ``` ### 2. Stale closure in increment/decrement The `increment`/`decrement` callbacks in `NumberFieldRoot` close over `numberValue` via `useCallback`. When the orphaned interval fires, `actionRef.current` may hold a closure with a stale `numberValue`, causing each tick to re-compute the same step and emit duplicate `onChange` calls. ## Suggested Fix In `useLongPressRepeat`, clear existing timers before starting new ones: ```js const onPressIn = useCallback(() => { if (isDisabledRef.current) return; clear(); // ← clear any existing timer/interval first actionRef.current(); timerRef.current = setTimeout(() => { intervalRef.current = setInterval(() => { actionRef.current(); }, interval); }, delay); }, [delay, interval, clear]); ``` Additionally, consider using a ref for `numberValue` inside `increment`/`decrement` instead of closing over it, so interval ticks always read the latest value. ## Minimal Repro ```tsx import { useCallback, useMemo, useState } from "react"; import { View } from "react-native"; import { Text } from "heroui-native"; import { NumberField } from "heroui-native-pro"; export default function NumberFieldRepro() { const [amount, setAmount] = useState(0); const [changeCount, setChangeCount] = useState(0); const formatOptions = useMemo ( () => ({ style: "currency", currency: "USD", minimumFractionDigits: 0, maximumFractionDigits: 0 }), [], ); const handleChange = useCallback((newValue: number) => { if (isNaN(newValue)) return; console.log(`[NumberField onChange] newValue=${newValue}`); setChangeCount((c) => c + 1); setAmount(newValue); }, []); return ( onChange fired {changeCount} times — spam-tap +/- to reproduce ); } ``` ## Workaround (consumer-side) Guard `onChange` with a tolerance check to suppress duplicate state updates: ```ts const handleChange = useCallback((v: number) => { if (isNaN(v)) return; setAmount(prev => Math.abs(prev - v) < 0.01 ? prev : v); }, []); ```

Stefan Kudla 4 days ago
🐛 Bug Reports
NumberField: Runaway onChange loop when spam-tapping increment/decrement buttons (iOS)
# NumberField: Runaway onChange loop when spam-tapping increment/decrement buttons (iOS) **Category:** Bug **Severity:** High **Component:** `NumberField` (heroui-native-pro) --- ## Description When using `NumberField` in controlled mode (`value` + `onChange`), rapidly tapping the increment (+) or decrement (-) button on iOS causes `onChange` to fire in an infinite loop. The value runs away to `maxValue` or `minValue` and does not stop even after tapping stops. This is also reproducible in the official **HeroUI Native iOS app**. ## Environment - heroui-native-pro: 1.0.0-beta.4 (also reproduced on beta.3) - heroui-native: ^1.0.3 - expo: ~55.0.26 - react-native: 0.83 - Platform: iOS ## Steps to Reproduce 1. Render a `NumberField` in controlled mode with `value`, `onChange`, `step={50}`, `minValue={0}`, `maxValue={10000}` 2. On iOS, rapidly tap (spam-press) the increment (+) or decrement (-) button 3. Observe the value — it keeps incrementing/decrementing on its own and does not stop ## Expected Behavior Each tap increments/decrements by `step` once. Rapid taps should increment once per tap. The value should stop changing when tapping stops. ## Actual Behavior After rapid taps, `onChange` continues firing in a loop. The value runs away to `maxValue`/`minValue` without stopping. ## Root Cause (from source inspection) Two issues in `useLongPressRepeat`: ### 1. Timer leak on rapid press-in `onPressIn` sets `timerRef.current` to a new `setTimeout` **without clearing the previous one**. During spam-tapping, if two `onPressIn` events fire before `onPressOut` clears them (iOS touch coalescing), the first timeout is leaked — its ref was overwritten, so `clear()` can never cancel it. That orphaned timeout spawns a `setInterval` that runs indefinitely. ```js // useLongPressRepeat.js — current code const onPressIn = useCallback(() => { actionRef.current(); timerRef.current = setTimeout(() => { // ← overwrites without clearing intervalRef.current = setInterval(() => { // ← also overwrites without clearing actionRef.current(); }, interval); }, delay); }, [delay, interval]); ``` ### 2. Stale closure in increment/decrement The `increment`/`decrement` callbacks in `NumberFieldRoot` close over `numberValue` via `useCallback`. When the orphaned interval fires, `actionRef.current` may hold a closure with a stale `numberValue`, causing each tick to re-compute the same step and emit duplicate `onChange` calls. ## Suggested Fix In `useLongPressRepeat`, clear existing timers before starting new ones: ```js const onPressIn = useCallback(() => { if (isDisabledRef.current) return; clear(); // ← clear any existing timer/interval first actionRef.current(); timerRef.current = setTimeout(() => { intervalRef.current = setInterval(() => { actionRef.current(); }, interval); }, delay); }, [delay, interval, clear]); ``` Additionally, consider using a ref for `numberValue` inside `increment`/`decrement` instead of closing over it, so interval ticks always read the latest value. ## Minimal Repro ```tsx import { useCallback, useMemo, useState } from "react"; import { View } from "react-native"; import { Text } from "heroui-native"; import { NumberField } from "heroui-native-pro"; export default function NumberFieldRepro() { const [amount, setAmount] = useState(0); const [changeCount, setChangeCount] = useState(0); const formatOptions = useMemo ( () => ({ style: "currency", currency: "USD", minimumFractionDigits: 0, maximumFractionDigits: 0 }), [], ); const handleChange = useCallback((newValue: number) => { if (isNaN(newValue)) return; console.log(`[NumberField onChange] newValue=${newValue}`); setChangeCount((c) => c + 1); setAmount(newValue); }, []); return ( onChange fired {changeCount} times — spam-tap +/- to reproduce ); } ``` ## Workaround (consumer-side) Guard `onChange` with a tolerance check to suppress duplicate state updates: ```ts const handleChange = useCallback((v: number) => { if (isNaN(v)) return; setAmount(prev => Math.abs(prev - v) < 0.01 ? prev : v); }, []); ```

Stefan Kudla 4 days ago
🐛 Bug Reports
The theme sync functionality in the theme builder for heroui pro is not working properly
And the difference between the normal theme builder seen in the heroui docs is that the hero ui theme builder gets every single css variable: /* HeroUI Theme Customization Add this to your global.css after importing @heroui/styles Only includes variables users need to customize @see https://heroui.com/docs/react/getting-started/theming */ :root, .light, .default, [data-theme="light"], [data-theme="default"] { /* Theme Colors (Light Mode) */ --accent: oklch(0 0 0); --accent-foreground: oklch(99.11% 0 0); --background: oklch(97.02% 0.0000 0.00); --border: oklch(90.00% 0.0000 0.00); --danger: oklch(0.573 0.2249 21.97); --danger-foreground: oklch(98% 0.0200 21.97); --default: oklch(94.00% 0.0000 0.00); --default-foreground: oklch(21.03% 0.0059 0.00); --field-background: oklch(100.00% 0.0000 0.00); --field-border: transparent; --field-foreground: oklch(21.03% 0.0000 0.00); --field-placeholder: oklch(55.17% 0.0000 0.00); --focus: oklch(0 0 0); --foreground: oklch(21.03% 0.0000 0.00); --muted: oklch(55.17% 0.0000 0.00); --overlay: oklch(100.00% 0.0000 0.00); --overlay-foreground: oklch(21.03% 0.0000 0.00); --scrollbar: oklch(87.10% 0.0000 0.00); --segment: oklch(100.00% 0.0000 0.00); --segment-foreground: oklch(21.03% 0.0000 0.00); --separator: oklch(92.00% 0.0000 0.00); --success: oklch(0.6277 0.1604 153.06); --success-foreground: oklch(98% 0.0160 153.06); --surface: oklch(100.00% 0.0000 0.00); --surface-foreground: oklch(21.03% 0.0000 0.00); --surface-secondary: oklch(95.24% 0.0000 0.00); --surface-secondary-foreground: oklch(21.03% 0.0000 0.00); --surface-tertiary: oklch(93.73% 0.0000 0.00); --surface-tertiary-foreground: oklch(21.03% 0.0000 0.00); --warning: oklch(0.8446 0.1525 80.6); --warning-foreground: oklch(15% 0.0457 80.60); --accent-soft-foreground: oklch(0 0 0); /* Border Radius */ --radius: 0.25rem; --field-radius: 0.25rem; /* Font Family / / Make sure to load Inter font in your app */ --font-sans: var(--font-inter); } .dark, [data-theme="dark"] { color-scheme: dark; /* Theme Colors (Dark Mode) */ --accent: oklch(0.9848 0 0); --accent-foreground: oklch(15% 0.0000 0.00); --background: oklch(12.00% 0.0000 0.00); --border: oklch(28.00% 0.0000 0.00); --danger: oklch(0.7044 0.1872 23.19); --danger-foreground: oklch(15% 0.0500 23.19); --default: oklch(27.40% 0.0000 0.00); --default-foreground: oklch(99.11% 0 0); --field-background: oklch(21.03% 0.0000 0.00); --field-border: transparent; --field-foreground: oklch(99.11% 0.0000 0.00); --field-placeholder: oklch(70.50% 0.0000 0.00); --focus: oklch(0.9848 0 0); --foreground: oklch(99.11% 0.0000 0.00); --muted: oklch(70.50% 0.0000 0.00); --overlay: oklch(21.03% 0.0000 0.00); --overlay-foreground: oklch(99.11% 0.0000 0.00); --scrollbar: oklch(70.50% 0.0000 0.00); --segment: oklch(39.64% 0.0000 0.00); --segment-foreground: oklch(99.11% 0.0000 0.00); --separator: oklch(25.00% 0.0000 0.00); --success: oklch(0.6514 0.1321 156.22); --success-foreground: oklch(15% 0.0396 156.22); --surface: oklch(21.03% 0.0000 0.00); --surface-foreground: oklch(99.11% 0.0000 0.00); --surface-secondary: oklch(25.70% 0.0000 0.00); --surface-secondary-foreground: oklch(99.11% 0.0000 0.00); --surface-tertiary: oklch(27.21% 0.0000 0.00); --surface-tertiary-foreground: oklch(99.11% 0.0000 0.00); --warning: oklch(0.8803 0.1348 86.06); --warning-foreground: oklch(15% 0.0404 86.06); --accent-soft-foreground: oklch(0.9848 0 0); } This is the pro version: /* HeroUI Pro Theme Add this to your globals.css after importing @heroui/styles @see https://heroui.com/docs/react/getting-started/theming */ /* Font: Inter Load this font in your app: */ @import "@heroui-pro/react/themes/glass"; .glass-light, [data-theme="glass-light"] { /* Theme Colors */ --muted: oklch(55.17% 0.0060 253.83); --scrollbar: oklch(87.10% 0.0030 253.83); --border: oklch(90.00% 0.0030 253.83); --danger-soft-foreground: var(--danger); --warning-soft-foreground: var(--warning); --success-soft-foreground: var(--success); /* Misc */ --skeleton-animation: shimmer; } .glass-dark, [data-theme="glass-dark"] { color-scheme: dark; /* Theme Colors */ --muted: oklch(70.50% 0.0060 253.83); --scrollbar: oklch(70.50% 0.0030 253.83); --surface-secondary-foreground: oklch(25.70% 0.0000 253.83); --surface-tertiary-foreground: oklch(27.21% 0.0000 253.83); --field-placeholder: oklch(70.50% 0.0000 253.83); --segment: oklch(39.64% 0.0030 253.83); --border: oklch(28.00% 0.0030 253.83); --danger-soft-foreground: var(--danger); --warning-soft-foreground: var(--warning); --success-soft-foreground: var(--success); --warning-soft: color-mix(in oklab, var(--warning) 15%, transparent); --warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent); --success-soft: color-mix(in oklab, var(--success) 15%, transparent); --success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent); } Please fix this in order to not to have to work so hard to get the plugin working on the pro theme

Juan Carlos Tremols S 9 days ago
🐛 Bug Reports
The theme sync functionality in the theme builder for heroui pro is not working properly
And the difference between the normal theme builder seen in the heroui docs is that the hero ui theme builder gets every single css variable: /* HeroUI Theme Customization Add this to your global.css after importing @heroui/styles Only includes variables users need to customize @see https://heroui.com/docs/react/getting-started/theming */ :root, .light, .default, [data-theme="light"], [data-theme="default"] { /* Theme Colors (Light Mode) */ --accent: oklch(0 0 0); --accent-foreground: oklch(99.11% 0 0); --background: oklch(97.02% 0.0000 0.00); --border: oklch(90.00% 0.0000 0.00); --danger: oklch(0.573 0.2249 21.97); --danger-foreground: oklch(98% 0.0200 21.97); --default: oklch(94.00% 0.0000 0.00); --default-foreground: oklch(21.03% 0.0059 0.00); --field-background: oklch(100.00% 0.0000 0.00); --field-border: transparent; --field-foreground: oklch(21.03% 0.0000 0.00); --field-placeholder: oklch(55.17% 0.0000 0.00); --focus: oklch(0 0 0); --foreground: oklch(21.03% 0.0000 0.00); --muted: oklch(55.17% 0.0000 0.00); --overlay: oklch(100.00% 0.0000 0.00); --overlay-foreground: oklch(21.03% 0.0000 0.00); --scrollbar: oklch(87.10% 0.0000 0.00); --segment: oklch(100.00% 0.0000 0.00); --segment-foreground: oklch(21.03% 0.0000 0.00); --separator: oklch(92.00% 0.0000 0.00); --success: oklch(0.6277 0.1604 153.06); --success-foreground: oklch(98% 0.0160 153.06); --surface: oklch(100.00% 0.0000 0.00); --surface-foreground: oklch(21.03% 0.0000 0.00); --surface-secondary: oklch(95.24% 0.0000 0.00); --surface-secondary-foreground: oklch(21.03% 0.0000 0.00); --surface-tertiary: oklch(93.73% 0.0000 0.00); --surface-tertiary-foreground: oklch(21.03% 0.0000 0.00); --warning: oklch(0.8446 0.1525 80.6); --warning-foreground: oklch(15% 0.0457 80.60); --accent-soft-foreground: oklch(0 0 0); /* Border Radius */ --radius: 0.25rem; --field-radius: 0.25rem; /* Font Family / / Make sure to load Inter font in your app */ --font-sans: var(--font-inter); } .dark, [data-theme="dark"] { color-scheme: dark; /* Theme Colors (Dark Mode) */ --accent: oklch(0.9848 0 0); --accent-foreground: oklch(15% 0.0000 0.00); --background: oklch(12.00% 0.0000 0.00); --border: oklch(28.00% 0.0000 0.00); --danger: oklch(0.7044 0.1872 23.19); --danger-foreground: oklch(15% 0.0500 23.19); --default: oklch(27.40% 0.0000 0.00); --default-foreground: oklch(99.11% 0 0); --field-background: oklch(21.03% 0.0000 0.00); --field-border: transparent; --field-foreground: oklch(99.11% 0.0000 0.00); --field-placeholder: oklch(70.50% 0.0000 0.00); --focus: oklch(0.9848 0 0); --foreground: oklch(99.11% 0.0000 0.00); --muted: oklch(70.50% 0.0000 0.00); --overlay: oklch(21.03% 0.0000 0.00); --overlay-foreground: oklch(99.11% 0.0000 0.00); --scrollbar: oklch(70.50% 0.0000 0.00); --segment: oklch(39.64% 0.0000 0.00); --segment-foreground: oklch(99.11% 0.0000 0.00); --separator: oklch(25.00% 0.0000 0.00); --success: oklch(0.6514 0.1321 156.22); --success-foreground: oklch(15% 0.0396 156.22); --surface: oklch(21.03% 0.0000 0.00); --surface-foreground: oklch(99.11% 0.0000 0.00); --surface-secondary: oklch(25.70% 0.0000 0.00); --surface-secondary-foreground: oklch(99.11% 0.0000 0.00); --surface-tertiary: oklch(27.21% 0.0000 0.00); --surface-tertiary-foreground: oklch(99.11% 0.0000 0.00); --warning: oklch(0.8803 0.1348 86.06); --warning-foreground: oklch(15% 0.0404 86.06); --accent-soft-foreground: oklch(0.9848 0 0); } This is the pro version: /* HeroUI Pro Theme Add this to your globals.css after importing @heroui/styles @see https://heroui.com/docs/react/getting-started/theming */ /* Font: Inter Load this font in your app: */ @import "@heroui-pro/react/themes/glass"; .glass-light, [data-theme="glass-light"] { /* Theme Colors */ --muted: oklch(55.17% 0.0060 253.83); --scrollbar: oklch(87.10% 0.0030 253.83); --border: oklch(90.00% 0.0030 253.83); --danger-soft-foreground: var(--danger); --warning-soft-foreground: var(--warning); --success-soft-foreground: var(--success); /* Misc */ --skeleton-animation: shimmer; } .glass-dark, [data-theme="glass-dark"] { color-scheme: dark; /* Theme Colors */ --muted: oklch(70.50% 0.0060 253.83); --scrollbar: oklch(70.50% 0.0030 253.83); --surface-secondary-foreground: oklch(25.70% 0.0000 253.83); --surface-tertiary-foreground: oklch(27.21% 0.0000 253.83); --field-placeholder: oklch(70.50% 0.0000 253.83); --segment: oklch(39.64% 0.0030 253.83); --border: oklch(28.00% 0.0030 253.83); --danger-soft-foreground: var(--danger); --warning-soft-foreground: var(--warning); --success-soft-foreground: var(--success); --warning-soft: color-mix(in oklab, var(--warning) 15%, transparent); --warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent); --success-soft: color-mix(in oklab, var(--success) 15%, transparent); --success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent); } Please fix this in order to not to have to work so hard to get the plugin working on the pro theme

Juan Carlos Tremols S 9 days ago
🐛 Bug Reports
Notification center
It would be great to have a notification center component. Similar to ones you see right here on the feedback page when you click on the Bell icon button
Vinod Kumar 11 days ago
💡 Feature Request
Notification center
It would be great to have a notification center component. Similar to ones you see right here on the feedback page when you click on the Bell icon button
Vinod Kumar 11 days ago
💡 Feature Request
Searchable Select
I’d like to be able to have a search bar inside of a Select component See GitHub issue: https://github.com/heroui-inc/heroui/discussions/5656

Ben King 18 days ago
📝 Components Request
Searchable Select
I’d like to be able to have a search bar inside of a Select component See GitHub issue: https://github.com/heroui-inc/heroui/discussions/5656

Ben King 18 days ago
📝 Components Request
In Progress
Error with multiple DataGrid on a page
The DataGrid work fine if there’s only 1 on a page. A second DataGrid causes the following error. I’ve tried both grids independently, and extracted to a common component. Tried both beta 2 and 3. error-boundary-callbacks.ts:90 Error: A table must have at least one Column with the isRowHeader prop set to true at $76d00c5a4edb230a$var$TableCollection.updateColumns (Table.tsx:174:13) at $76d00c5a4edb230a$var$TableCollection.commit (Table.tsx:117:10) at $96ead35620b8fd36$export$b34a105447964f9f.updateCollection (Document.ts:521:27) at $96ead35620b8fd36$export$b34a105447964f9f.getCollection (Document.ts:487:10) at CollectionBuilder.tsx:102:31 at updateSyncExternalStore (react-dom-client.development.js:8499:31) at Object.useSyncExternalStore (react-dom-client.development.js:28671:16) at exports.useSyncExternalStore (react.development.js:1316:34) at $42ceafc619f9c3ba$var$useCollectionDocument (CollectionBuilder.tsx:115:20) at $42ceafc619f9c3ba$export$bf788dd355e3a401 (CollectionBuilder.tsx:53:32) at Object.react_stack_bottom_frame (react-dom-client.development.js:28038:20) at renderWithHooks (react-dom-client.development.js:7984:22) at updateFunctionComponent (react-dom-client.development.js:10501:19) at beginWork (react-dom-client.development.js:12136:18) at runWithFiberInDEV (react-dom-client.development.js:986:30) at performUnitOfWork (react-dom-client.development.js:18997:22) at workLoopSync (react-dom-client.development.js:18825:41) at renderRootSync (react-dom-client.development.js:18806:11) at performWorkOnRoot (react-dom-client.development.js:17914:35) at performSyncWorkOnRoot (react-dom-client.development.js:20399:7) at flushSyncWorkAcrossRoots_impl (react-dom-client.development.js:20241:21) at flushSpawnedWork (react-dom-client.development.js:19752:9) at commitRoot (react-dom-client.development.js:19335:60) at commitRootWhenReady (react-dom-client.development.js:18178:7) at performWorkOnRoot (react-dom-client.development.js:18054:15) at performWorkOnRootViaSchedulerTask (react-dom-client.development.js:20384:7) at MessagePort.performWorkUntilDeadline (scheduler.development.js:45:48) The above error occurred in the component. It was handled by the error boundary. 'use client'; import { DataGrid, EmptyState } from '@heroui-pro/react'; import { SortableLibraryItem } from './sorting'; interface ItemTableProps { title?: string; items: (SortableLibraryItem & { _id: string })[]; tableKey: string; } export function ItemTable({ title, items, tableKey }: ItemTableProps) { return ( ( {title} Title / Key ), minWidth: 200, // accessorKey: 'title', cell: (item) => ( {item.title} {item.key} ), }, { id: 'type', headerClassName: 'content-end align-end', header: 'Type', accessorKey: 'subType', // minWidth: 120, maxWidth: 200, }, { id: 'storyDate', header: 'Story Date', headerClassName: 'content-end align-end', // minWidth: 120, maxWidth: 200, cell: (item) => ( {item.position?.startDate} ), }, { id: 'publicationDate', headerClassName: 'content-end align-end', header: 'Publication Date', accessorKey: 'publishedDate', // minWidth: 120, maxWidth: 200, }, ]} contentClassName="w-full" data={items} getRowId={(item) => item.id} renderEmptyState={() => ( Nothing to see here. )} selectionMode="none" variant="primary" /> ); } npm ls | grep heroui ├── @heroui-pro/react@1.0.0-beta.3 ├── @heroui/react@3.0.3 ├── @heroui/styles@3.0.3

chilltemp 28 days ago
🐛 Bug Reports
In Progress
Error with multiple DataGrid on a page
The DataGrid work fine if there’s only 1 on a page. A second DataGrid causes the following error. I’ve tried both grids independently, and extracted to a common component. Tried both beta 2 and 3. error-boundary-callbacks.ts:90 Error: A table must have at least one Column with the isRowHeader prop set to true at $76d00c5a4edb230a$var$TableCollection.updateColumns (Table.tsx:174:13) at $76d00c5a4edb230a$var$TableCollection.commit (Table.tsx:117:10) at $96ead35620b8fd36$export$b34a105447964f9f.updateCollection (Document.ts:521:27) at $96ead35620b8fd36$export$b34a105447964f9f.getCollection (Document.ts:487:10) at CollectionBuilder.tsx:102:31 at updateSyncExternalStore (react-dom-client.development.js:8499:31) at Object.useSyncExternalStore (react-dom-client.development.js:28671:16) at exports.useSyncExternalStore (react.development.js:1316:34) at $42ceafc619f9c3ba$var$useCollectionDocument (CollectionBuilder.tsx:115:20) at $42ceafc619f9c3ba$export$bf788dd355e3a401 (CollectionBuilder.tsx:53:32) at Object.react_stack_bottom_frame (react-dom-client.development.js:28038:20) at renderWithHooks (react-dom-client.development.js:7984:22) at updateFunctionComponent (react-dom-client.development.js:10501:19) at beginWork (react-dom-client.development.js:12136:18) at runWithFiberInDEV (react-dom-client.development.js:986:30) at performUnitOfWork (react-dom-client.development.js:18997:22) at workLoopSync (react-dom-client.development.js:18825:41) at renderRootSync (react-dom-client.development.js:18806:11) at performWorkOnRoot (react-dom-client.development.js:17914:35) at performSyncWorkOnRoot (react-dom-client.development.js:20399:7) at flushSyncWorkAcrossRoots_impl (react-dom-client.development.js:20241:21) at flushSpawnedWork (react-dom-client.development.js:19752:9) at commitRoot (react-dom-client.development.js:19335:60) at commitRootWhenReady (react-dom-client.development.js:18178:7) at performWorkOnRoot (react-dom-client.development.js:18054:15) at performWorkOnRootViaSchedulerTask (react-dom-client.development.js:20384:7) at MessagePort.performWorkUntilDeadline (scheduler.development.js:45:48) The above error occurred in the component. It was handled by the error boundary. 'use client'; import { DataGrid, EmptyState } from '@heroui-pro/react'; import { SortableLibraryItem } from './sorting'; interface ItemTableProps { title?: string; items: (SortableLibraryItem & { _id: string })[]; tableKey: string; } export function ItemTable({ title, items, tableKey }: ItemTableProps) { return ( ( {title} Title / Key ), minWidth: 200, // accessorKey: 'title', cell: (item) => ( {item.title} {item.key} ), }, { id: 'type', headerClassName: 'content-end align-end', header: 'Type', accessorKey: 'subType', // minWidth: 120, maxWidth: 200, }, { id: 'storyDate', header: 'Story Date', headerClassName: 'content-end align-end', // minWidth: 120, maxWidth: 200, cell: (item) => ( {item.position?.startDate} ), }, { id: 'publicationDate', headerClassName: 'content-end align-end', header: 'Publication Date', accessorKey: 'publishedDate', // minWidth: 120, maxWidth: 200, }, ]} contentClassName="w-full" data={items} getRowId={(item) => item.id} renderEmptyState={() => ( Nothing to see here. )} selectionMode="none" variant="primary" /> ); } npm ls | grep heroui ├── @heroui-pro/react@1.0.0-beta.3 ├── @heroui/react@3.0.3 ├── @heroui/styles@3.0.3

chilltemp 28 days ago
🐛 Bug Reports
Add native sticky header support to DataGrid without requiring virtualization
Currently, HeroUI Pro DataGrid appears to support sticky headers mainly through the virtualized mode, using rowHeight and headingHeight. That works visually, but it forces the table into fixed row heights and virtualization even when the only requirement is keeping the column header visible during vertical scrolling. It would be useful to have a native prop such as: or: This would allow the regular DataGrid to keep dynamic row heights, selection, horizontal scrolling, pagination, and normal table behavior while keeping the header fixed inside the scroll container.

Kayo Cordeiro 30 days ago
💡 Feature Request
Add native sticky header support to DataGrid without requiring virtualization
Currently, HeroUI Pro DataGrid appears to support sticky headers mainly through the virtualized mode, using rowHeight and headingHeight. That works visually, but it forces the table into fixed row heights and virtualization even when the only requirement is keeping the column header visible during vertical scrolling. It would be useful to have a native prop such as: or: This would allow the regular DataGrid to keep dynamic row heights, selection, horizontal scrolling, pagination, and normal table behavior while keeping the header fixed inside the scroll container.

Kayo Cordeiro 30 days ago
💡 Feature Request
beta 2 import bugs
After update to beta 2, it always show this error on all heroui-native-pro imports no matter which component is imported [TypeError: Cannot read property 'Bar' of undefined] It never occurs in beta 1, maybe problems with Bar Chart exports. Please fix that, Thank you.

Ajkbxcd Bdcadcb about 1 month ago
🐛 Bug Reports
beta 2 import bugs
After update to beta 2, it always show this error on all heroui-native-pro imports no matter which component is imported [TypeError: Cannot read property 'Bar' of undefined] It never occurs in beta 1, maybe problems with Bar Chart exports. Please fix that, Thank you.

Ajkbxcd Bdcadcb about 1 month ago
🐛 Bug Reports
SwipeList
A SwipeList component would be really useful (for Native Pro) please. NativeBase has one, and I can build one in RN, but would prefer a HeroUI Native version.

Picpoul about 1 month ago
📝 Components Request
SwipeList
A SwipeList component would be really useful (for Native Pro) please. NativeBase has one, and I can build one in RN, but would prefer a HeroUI Native version.

Picpoul about 1 month ago
📝 Components Request