diff --git a/.changeset/fix-collection-item-types.md b/.changeset/fix-collection-item-types.md new file mode 100644 index 000000000..8327105d5 --- /dev/null +++ b/.changeset/fix-collection-item-types.md @@ -0,0 +1,5 @@ +--- +'@cube-dev/ui-kit': patch +--- + +Fix the types of `FilterListBox.Item` and `CommandMenu.Item`. Both were declared as React Stately's bare `Item`, so `Item` props such as `icon`, `rightIcon`, `description`, `hotkeys` and `actions` were rejected by TypeScript even though they worked at runtime. They now use `CollectionItem`, matching `ListBox.Item`, `Menu.Item` and the other collection components. diff --git a/AGENTS.md b/AGENTS.md index ab7e38178..cca30c8f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,6 +10,22 @@ Entry point for AI agents working on `@cube-dev/ui-kit`. > **Maintenance note:** The design-system reference (tokens, presets, colors, modifiers, state syntax, form system, icons) lives in `src/stories/Usage.docs.mdx` (Storybook → **Getting Started / Usage**). The component creation guide lives in `src/stories/CreateComponent.docs.mdx` (**Getting Started / Create Component**). Update these whenever you add components, change the API surface, or modify tokens/presets. +## Before You Start + +**Run this at the start of every task, before reading code, running tests, or trusting any type error:** + +```bash +pnpm install && pnpm rebuild esbuild +``` + +A working copy can sit idle across dependency bumps, so `node_modules` may not match `pnpm-lock.yaml`. A stale tree does not fail loudly — it silently inverts results. Tests pass locally and fail on CI (or the reverse), and `tsc` reports errors that do not exist on the pinned version. Anything you conclude from a stale tree is unreliable, including the conclusion that a failure is "pre-existing". + +When local results and CI disagree, suspect the dependency tree first. Compare the installed version against the lockfile before theorising about anything else: + +```bash +pnpm list @tenphi/tasty @tenphi/glaze +``` + ## Rules Project-specific working rules for AI agents. Not published with the package. @@ -65,7 +81,7 @@ Each component lives in `src/components/{category}/{ComponentName}/` and ships ` ## Environment - Node `>=22.0.0`, pnpm `^10` (pinned to `pnpm@10.32.0`). The publish workflow (`publish.yml`) still runs on Node 24 because OIDC trusted publishing requires npm ≥ 11.5.1+, which Node 24 ships natively (Node 22 ships npm 10.x). -- After `pnpm install`, run `pnpm rebuild esbuild` (postinstall is blocked in `pnpm-workspace.yaml`). +- After `pnpm install`, run `pnpm rebuild esbuild` (postinstall is blocked in `pnpm-workspace.yaml`). Do this at the start of every task — see [Before You Start](#before-you-start). - Husky hooks: `pre-commit` runs `pnpm lint-staged`; `pre-push` runs `pnpm test`. Skip only intentionally (`--no-verify` or `HUSKY=0`). - No external services or databases required for local development. diff --git a/src/components/actions/CommandMenu/CommandMenu.tsx b/src/components/actions/CommandMenu/CommandMenu.tsx index 5a3248813..5e1f355ee 100644 --- a/src/components/actions/CommandMenu/CommandMenu.tsx +++ b/src/components/actions/CommandMenu/CommandMenu.tsx @@ -18,13 +18,15 @@ import React, { useState, } from 'react'; import { useFilter, useMenu } from 'react-aria'; -// Import Item and Section from Menu for CommandMenu compound component -import { Item, Section, useTreeState } from 'react-stately'; +import { Section, useTreeState } from 'react-stately'; import { useI18n } from '../../../i18n'; import { LoadingIcon } from '../../../icons'; import { mergeProps } from '../../../utils/react'; import { extractStyles } from '../../../utils/styles'; +// `CollectionItem` (not react-stately's bare `Item`) is what CommandMenu +// actually renders through `MenuItem`, so it carries the `Item` props. +import { CollectionItem as Item } from '../../CollectionItem'; import { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider'; import { useMenuContext } from '../Menu'; import { CubeMenuProps } from '../Menu/Menu'; diff --git a/src/components/fields/FilterListBox/FilterListBox.tsx b/src/components/fields/FilterListBox/FilterListBox.tsx index 3f457b347..bb692018b 100644 --- a/src/components/fields/FilterListBox/FilterListBox.tsx +++ b/src/components/fields/FilterListBox/FilterListBox.tsx @@ -22,8 +22,7 @@ import { useState, } from 'react'; import { useFilter, useKeyboard } from 'react-aria'; -import { Section as BaseSection, Item, useListState } from 'react-stately'; -import { CubeCollectionItemProps } from 'src/components/CollectionItem'; +import { Section as BaseSection, useListState } from 'react-stately'; import { useI18n } from '../../../i18n'; import { LoadingIcon } from '../../../icons'; @@ -31,6 +30,10 @@ import { mergeProps, modAttrs, useCombinedRefs } from '../../../utils/react'; import { useFocus } from '../../../utils/react/interactions'; import { extractStyles } from '../../../utils/styles'; import { StyledHeader } from '../../actions/Menu/styled'; +import { + CubeCollectionItemProps, + CollectionItem as Item, +} from '../../CollectionItem'; import { getValidationMods, useFieldProps, wrapWithField } from '../../form'; import { CubeListBoxProps, ListBox } from '../ListBox/ListBox'; import { @@ -587,7 +590,7 @@ export const FilterListBox = forwardRef(function FilterListBox< {term} @@ -1166,7 +1169,7 @@ export const FilterListBox = forwardRef(function FilterListBox< props: CubeFilterListBoxProps & { ref?: ForwardedRef }, ) => ReactElement) & { Item: typeof Item; Section: typeof BaseSection }; -FilterListBox.Item = ListBox.Item; +FilterListBox.Item = Item; FilterListBox.Section = BaseSection;