@cdx-ui/primitives 0.0.1-beta.3 → 0.0.1-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -24
- package/lib/commonjs/checkbox/createCheckboxRoot.web.js +8 -3
- package/lib/commonjs/checkbox/createCheckboxRoot.web.js.map +1 -1
- package/lib/commonjs/field/createFieldLabel.js.map +1 -1
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/input/createInputField.js +5 -0
- package/lib/commonjs/input/createInputField.js.map +1 -1
- package/lib/commonjs/list-item/context.js +11 -0
- package/lib/commonjs/list-item/context.js.map +1 -0
- package/lib/commonjs/list-item/createListItemContent.js +30 -0
- package/lib/commonjs/list-item/createListItemContent.js.map +1 -0
- package/lib/commonjs/list-item/createListItemDescription.js +25 -0
- package/lib/commonjs/list-item/createListItemDescription.js.map +1 -0
- package/lib/commonjs/list-item/createListItemLeadingSlot.js +34 -0
- package/lib/commonjs/list-item/createListItemLeadingSlot.js.map +1 -0
- package/lib/commonjs/list-item/createListItemMeta.js +25 -0
- package/lib/commonjs/list-item/createListItemMeta.js.map +1 -0
- package/lib/commonjs/list-item/createListItemRoot.js +157 -0
- package/lib/commonjs/list-item/createListItemRoot.js.map +1 -0
- package/lib/commonjs/list-item/createListItemSectionHeader.js +54 -0
- package/lib/commonjs/list-item/createListItemSectionHeader.js.map +1 -0
- package/lib/commonjs/list-item/createListItemTitle.js +25 -0
- package/lib/commonjs/list-item/createListItemTitle.js.map +1 -0
- package/lib/commonjs/list-item/createListItemTrailingSlot.js +28 -0
- package/lib/commonjs/list-item/createListItemTrailingSlot.js.map +1 -0
- package/lib/commonjs/list-item/index.js +55 -0
- package/lib/commonjs/list-item/index.js.map +1 -0
- package/lib/commonjs/list-item/types.js +6 -0
- package/lib/commonjs/list-item/types.js.map +1 -0
- package/lib/commonjs/radio/context.js +14 -0
- package/lib/commonjs/radio/context.js.map +1 -0
- package/lib/commonjs/radio/createRadioGroup.js +66 -0
- package/lib/commonjs/radio/createRadioGroup.js.map +1 -0
- package/lib/commonjs/radio/createRadioIndicator.js +43 -0
- package/lib/commonjs/radio/createRadioIndicator.js.map +1 -0
- package/lib/commonjs/radio/createRadioLabel.js +38 -0
- package/lib/commonjs/radio/createRadioLabel.js.map +1 -0
- package/lib/commonjs/radio/createRadioRoot.js +95 -0
- package/lib/commonjs/radio/createRadioRoot.js.map +1 -0
- package/lib/commonjs/radio/createRadioRoot.web.js +87 -0
- package/lib/commonjs/radio/createRadioRoot.web.js.map +1 -0
- package/lib/commonjs/radio/index.js +26 -0
- package/lib/commonjs/radio/index.js.map +1 -0
- package/lib/commonjs/radio/types.js +6 -0
- package/lib/commonjs/radio/types.js.map +1 -0
- package/lib/commonjs/radio/useRadioRoot.js +64 -0
- package/lib/commonjs/radio/useRadioRoot.js.map +1 -0
- package/lib/commonjs/select/createSelectTrigger.js +17 -4
- package/lib/commonjs/select/createSelectTrigger.js.map +1 -1
- package/lib/commonjs/tile/context.js +30 -0
- package/lib/commonjs/tile/context.js.map +1 -0
- package/lib/commonjs/tile/createTileContent.js +30 -0
- package/lib/commonjs/tile/createTileContent.js.map +1 -0
- package/lib/commonjs/tile/createTileDescription.js +28 -0
- package/lib/commonjs/tile/createTileDescription.js.map +1 -0
- package/lib/commonjs/tile/createTileGroup.js +112 -0
- package/lib/commonjs/tile/createTileGroup.js.map +1 -0
- package/lib/commonjs/tile/createTileIndicator.js +46 -0
- package/lib/commonjs/tile/createTileIndicator.js.map +1 -0
- package/lib/commonjs/tile/createTileLeadingSlot.js +34 -0
- package/lib/commonjs/tile/createTileLeadingSlot.js.map +1 -0
- package/lib/commonjs/tile/createTileRoot.js +133 -0
- package/lib/commonjs/tile/createTileRoot.js.map +1 -0
- package/lib/commonjs/tile/createTileTitle.js +28 -0
- package/lib/commonjs/tile/createTileTitle.js.map +1 -0
- package/lib/commonjs/tile/createTileTrailingSlot.js +35 -0
- package/lib/commonjs/tile/createTileTrailingSlot.js.map +1 -0
- package/lib/commonjs/tile/index.js +55 -0
- package/lib/commonjs/tile/index.js.map +1 -0
- package/lib/commonjs/tile/types.js +6 -0
- package/lib/commonjs/tile/types.js.map +1 -0
- package/lib/module/checkbox/createCheckboxRoot.web.js +8 -2
- package/lib/module/checkbox/createCheckboxRoot.web.js.map +1 -1
- package/lib/module/field/createFieldLabel.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/input/createInputField.js +5 -0
- package/lib/module/input/createInputField.js.map +1 -1
- package/lib/module/list-item/context.js +5 -0
- package/lib/module/list-item/context.js.map +1 -0
- package/lib/module/list-item/createListItemContent.js +24 -0
- package/lib/module/list-item/createListItemContent.js.map +1 -0
- package/lib/module/list-item/createListItemDescription.js +19 -0
- package/lib/module/list-item/createListItemDescription.js.map +1 -0
- package/lib/module/list-item/createListItemLeadingSlot.js +28 -0
- package/lib/module/list-item/createListItemLeadingSlot.js.map +1 -0
- package/lib/module/list-item/createListItemMeta.js +19 -0
- package/lib/module/list-item/createListItemMeta.js.map +1 -0
- package/lib/module/list-item/createListItemRoot.js +151 -0
- package/lib/module/list-item/createListItemRoot.js.map +1 -0
- package/lib/module/list-item/createListItemSectionHeader.js +48 -0
- package/lib/module/list-item/createListItemSectionHeader.js.map +1 -0
- package/lib/module/list-item/createListItemTitle.js +19 -0
- package/lib/module/list-item/createListItemTitle.js.map +1 -0
- package/lib/module/list-item/createListItemTrailingSlot.js +22 -0
- package/lib/module/list-item/createListItemTrailingSlot.js.map +1 -0
- package/lib/module/list-item/index.js +39 -0
- package/lib/module/list-item/index.js.map +1 -0
- package/lib/module/list-item/types.js +4 -0
- package/lib/module/list-item/types.js.map +1 -0
- package/lib/module/radio/context.js +7 -0
- package/lib/module/radio/context.js.map +1 -0
- package/lib/module/radio/createRadioGroup.js +61 -0
- package/lib/module/radio/createRadioGroup.js.map +1 -0
- package/lib/module/radio/createRadioIndicator.js +38 -0
- package/lib/module/radio/createRadioIndicator.js.map +1 -0
- package/lib/module/radio/createRadioLabel.js +33 -0
- package/lib/module/radio/createRadioLabel.js.map +1 -0
- package/lib/module/radio/createRadioRoot.js +90 -0
- package/lib/module/radio/createRadioRoot.js.map +1 -0
- package/lib/module/radio/createRadioRoot.web.js +82 -0
- package/lib/module/radio/createRadioRoot.web.js.map +1 -0
- package/lib/module/radio/index.js +22 -0
- package/lib/module/radio/index.js.map +1 -0
- package/lib/module/radio/types.js +4 -0
- package/lib/module/radio/types.js.map +1 -0
- package/lib/module/radio/useRadioRoot.js +60 -0
- package/lib/module/radio/useRadioRoot.js.map +1 -0
- package/lib/module/select/createSelectTrigger.js +19 -6
- package/lib/module/select/createSelectTrigger.js.map +1 -1
- package/lib/module/tile/context.js +21 -0
- package/lib/module/tile/context.js.map +1 -0
- package/lib/module/tile/createTileContent.js +24 -0
- package/lib/module/tile/createTileContent.js.map +1 -0
- package/lib/module/tile/createTileDescription.js +22 -0
- package/lib/module/tile/createTileDescription.js.map +1 -0
- package/lib/module/tile/createTileGroup.js +106 -0
- package/lib/module/tile/createTileGroup.js.map +1 -0
- package/lib/module/tile/createTileIndicator.js +40 -0
- package/lib/module/tile/createTileIndicator.js.map +1 -0
- package/lib/module/tile/createTileLeadingSlot.js +28 -0
- package/lib/module/tile/createTileLeadingSlot.js.map +1 -0
- package/lib/module/tile/createTileRoot.js +127 -0
- package/lib/module/tile/createTileRoot.js.map +1 -0
- package/lib/module/tile/createTileTitle.js +22 -0
- package/lib/module/tile/createTileTitle.js.map +1 -0
- package/lib/module/tile/createTileTrailingSlot.js +29 -0
- package/lib/module/tile/createTileTrailingSlot.js.map +1 -0
- package/lib/module/tile/index.js +39 -0
- package/lib/module/tile/index.js.map +1 -0
- package/lib/module/tile/types.js +4 -0
- package/lib/module/tile/types.js.map +1 -0
- package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts +4 -0
- package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts.map +1 -1
- package/lib/typescript/checkbox/useCheckboxRoot.d.ts +2 -0
- package/lib/typescript/checkbox/useCheckboxRoot.d.ts.map +1 -1
- package/lib/typescript/field/createFieldLabel.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/input/createInputField.d.ts.map +1 -1
- package/lib/typescript/list-item/context.d.ts +6 -0
- package/lib/typescript/list-item/context.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemContent.d.ts +3 -0
- package/lib/typescript/list-item/createListItemContent.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemDescription.d.ts +3 -0
- package/lib/typescript/list-item/createListItemDescription.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemLeadingSlot.d.ts +4 -0
- package/lib/typescript/list-item/createListItemLeadingSlot.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemMeta.d.ts +3 -0
- package/lib/typescript/list-item/createListItemMeta.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemRoot.d.ts +4 -0
- package/lib/typescript/list-item/createListItemRoot.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemSectionHeader.d.ts +4 -0
- package/lib/typescript/list-item/createListItemSectionHeader.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemTitle.d.ts +3 -0
- package/lib/typescript/list-item/createListItemTitle.d.ts.map +1 -0
- package/lib/typescript/list-item/createListItemTrailingSlot.d.ts +3 -0
- package/lib/typescript/list-item/createListItemTrailingSlot.d.ts.map +1 -0
- package/lib/typescript/list-item/index.d.ts +16 -0
- package/lib/typescript/list-item/index.d.ts.map +1 -0
- package/lib/typescript/list-item/types.d.ts +86 -0
- package/lib/typescript/list-item/types.d.ts.map +1 -0
- package/lib/typescript/radio/context.d.ts +21 -0
- package/lib/typescript/radio/context.d.ts.map +1 -0
- package/lib/typescript/radio/createRadioGroup.d.ts +3 -0
- package/lib/typescript/radio/createRadioGroup.d.ts.map +1 -0
- package/lib/typescript/radio/createRadioIndicator.d.ts +5 -0
- package/lib/typescript/radio/createRadioIndicator.d.ts.map +1 -0
- package/lib/typescript/radio/createRadioLabel.d.ts +5 -0
- package/lib/typescript/radio/createRadioLabel.d.ts.map +1 -0
- package/lib/typescript/radio/createRadioRoot.d.ts +3 -0
- package/lib/typescript/radio/createRadioRoot.d.ts.map +1 -0
- package/lib/typescript/radio/createRadioRoot.web.d.ts +3 -0
- package/lib/typescript/radio/createRadioRoot.web.d.ts.map +1 -0
- package/lib/typescript/radio/index.d.ts +10 -0
- package/lib/typescript/radio/index.d.ts.map +1 -0
- package/lib/typescript/radio/types.d.ts +54 -0
- package/lib/typescript/radio/types.d.ts.map +1 -0
- package/lib/typescript/radio/useRadioRoot.d.ts +151 -0
- package/lib/typescript/radio/useRadioRoot.d.ts.map +1 -0
- package/lib/typescript/select/createSelectTrigger.d.ts.map +1 -1
- package/lib/typescript/tile/context.d.ts +9 -0
- package/lib/typescript/tile/context.d.ts.map +1 -0
- package/lib/typescript/tile/createTileContent.d.ts +3 -0
- package/lib/typescript/tile/createTileContent.d.ts.map +1 -0
- package/lib/typescript/tile/createTileDescription.d.ts +3 -0
- package/lib/typescript/tile/createTileDescription.d.ts.map +1 -0
- package/lib/typescript/tile/createTileGroup.d.ts +4 -0
- package/lib/typescript/tile/createTileGroup.d.ts.map +1 -0
- package/lib/typescript/tile/createTileIndicator.d.ts +4 -0
- package/lib/typescript/tile/createTileIndicator.d.ts.map +1 -0
- package/lib/typescript/tile/createTileLeadingSlot.d.ts +4 -0
- package/lib/typescript/tile/createTileLeadingSlot.d.ts.map +1 -0
- package/lib/typescript/tile/createTileRoot.d.ts +4 -0
- package/lib/typescript/tile/createTileRoot.d.ts.map +1 -0
- package/lib/typescript/tile/createTileTitle.d.ts +3 -0
- package/lib/typescript/tile/createTileTitle.d.ts.map +1 -0
- package/lib/typescript/tile/createTileTrailingSlot.d.ts +9 -0
- package/lib/typescript/tile/createTileTrailingSlot.d.ts.map +1 -0
- package/lib/typescript/tile/index.d.ts +15 -0
- package/lib/typescript/tile/index.d.ts.map +1 -0
- package/lib/typescript/tile/types.d.ts +119 -0
- package/lib/typescript/tile/types.d.ts.map +1 -0
- package/package.json +5 -2
- package/src/checkbox/createCheckboxRoot.web.tsx +6 -2
- package/src/field/createFieldLabel.tsx +4 -1
- package/src/index.ts +3 -0
- package/src/input/createInputField.tsx +6 -0
- package/src/list-item/context.tsx +5 -0
- package/src/list-item/createListItemContent.tsx +23 -0
- package/src/list-item/createListItemDescription.tsx +19 -0
- package/src/list-item/createListItemLeadingSlot.tsx +30 -0
- package/src/list-item/createListItemMeta.tsx +17 -0
- package/src/list-item/createListItemRoot.tsx +178 -0
- package/src/list-item/createListItemSectionHeader.tsx +53 -0
- package/src/list-item/createListItemTitle.tsx +17 -0
- package/src/list-item/createListItemTrailingSlot.tsx +21 -0
- package/src/list-item/index.ts +88 -0
- package/src/list-item/types.ts +122 -0
- package/src/radio/context.tsx +21 -0
- package/src/radio/createRadioGroup.tsx +67 -0
- package/src/radio/createRadioIndicator.tsx +32 -0
- package/src/radio/createRadioLabel.tsx +28 -0
- package/src/radio/createRadioRoot.tsx +100 -0
- package/src/radio/createRadioRoot.web.tsx +81 -0
- package/src/radio/index.ts +37 -0
- package/src/radio/types.ts +67 -0
- package/src/radio/useRadioRoot.ts +69 -0
- package/src/select/createSelectTrigger.tsx +26 -3
- package/src/tile/context.tsx +23 -0
- package/src/tile/createTileContent.tsx +23 -0
- package/src/tile/createTileDescription.tsx +19 -0
- package/src/tile/createTileGroup.tsx +134 -0
- package/src/tile/createTileIndicator.tsx +38 -0
- package/src/tile/createTileLeadingSlot.tsx +30 -0
- package/src/tile/createTileRoot.tsx +124 -0
- package/src/tile/createTileTitle.tsx +19 -0
- package/src/tile/createTileTrailingSlot.tsx +25 -0
- package/src/tile/index.ts +88 -0
- package/src/tile/types.ts +153 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTileTitle.d.ts","sourceRoot":"","sources":["../../../src/tile/createTileTitle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,eAAO,MAAM,eAAe,GAAI,CAAC,EAAG,MAAM,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,qGAY5D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Generic trailing content (chevron, amount, chip, status). Distinct from `Tile.Indicator`,
|
|
4
|
+
* which is purpose-built for the radio/checkbox selection affordance.
|
|
5
|
+
*
|
|
6
|
+
* Trailing content is meaningful by default (`aria-hidden` falsy), unlike the indicator.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createTileTrailingSlot: <T>(Base: React.ComponentType<T>) => React.ForwardRefExoticComponent<import("react-native").ViewProps & React.RefAttributes<unknown>>;
|
|
9
|
+
//# sourceMappingURL=createTileTrailingSlot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTileTrailingSlot.d.ts","sourceRoot":"","sources":["../../../src/tile/createTileTrailingSlot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,EAAG,MAAM,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,qGAYnE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ITileComponentType } from './types';
|
|
3
|
+
export type { ITileComponentType, ITileContentProps, ITileContextValue, ITileDescriptionProps, ITileGroupMultipleProps, ITileGroupProps, ITileGroupSingleProps, ITileGroupContextValue, ITileIndicatorProps, ITileLeadingSlotProps, ITilePressablePassthrough, ITileProps, ITileTitleProps, ITileTrailingSlotProps, TileGroupType, TileGroupValue, } from './types';
|
|
4
|
+
export { TileProvider, useTileContext } from './context';
|
|
5
|
+
export declare function createTile<Pressable, Leading, Content, Title, Description, Indicator, TrailingSlot, Group>(BaseComponents: {
|
|
6
|
+
Pressable: React.ComponentType<Pressable>;
|
|
7
|
+
LeadingSlot: React.ComponentType<Leading>;
|
|
8
|
+
Content: React.ComponentType<Content>;
|
|
9
|
+
Title: React.ComponentType<Title>;
|
|
10
|
+
Description: React.ComponentType<Description>;
|
|
11
|
+
Indicator: React.ComponentType<Indicator>;
|
|
12
|
+
TrailingSlot: React.ComponentType<TrailingSlot>;
|
|
13
|
+
Group: React.ComponentType<Group>;
|
|
14
|
+
}): ITileComponentType<Pressable, Leading, Content, Title, Description, Indicator, TrailingSlot, Group>;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tile/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEzD,wBAAgB,UAAU,CACxB,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,EACL,WAAW,EACX,SAAS,EACT,YAAY,EACZ,KAAK,EACL,cAAc,EAAE;IAChB,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1C,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1C,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAChD,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;CACnC,GA2BO,kBAAkB,CACtB,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,EACL,WAAW,EACX,SAAS,EACT,YAAY,EACZ,KAAK,CACN,CACF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { ForwardRefExoticComponent, PropsWithoutRef, ReactNode, RefAttributes } from 'react';
|
|
2
|
+
import type { PressableProps, TextProps, ViewProps } from 'react-native';
|
|
3
|
+
import type { WithStyleContextProps } from '@cdx-ui/utils';
|
|
4
|
+
export type TileGroupType = 'single' | 'multiple';
|
|
5
|
+
export type TileGroupValue = string | string[] | undefined;
|
|
6
|
+
interface ITileGroupBaseProps extends ViewProps, WithStyleContextProps {
|
|
7
|
+
/** Disables the whole group. */
|
|
8
|
+
isDisabled?: boolean;
|
|
9
|
+
/** Accessible name for the group (radiogroup / group). */
|
|
10
|
+
'aria-label'?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ITileGroupSingleProps extends ITileGroupBaseProps {
|
|
13
|
+
/** Single-select (radio semantics). One value at a time. */
|
|
14
|
+
type: 'single';
|
|
15
|
+
/** Controlled selected value. */
|
|
16
|
+
value?: string;
|
|
17
|
+
/** Uncontrolled initial value. */
|
|
18
|
+
defaultValue?: string;
|
|
19
|
+
/** Called when selection changes. */
|
|
20
|
+
onValueChange?: (value: string) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface ITileGroupMultipleProps extends ITileGroupBaseProps {
|
|
23
|
+
/** Multi-select (checkbox semantics). Zero to `max` values at a time. */
|
|
24
|
+
type: 'multiple';
|
|
25
|
+
/** Controlled selected values. */
|
|
26
|
+
value?: string[];
|
|
27
|
+
/** Uncontrolled initial values. */
|
|
28
|
+
defaultValue?: string[];
|
|
29
|
+
/** Called when selection changes. */
|
|
30
|
+
onValueChange?: (value: string[]) => void;
|
|
31
|
+
/** Maximum selections allowed. @default Infinity */
|
|
32
|
+
max?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Discriminated union: `type` narrows `value` / `defaultValue` / `onValueChange`,
|
|
36
|
+
* and `max` is only valid on `type="multiple"`.
|
|
37
|
+
*/
|
|
38
|
+
export type ITileGroupProps = ITileGroupSingleProps | ITileGroupMultipleProps;
|
|
39
|
+
export interface ITileGroupContextValue {
|
|
40
|
+
type: TileGroupType;
|
|
41
|
+
/** Current selection (string for single, array for multiple). */
|
|
42
|
+
value: string | string[] | undefined;
|
|
43
|
+
toggleValue: (tileValue: string) => void;
|
|
44
|
+
isSelected: (tileValue: string) => boolean;
|
|
45
|
+
/** Group-level disabled or multi-select at max (unselected tiles). */
|
|
46
|
+
isTileDisabledByGroup: (tileValue: string) => boolean;
|
|
47
|
+
isGroupDisabled: boolean;
|
|
48
|
+
max: number;
|
|
49
|
+
}
|
|
50
|
+
export interface ITileContextValue {
|
|
51
|
+
/** This tile's `value`. */
|
|
52
|
+
value: string;
|
|
53
|
+
isSelected: boolean;
|
|
54
|
+
/** Effective disabled (group rules + tile `disabled`). */
|
|
55
|
+
isDisabled: boolean;
|
|
56
|
+
selectionType: TileGroupType;
|
|
57
|
+
}
|
|
58
|
+
export type ITilePressablePassthrough = Partial<Pick<PressableProps, 'onPressIn' | 'onPressOut' | 'onHoverIn' | 'onHoverOut'>>;
|
|
59
|
+
export interface ITileProps extends PressableProps, ITilePressablePassthrough, WithStyleContextProps {
|
|
60
|
+
/**
|
|
61
|
+
* Identifies this tile within `Tile.Group`. Must be unique within the group.
|
|
62
|
+
* Standalone tiles still require a value (useful for form submission, analytics, etc.).
|
|
63
|
+
*/
|
|
64
|
+
value: string;
|
|
65
|
+
/**
|
|
66
|
+
* Disables this tile (in addition to group rules such as multi-select max).
|
|
67
|
+
*/
|
|
68
|
+
disabled?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Controlled selected state for **standalone** usage (no parent `Tile.Group`).
|
|
71
|
+
* Ignored when the tile is rendered inside a `Tile.Group` — selection is owned by the group.
|
|
72
|
+
*/
|
|
73
|
+
isSelected?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Initial selected state for **standalone**, uncontrolled usage.
|
|
76
|
+
*/
|
|
77
|
+
defaultSelected?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Called when standalone selection state changes. Group context overrides this — when inside
|
|
80
|
+
* a `Tile.Group`, use the group's `onValueChange` instead.
|
|
81
|
+
*/
|
|
82
|
+
onSelectedChange?: (isSelected: boolean) => void;
|
|
83
|
+
}
|
|
84
|
+
export interface ITileLeadingSlotProps extends ViewProps {
|
|
85
|
+
/**
|
|
86
|
+
* Leading content is decorative by default for screen readers.
|
|
87
|
+
* @default true
|
|
88
|
+
*/
|
|
89
|
+
'aria-hidden'?: boolean;
|
|
90
|
+
}
|
|
91
|
+
export type ITileContentProps = ViewProps;
|
|
92
|
+
export type ITileTitleProps = TextProps;
|
|
93
|
+
export type ITileDescriptionProps = TextProps;
|
|
94
|
+
export interface ITileIndicatorProps extends ViewProps {
|
|
95
|
+
/**
|
|
96
|
+
* Explicit indicator visual. When inside a `Tile.Group`, auto-infers from `type`
|
|
97
|
+
* (`single` → radio, `multiple` → checkbox). For standalone tiles, defaults to `'checkbox'`
|
|
98
|
+
* to match the standalone `checkbox` ARIA role; override with `indicatorType="radio"` if
|
|
99
|
+
* a radio-style visual is needed.
|
|
100
|
+
*/
|
|
101
|
+
indicatorType?: 'radio' | 'checkbox';
|
|
102
|
+
children?: ReactNode;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Generic trailing content slot. Use for chevrons, amounts, chips, status text — anything that
|
|
106
|
+
* is **not** the radio/checkbox selection affordance. For that, use `Tile.Indicator`.
|
|
107
|
+
*/
|
|
108
|
+
export type ITileTrailingSlotProps = ViewProps;
|
|
109
|
+
export type ITileComponentType<RootRef, LeadingSlot, Content, Title, Description, Indicator, TrailingSlot, Group> = ForwardRefExoticComponent<RefAttributes<RootRef> & ITileProps> & {
|
|
110
|
+
Group: ForwardRefExoticComponent<RefAttributes<Group> & PropsWithoutRef<Group> & ITileGroupProps>;
|
|
111
|
+
LeadingSlot: ForwardRefExoticComponent<RefAttributes<LeadingSlot> & PropsWithoutRef<LeadingSlot> & ITileLeadingSlotProps>;
|
|
112
|
+
Content: ForwardRefExoticComponent<RefAttributes<Content> & PropsWithoutRef<Content> & ITileContentProps>;
|
|
113
|
+
Title: ForwardRefExoticComponent<RefAttributes<Title> & PropsWithoutRef<Title> & ITileTitleProps>;
|
|
114
|
+
Description: ForwardRefExoticComponent<RefAttributes<Description> & PropsWithoutRef<Description> & ITileDescriptionProps>;
|
|
115
|
+
Indicator: ForwardRefExoticComponent<RefAttributes<Indicator> & PropsWithoutRef<Indicator> & ITileIndicatorProps>;
|
|
116
|
+
TrailingSlot: ForwardRefExoticComponent<RefAttributes<TrailingSlot> & PropsWithoutRef<TrailingSlot> & ITileTrailingSlotProps>;
|
|
117
|
+
};
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tile/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdx-ui/primitives",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.31",
|
|
4
4
|
"main": "lib/commonjs/index.js",
|
|
5
5
|
"module": "lib/module/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -51,13 +51,16 @@
|
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
+
"@react-aria/utils": "^3.33.0",
|
|
54
55
|
"@react-aria/visually-hidden": "3.8.30",
|
|
55
56
|
"@react-native-aria/checkbox": "0.2.10",
|
|
56
57
|
"@react-native-aria/focus": "^0.2.9",
|
|
57
58
|
"@react-native-aria/interactions": "^0.2.16",
|
|
59
|
+
"@react-native-aria/radio": "0.2.13",
|
|
58
60
|
"@react-stately/checkbox": "3.7.4",
|
|
61
|
+
"@react-stately/radio": "3.12.0",
|
|
59
62
|
"@react-stately/toggle": "3.9.4",
|
|
60
|
-
"@cdx-ui/utils": "0.0.1-beta.
|
|
63
|
+
"@cdx-ui/utils": "0.0.1-beta.31"
|
|
61
64
|
},
|
|
62
65
|
"devDependencies": {
|
|
63
66
|
"@types/react": "*",
|
|
@@ -6,8 +6,10 @@ import { CheckboxProvider } from './context';
|
|
|
6
6
|
import type { ICheckboxProps } from './types';
|
|
7
7
|
import { useCheckboxRoot } from './useCheckboxRoot';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Web uses a native checkbox input (VisuallyHidden) for ARIA + focus management. The outer
|
|
11
|
+
* `Pressable` must not be in the tab order or each control consumes two Tab stops (wrapper + input).
|
|
12
|
+
*/
|
|
11
13
|
export const createCheckboxRoot = <T,>(BaseCheckbox: React.ComponentType<T>) =>
|
|
12
14
|
forwardRef(({ children, ...props }: ICheckboxProps, ref?: React.Ref<T>) => {
|
|
13
15
|
const {
|
|
@@ -41,6 +43,8 @@ export const createCheckboxRoot = <T,>(BaseCheckbox: React.ComponentType<T>) =>
|
|
|
41
43
|
<BaseCheckbox
|
|
42
44
|
{...(combinedProps as T)}
|
|
43
45
|
ref={mergedRef}
|
|
46
|
+
// Native input is the only tab stop; Pressable is still clickable (mouse / screen reader).
|
|
47
|
+
tabIndex={-1}
|
|
44
48
|
role="label"
|
|
45
49
|
// eslint-disable-next-line react-native-a11y/has-valid-accessibility-role
|
|
46
50
|
accessibilityRole="label"
|
|
@@ -20,7 +20,10 @@ export const createFieldLabel = <T,>(BaseFormLabel: React.ComponentType<T>) =>
|
|
|
20
20
|
{...(props as T)}
|
|
21
21
|
id={labelId}
|
|
22
22
|
htmlFor={htmlFor}
|
|
23
|
-
{...dataAttributes({
|
|
23
|
+
{...dataAttributes({
|
|
24
|
+
invalid: field.isInvalid,
|
|
25
|
+
required: field.isRequired,
|
|
26
|
+
})}
|
|
24
27
|
>
|
|
25
28
|
{children}
|
|
26
29
|
{field.isRequired ? requiredIndicator : null}
|
package/src/index.ts
CHANGED
|
@@ -7,9 +7,12 @@ export * from './form';
|
|
|
7
7
|
export * from './input';
|
|
8
8
|
export * from './otp-input';
|
|
9
9
|
export * from './link';
|
|
10
|
+
export * from './list-item';
|
|
10
11
|
export { type EdgeInsets, OverlayInsetsProvider } from './overlay';
|
|
11
12
|
export * from './select';
|
|
12
13
|
export * from './switch';
|
|
14
|
+
export * from './tile';
|
|
13
15
|
export * from './progress';
|
|
16
|
+
export * from './radio';
|
|
14
17
|
export type { InteractionState } from './types';
|
|
15
18
|
export { dataAttributes } from './utils/dataAttributes';
|
|
@@ -49,8 +49,14 @@ export const createInputField = <T,>(BaseInputField: React.ComponentType<T>) =>
|
|
|
49
49
|
|
|
50
50
|
const field = useFormControlContext();
|
|
51
51
|
|
|
52
|
+
const reportLabelFocus = (focused: boolean) => {
|
|
53
|
+
const active = focused && !(isDisabled || inputProps.disabled);
|
|
54
|
+
field.setIsLabelFocused?.(active);
|
|
55
|
+
};
|
|
56
|
+
|
|
52
57
|
const handleFocus = (focusState: boolean, callback: any) => {
|
|
53
58
|
setIsFocused(focusState);
|
|
59
|
+
reportLabelFocus(focusState);
|
|
54
60
|
callback();
|
|
55
61
|
};
|
|
56
62
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemContentProps } from './types';
|
|
4
|
+
|
|
5
|
+
const contentStyle = {
|
|
6
|
+
flex: 1,
|
|
7
|
+
flexDirection: 'column' as const,
|
|
8
|
+
minWidth: 0,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const createListItemContent = <T,>(Base: React.ComponentType<T>) =>
|
|
12
|
+
forwardRef(({ children, style, ...props }: IListItemContentProps, ref: React.Ref<unknown>) => (
|
|
13
|
+
<Base
|
|
14
|
+
{...(props as T)}
|
|
15
|
+
{...dataAttributes({
|
|
16
|
+
slot: 'list-item-content',
|
|
17
|
+
})}
|
|
18
|
+
ref={ref as React.Ref<T>}
|
|
19
|
+
style={[contentStyle, style]}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</Base>
|
|
23
|
+
));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemDescriptionProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const createListItemDescription = <T,>(Base: React.ComponentType<T>) =>
|
|
6
|
+
forwardRef(
|
|
7
|
+
({ children, style, ...props }: IListItemDescriptionProps, ref: React.Ref<unknown>) => (
|
|
8
|
+
<Base
|
|
9
|
+
{...(props as T)}
|
|
10
|
+
{...dataAttributes({
|
|
11
|
+
slot: 'list-item-description',
|
|
12
|
+
})}
|
|
13
|
+
ref={ref as React.Ref<T>}
|
|
14
|
+
style={style}
|
|
15
|
+
>
|
|
16
|
+
{children}
|
|
17
|
+
</Base>
|
|
18
|
+
),
|
|
19
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemLeadingSlotProps } from './types';
|
|
4
|
+
|
|
5
|
+
const shrinkZero = { flexShrink: 0 as const };
|
|
6
|
+
|
|
7
|
+
export const createListItemLeadingSlot = <T,>(Base: React.ComponentType<T>) =>
|
|
8
|
+
forwardRef(
|
|
9
|
+
(
|
|
10
|
+
{ 'aria-hidden': ariaHidden, style, children, ...props }: IListItemLeadingSlotProps,
|
|
11
|
+
ref: React.Ref<unknown>,
|
|
12
|
+
) => {
|
|
13
|
+
const accessibilityElementsHidden = ariaHidden !== false;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Base
|
|
17
|
+
{...(props as T)}
|
|
18
|
+
{...dataAttributes({
|
|
19
|
+
slot: 'list-item-leading',
|
|
20
|
+
})}
|
|
21
|
+
accessibilityElementsHidden={accessibilityElementsHidden}
|
|
22
|
+
aria-hidden={ariaHidden}
|
|
23
|
+
ref={ref as React.Ref<T>}
|
|
24
|
+
style={[shrinkZero, style]}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
</Base>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemMetaProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const createListItemMeta = <T,>(Base: React.ComponentType<T>) =>
|
|
6
|
+
forwardRef(({ children, style, ...props }: IListItemMetaProps, ref: React.Ref<unknown>) => (
|
|
7
|
+
<Base
|
|
8
|
+
{...(props as T)}
|
|
9
|
+
{...dataAttributes({
|
|
10
|
+
slot: 'list-item-meta',
|
|
11
|
+
})}
|
|
12
|
+
ref={ref as React.Ref<T>}
|
|
13
|
+
style={style}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</Base>
|
|
17
|
+
));
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
2
|
+
import type { PressableProps } from 'react-native';
|
|
3
|
+
import { composeEventHandlers, mergeRefs } from '@cdx-ui/utils';
|
|
4
|
+
import { useHover, usePress } from '@react-native-aria/interactions';
|
|
5
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
6
|
+
import { ListItemProvider } from './context';
|
|
7
|
+
import type { IListItemProps, IListItemPressablePassthrough } from './types';
|
|
8
|
+
|
|
9
|
+
function listItemRootDataAttrs(
|
|
10
|
+
size: IListItemProps['size'],
|
|
11
|
+
surface: IListItemProps['surface'],
|
|
12
|
+
showSeparator: boolean | undefined,
|
|
13
|
+
crossAlign: IListItemProps['crossAlign'],
|
|
14
|
+
) {
|
|
15
|
+
return dataAttributes({
|
|
16
|
+
slot: 'list-item',
|
|
17
|
+
size: size ?? 'default',
|
|
18
|
+
surface: surface ?? 'default',
|
|
19
|
+
separator: showSeparator ?? true,
|
|
20
|
+
crossAlign: crossAlign ?? 'center',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function rowStyleForCrossAlign(crossAlign: IListItemProps['crossAlign']) {
|
|
25
|
+
return {
|
|
26
|
+
flexDirection: 'row' as const,
|
|
27
|
+
alignSelf: 'stretch' as const,
|
|
28
|
+
alignItems: crossAlign === 'start' ? ('flex-start' as const) : ('center' as const),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const createListItemRoot = <V, P>(
|
|
33
|
+
BaseView: React.ComponentType<V>,
|
|
34
|
+
BasePressable: React.ComponentType<P>,
|
|
35
|
+
) =>
|
|
36
|
+
forwardRef(
|
|
37
|
+
(
|
|
38
|
+
{
|
|
39
|
+
asChild = false,
|
|
40
|
+
children,
|
|
41
|
+
onPress,
|
|
42
|
+
size = 'default',
|
|
43
|
+
surface = 'default',
|
|
44
|
+
showSeparator = true,
|
|
45
|
+
crossAlign = 'center',
|
|
46
|
+
disabled = false,
|
|
47
|
+
style,
|
|
48
|
+
...restProps
|
|
49
|
+
}: IListItemProps,
|
|
50
|
+
ref: React.Ref<unknown>,
|
|
51
|
+
) => {
|
|
52
|
+
const childOnPress = React.isValidElement(children)
|
|
53
|
+
? ((children.props as { onPress?: unknown }).onPress as
|
|
54
|
+
| IListItemProps['onPress']
|
|
55
|
+
| undefined)
|
|
56
|
+
: undefined;
|
|
57
|
+
|
|
58
|
+
// asChild always wins when explicitly set with a valid element — even when the press
|
|
59
|
+
// surface is built internally by the child (e.g. `Link` adds its onPress via `useLink`,
|
|
60
|
+
// not as a JSX-level prop). The clone path below preserves the child's own press by
|
|
61
|
+
// *omitting* `onPress` when there is nothing to compose.
|
|
62
|
+
const asChildInteractive = asChild && React.isValidElement(children);
|
|
63
|
+
const isPressableRoot = !!onPress && !asChildInteractive;
|
|
64
|
+
|
|
65
|
+
const pressState = usePress({
|
|
66
|
+
isDisabled: !isPressableRoot || disabled,
|
|
67
|
+
});
|
|
68
|
+
const isPressed = pressState.isPressed;
|
|
69
|
+
const pressProps = pressState.pressProps as Pick<PressableProps, 'onPressIn' | 'onPressOut'>;
|
|
70
|
+
const { hoverProps, isHovered } = useHover();
|
|
71
|
+
|
|
72
|
+
const slotAttrs = listItemRootDataAttrs(size, surface, showSeparator, crossAlign);
|
|
73
|
+
|
|
74
|
+
const contextValue = useMemo(
|
|
75
|
+
() => ({
|
|
76
|
+
isPressed: isPressableRoot ? isPressed : false,
|
|
77
|
+
isHovered,
|
|
78
|
+
isDisabled: disabled,
|
|
79
|
+
crossAlign: crossAlign ?? 'center',
|
|
80
|
+
}),
|
|
81
|
+
[isPressableRoot, isPressed, isHovered, disabled, crossAlign],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (asChildInteractive) {
|
|
85
|
+
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
86
|
+
|
|
87
|
+
const childDisabled = !!(child.props as { disabled?: boolean }).disabled;
|
|
88
|
+
const resolvedDisabled = disabled || childDisabled;
|
|
89
|
+
|
|
90
|
+
const cloneProps: Record<string, unknown> = {
|
|
91
|
+
...restProps,
|
|
92
|
+
...slotAttrs,
|
|
93
|
+
...dataAttributes({
|
|
94
|
+
active: false,
|
|
95
|
+
hover: false,
|
|
96
|
+
disabled: resolvedDisabled,
|
|
97
|
+
}),
|
|
98
|
+
...(resolvedDisabled && { accessibilityState: { disabled: true } }),
|
|
99
|
+
disabled: resolvedDisabled,
|
|
100
|
+
ref: mergeRefs(ref, child.props.ref as React.Ref<unknown>),
|
|
101
|
+
style: [rowStyleForCrossAlign(crossAlign), style, child.props.style],
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Only override the child's `onPress` when we have something to add (a parent handler)
|
|
105
|
+
// or need to suppress (disabled). Otherwise leave the child's own onPress alone — e.g.
|
|
106
|
+
// `Link` builds its navigation handler inside `useLink`, not as a JSX-level prop, and
|
|
107
|
+
// overriding here would shadow it.
|
|
108
|
+
if (resolvedDisabled) {
|
|
109
|
+
cloneProps.onPress = undefined;
|
|
110
|
+
} else if (onPress) {
|
|
111
|
+
cloneProps.onPress = composeEventHandlers(childOnPress, onPress);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<ListItemProvider
|
|
116
|
+
value={{
|
|
117
|
+
isPressed: false,
|
|
118
|
+
isHovered: false,
|
|
119
|
+
isDisabled: resolvedDisabled,
|
|
120
|
+
crossAlign: crossAlign ?? 'center',
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
{React.cloneElement(child, cloneProps)}
|
|
124
|
+
</ListItemProvider>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (isPressableRoot) {
|
|
129
|
+
const interactionAttrs = dataAttributes({
|
|
130
|
+
active: isPressed,
|
|
131
|
+
hover: isHovered,
|
|
132
|
+
disabled,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const {
|
|
136
|
+
onPressIn: onPressInProp,
|
|
137
|
+
onPressOut: onPressOutProp,
|
|
138
|
+
onHoverIn: onHoverInProp,
|
|
139
|
+
onHoverOut: onHoverOutProp,
|
|
140
|
+
} = restProps as IListItemPressablePassthrough;
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<ListItemProvider value={contextValue}>
|
|
144
|
+
<BasePressable
|
|
145
|
+
{...(restProps as P)}
|
|
146
|
+
{...slotAttrs}
|
|
147
|
+
{...interactionAttrs}
|
|
148
|
+
{...(disabled && { accessibilityState: { disabled: true } })}
|
|
149
|
+
disabled={disabled}
|
|
150
|
+
ref={ref as React.Ref<P>}
|
|
151
|
+
style={[rowStyleForCrossAlign(crossAlign), style]}
|
|
152
|
+
onPress={disabled ? undefined : onPress}
|
|
153
|
+
onPressIn={composeEventHandlers(onPressInProp, pressProps.onPressIn)}
|
|
154
|
+
onPressOut={composeEventHandlers(onPressOutProp, pressProps.onPressOut)}
|
|
155
|
+
onHoverIn={composeEventHandlers(onHoverInProp, hoverProps.onHoverIn)}
|
|
156
|
+
onHoverOut={composeEventHandlers(onHoverOutProp, hoverProps.onHoverOut)}
|
|
157
|
+
>
|
|
158
|
+
{children}
|
|
159
|
+
</BasePressable>
|
|
160
|
+
</ListItemProvider>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<ListItemProvider value={contextValue}>
|
|
166
|
+
<BaseView
|
|
167
|
+
{...(restProps as V)}
|
|
168
|
+
{...slotAttrs}
|
|
169
|
+
{...(disabled ? dataAttributes({ disabled: true }) : undefined)}
|
|
170
|
+
ref={ref as React.Ref<V>}
|
|
171
|
+
style={[rowStyleForCrossAlign(crossAlign), style]}
|
|
172
|
+
>
|
|
173
|
+
{children}
|
|
174
|
+
</BaseView>
|
|
175
|
+
</ListItemProvider>
|
|
176
|
+
);
|
|
177
|
+
},
|
|
178
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
4
|
+
import type { IListItemSectionHeaderProps } from './types';
|
|
5
|
+
|
|
6
|
+
const row = {
|
|
7
|
+
flexDirection: 'row' as const,
|
|
8
|
+
alignItems: 'center' as const,
|
|
9
|
+
justifyContent: 'space-between' as const,
|
|
10
|
+
gap: 8,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const labelCell = {
|
|
14
|
+
flex: 1,
|
|
15
|
+
minWidth: 0,
|
|
16
|
+
/** Keeps the label column from stretching to a taller trailing sibling (e.g. Chip). */
|
|
17
|
+
alignSelf: 'center' as const,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const trailingCell = {
|
|
21
|
+
flexShrink: 0,
|
|
22
|
+
/** Prevents the trailing slot from stretching vertically and “filling” the row. */
|
|
23
|
+
alignSelf: 'center' as const,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const createListItemSectionHeader = <T,>(Base: React.ComponentType<T>) =>
|
|
27
|
+
forwardRef(
|
|
28
|
+
(
|
|
29
|
+
{
|
|
30
|
+
children,
|
|
31
|
+
trailing,
|
|
32
|
+
showDivider = true,
|
|
33
|
+
style,
|
|
34
|
+
accessibilityRole = 'header',
|
|
35
|
+
...props
|
|
36
|
+
}: IListItemSectionHeaderProps,
|
|
37
|
+
ref: React.Ref<unknown>,
|
|
38
|
+
) => (
|
|
39
|
+
<Base
|
|
40
|
+
{...(props as T)}
|
|
41
|
+
{...dataAttributes({
|
|
42
|
+
slot: 'list-section-header',
|
|
43
|
+
divider: showDivider,
|
|
44
|
+
})}
|
|
45
|
+
accessibilityRole={accessibilityRole}
|
|
46
|
+
ref={ref as React.Ref<T>}
|
|
47
|
+
style={[row, style]}
|
|
48
|
+
>
|
|
49
|
+
<View style={labelCell}>{children}</View>
|
|
50
|
+
{trailing ? <View style={trailingCell}>{trailing}</View> : null}
|
|
51
|
+
</Base>
|
|
52
|
+
),
|
|
53
|
+
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemTitleProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const createListItemTitle = <T,>(Base: React.ComponentType<T>) =>
|
|
6
|
+
forwardRef(({ children, style, ...props }: IListItemTitleProps, ref: React.Ref<unknown>) => (
|
|
7
|
+
<Base
|
|
8
|
+
{...(props as T)}
|
|
9
|
+
{...dataAttributes({
|
|
10
|
+
slot: 'list-item-title',
|
|
11
|
+
})}
|
|
12
|
+
ref={ref as React.Ref<T>}
|
|
13
|
+
style={style}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</Base>
|
|
17
|
+
));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
3
|
+
import type { IListItemTrailingSlotProps } from './types';
|
|
4
|
+
|
|
5
|
+
const shrinkZero = { flexShrink: 0 as const };
|
|
6
|
+
|
|
7
|
+
export const createListItemTrailingSlot = <T,>(Base: React.ComponentType<T>) =>
|
|
8
|
+
forwardRef(
|
|
9
|
+
({ children, style, ...props }: IListItemTrailingSlotProps, ref: React.Ref<unknown>) => (
|
|
10
|
+
<Base
|
|
11
|
+
{...(props as T)}
|
|
12
|
+
{...dataAttributes({
|
|
13
|
+
slot: 'list-item-trailing',
|
|
14
|
+
})}
|
|
15
|
+
ref={ref as React.Ref<T>}
|
|
16
|
+
style={[shrinkZero, style]}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</Base>
|
|
20
|
+
),
|
|
21
|
+
);
|