diff --git a/README.md b/README.md
index eb0f265..a42a09e 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,7 @@ the main Picker container component.
| height | 216 | `number`
Height of the picker in `px` |
| itemHeight | 36 | `number`
Height of each item (that is each option) in `px` |
| wheelMode | `'off'` | `'off' \| 'natural' \| 'normal'`
Enable wheel scrolling on desktop browsers |
+| showDivider | `true` | `boolean`
Whether to show the center divider lines |
### Picker.Column
diff --git a/lib/components/Picker.tsx b/lib/components/Picker.tsx
index 56c4b19..a19cae8 100644
--- a/lib/components/Picker.tsx
+++ b/lib/components/Picker.tsx
@@ -1,107 +1,126 @@
-import { CSSProperties, HTMLProps, MutableRefObject, createContext, useCallback, useContext, useMemo, useReducer } from 'react'
-
-const DEFAULT_HEIGHT = 216
-const DEFAULT_ITEM_HEIGHT = 36
-const DEFAULT_WHEEL_MODE = 'off'
+import {
+ CSSProperties,
+ HTMLProps,
+ MutableRefObject,
+ createContext,
+ useCallback,
+ useContext,
+ useMemo,
+ useReducer,
+} from "react";
+
+const DEFAULT_HEIGHT = 216;
+const DEFAULT_ITEM_HEIGHT = 36;
+const DEFAULT_WHEEL_MODE = "off";
interface Option {
- value: string | number
- element: MutableRefObject
+ value: string | number;
+ element: MutableRefObject;
}
export interface PickerValue {
- [key: string]: string | number
+ [key: string]: string | number;
}
-export interface PickerRootProps extends Omit, 'value' | 'onChange'> {
- value: TType
- onChange: (value: TType, key: string) => void
- height?: number
- itemHeight?: number
- wheelMode?: 'off' | 'natural' | 'normal'
+export interface PickerRootProps
+ extends Omit, "value" | "onChange"> {
+ value: TType;
+ onChange: (value: TType, key: string) => void;
+ height?: number;
+ itemHeight?: number;
+ wheelMode?: "off" | "natural" | "normal";
+ showDivider?: boolean;
}
const PickerDataContext = createContext<{
- height: number
- itemHeight: number
- wheelMode: 'off' | 'natural' | 'normal'
- value: PickerValue
- optionGroups: { [key: string]: Option[] }
-} | null>(null)
-PickerDataContext.displayName = 'PickerDataContext'
+ height: number;
+ itemHeight: number;
+ wheelMode: "off" | "natural" | "normal";
+ value: PickerValue;
+ optionGroups: { [key: string]: Option[] };
+} | null>(null);
+PickerDataContext.displayName = "PickerDataContext";
export function usePickerData(componentName: string) {
- const context = useContext(PickerDataContext)
+ const context = useContext(PickerDataContext);
if (context === null) {
- const error = new Error(`<${componentName} /> is missing a parent component.`)
+ const error = new Error(
+ `<${componentName} /> is missing a parent component.`
+ );
if (Error.captureStackTrace) {
- Error.captureStackTrace(error, usePickerData)
+ Error.captureStackTrace(error, usePickerData);
}
- throw error
+ throw error;
}
- return context
+ return context;
}
const PickerActionsContext = createContext<{
- registerOption(key: string, option: Option): () => void
- change(key: string, value: string | number): boolean
-} | null>(null)
-PickerActionsContext.displayName = 'PickerActionsContext'
+ registerOption(key: string, option: Option): () => void;
+ change(key: string, value: string | number): boolean;
+} | null>(null);
+PickerActionsContext.displayName = "PickerActionsContext";
export function usePickerActions(componentName: string) {
- const context = useContext(PickerActionsContext)
+ const context = useContext(PickerActionsContext);
if (context === null) {
- const error = new Error(`<${componentName} /> is missing a parent component.`)
+ const error = new Error(
+ `<${componentName} /> is missing a parent component.`
+ );
if (Error.captureStackTrace) {
- Error.captureStackTrace(error, usePickerActions)
+ Error.captureStackTrace(error, usePickerActions);
}
- throw error
+ throw error;
}
- return context
+ return context;
}
function sortByDomNode(
nodes: T[],
- resolveKey: (item: T) => HTMLElement | null = (i) => i as unknown as HTMLElement | null
+ resolveKey: (item: T) => HTMLElement | null = (i) =>
+ i as unknown as HTMLElement | null
): T[] {
return nodes.slice().sort((aItem, zItem) => {
- const a = resolveKey(aItem)
- const z = resolveKey(zItem)
+ const a = resolveKey(aItem);
+ const z = resolveKey(zItem);
- if (a === null || z === null) return 0
+ if (a === null || z === null) return 0;
- const position = a.compareDocumentPosition(z)
+ const position = a.compareDocumentPosition(z);
- if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1
- if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1
- return 0
- })
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
+ return 0;
+ });
}
function pickerReducer(
optionGroups: { [key: string]: Option[] },
action: {
- type: 'REGISTER_OPTION' | 'UNREGISTER_OPTION'
- key: string
- option: Option
+ type: "REGISTER_OPTION" | "UNREGISTER_OPTION";
+ key: string;
+ option: Option;
}
) {
switch (action.type) {
- case 'REGISTER_OPTION': {
- const { key, option } = action
- let nextOptionsForKey = [...(optionGroups[key] || []), option]
- nextOptionsForKey = sortByDomNode(nextOptionsForKey, (o) => o.element.current)
+ case "REGISTER_OPTION": {
+ const { key, option } = action;
+ let nextOptionsForKey = [...(optionGroups[key] || []), option];
+ nextOptionsForKey = sortByDomNode(
+ nextOptionsForKey,
+ (o) => o.element.current
+ );
return {
...optionGroups,
[key]: nextOptionsForKey,
- }
+ };
}
- case 'UNREGISTER_OPTION': {
- const { key, option } = action
+ case "UNREGISTER_OPTION": {
+ const { key, option } = action;
return {
...optionGroups,
[key]: (optionGroups[key] || []).filter((o) => o !== option),
- }
+ };
}
default: {
throw Error(`Unknown action: ${action.type as string}`);
@@ -118,55 +137,61 @@ function PickerRoot(props: PickerRootProps) {
height = DEFAULT_HEIGHT,
itemHeight = DEFAULT_ITEM_HEIGHT,
wheelMode = DEFAULT_WHEEL_MODE,
+ showDivider = true,
...restProps
- } = props
+ } = props;
const highlightStyle = useMemo(
() => ({
height: itemHeight,
marginTop: -(itemHeight / 2),
- position: 'absolute',
- top: '50%',
+ position: "absolute",
+ top: "50%",
left: 0,
- width: '100%',
- pointerEvents: 'none',
+ width: "100%",
+ pointerEvents: "none",
}),
[itemHeight]
- )
+ );
const containerStyle = useMemo(
() => ({
height: `${height}px`,
- position: 'relative',
- display: 'flex',
- justifyContent: 'center',
- overflow: 'hidden',
- maskImage: 'linear-gradient(to top, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent)',
- WebkitMaskImage: 'linear-gradient(to top, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent)',
+ position: "relative",
+ display: "flex",
+ justifyContent: "center",
+ overflow: "hidden",
+ maskImage:
+ "linear-gradient(to top, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent)",
+ WebkitMaskImage:
+ "linear-gradient(to top, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent)",
}),
[height]
- )
+ );
- const [optionGroups, dispatch] = useReducer(pickerReducer, {})
+ const [optionGroups, dispatch] = useReducer(pickerReducer, {});
const pickerData = useMemo(
() => ({ height, itemHeight, wheelMode, value, optionGroups }),
[height, itemHeight, value, optionGroups, wheelMode]
- )
-
- const triggerChange = useCallback((key: string, nextValue: string) => {
- if (value[key] === nextValue) return false
- const nextPickerValue = { ...value, [key]: nextValue }
- onChange(nextPickerValue, key)
- return true
- }, [onChange, value])
+ );
+
+ const triggerChange = useCallback(
+ (key: string, nextValue: string) => {
+ if (value[key] === nextValue) return false;
+ const nextPickerValue = { ...value, [key]: nextValue };
+ onChange(nextPickerValue, key);
+ return true;
+ },
+ [onChange, value]
+ );
const registerOption = useCallback((key: string, option: Option) => {
- dispatch({ type: 'REGISTER_OPTION', key, option })
- return () => dispatch({ type: 'UNREGISTER_OPTION', key, option })
- }, [])
+ dispatch({ type: "REGISTER_OPTION", key, option });
+ return () => dispatch({ type: "UNREGISTER_OPTION", key, option });
+ }, []);
const pickerActions = useMemo(
() => ({ registerOption, change: triggerChange }),
[registerOption, triggerChange]
- )
+ );
return (
(props: PickerRootProps
) {
{children}
-
+ {showDivider && (
+
+ )}
- )
+ );
}
-export default PickerRoot
+export default PickerRoot;