@yamada-ui/native-select
Version:
Yamada UI native select component
1 lines • 10.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/native-select.tsx"],"sourcesContent":["import type { CSSUIObject, FC, HTMLUIProps, ThemeProps } from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type {\n DetailedHTMLProps,\n OptionHTMLAttributes,\n ReactElement,\n} from \"react\"\nimport {\n forwardRef,\n layoutStyleProperties,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { ChevronIcon } from \"@yamada-ui/icon\"\nimport {\n createContext,\n cx,\n getValidChildren,\n isValidElement,\n omitObject,\n pickObject,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { cloneElement } from \"react\"\n\ninterface NativeSelectBaseItem\n extends Omit<\n DetailedHTMLProps<\n OptionHTMLAttributes<HTMLOptionElement>,\n HTMLOptionElement\n >,\n \"children\" | \"label\" | \"value\"\n > {\n label?: string\n}\n\ntype Value = DetailedHTMLProps<\n OptionHTMLAttributes<HTMLOptionElement>,\n HTMLOptionElement\n>[\"value\"]\n\ninterface NativeSelectItemWithValue extends NativeSelectBaseItem {\n value?: Value\n}\n\ninterface NativeSelectItemWithItems extends NativeSelectBaseItem {\n items?: NativeSelectItemWithValue[]\n}\n\nexport interface NativeSelectItem\n extends NativeSelectItemWithValue,\n NativeSelectItemWithItems {}\n\ninterface NativeSelectContext {\n [key: string]: CSSUIObject | undefined\n}\n\nconst [NativeSelectProvider, useNativeSelect] =\n createContext<NativeSelectContext>({\n name: \"NativeSelectContext\",\n errorMessage: `useNativeSelect returned is 'undefined'. Seems you forgot to wrap the components in \"<NativeSelect />\"`,\n })\n\ninterface NativeSelectOptions {\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: string\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: string\n /**\n * If provided, generate options based on items.\n *\n * @default '[]'\n */\n items?: NativeSelectItem[]\n /**\n * The placeholder for select.\n */\n placeholder?: string\n /**\n * If `true`, include placeholders in options.\n *\n * @default true\n */\n placeholderInOptions?: boolean\n /**\n * Props for container element.\n */\n containerProps?: Omit<HTMLUIProps, \"children\">\n /**\n * Props for icon element.\n */\n iconProps?: HTMLUIProps\n}\n\nexport interface NativeSelectProps\n extends Omit<HTMLUIProps<\"select\">, \"size\">,\n ThemeProps<\"NativeSelect\">,\n NativeSelectOptions,\n FormControlOptions {}\n\n/**\n * `NativeSelect` is a component used for allowing users to select one option from a list. It displays a native dropdown list provided by the browser (user agent).\n *\n * @see Docs https://yamada-ui.com/components/forms/native-select\n */\nexport const NativeSelect = forwardRef<NativeSelectProps, \"select\">(\n (props, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"NativeSelect\", props)\n const {\n className,\n children,\n color,\n items = [],\n placeholder,\n placeholderInOptions = true,\n containerProps,\n iconProps,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const {\n \"aria-readonly\": _ariaReadonly,\n onBlur: _onBlur,\n onFocus: _onFocus,\n ...formControlProps\n } = pickObject(rest, formControlProperties)\n const [{ h, height, minH, minHeight, ...layoutProps }, selectProps] =\n splitObject(omitObject(rest, [\"aria-readonly\"]), layoutStyleProperties)\n\n let computedChildren: ReactElement[] = []\n\n if (!children && items.length) {\n computedChildren = items\n .map((item, i) => {\n if (\"value\" in item) {\n const { label, value, ...props } = item\n\n return (\n <NativeOption key={i} value={value} {...props}>\n {label}\n </NativeOption>\n )\n } else if (\"items\" in item) {\n const { items = [], label, ...props } = item\n\n return (\n <NativeOptionGroup key={i} label={label} {...props}>\n {items.map(({ label, value, ...props }, i) => (\n <NativeOption key={i} value={value} {...props}>\n {label}\n </NativeOption>\n ))}\n </NativeOptionGroup>\n )\n }\n })\n .filter(Boolean) as ReactElement[]\n }\n\n return (\n <NativeSelectProvider value={styles}>\n <ui.div\n className=\"ui-select\"\n __css={{\n color,\n h: \"fit-content\",\n position: \"relative\",\n w: \"100%\",\n ...styles.container,\n }}\n {...layoutProps}\n {...containerProps}\n {...formControlProps}\n >\n <ui.select\n ref={ref}\n className={cx(\"ui-select__field\", className)}\n __css={{\n h: h ?? height,\n minH: minH ?? minHeight,\n pe: \"2rem\",\n ...styles.field,\n }}\n {...selectProps}\n >\n {placeholder ? (\n <NativeOption hidden={!placeholderInOptions} value=\"\">\n {placeholder}\n </NativeOption>\n ) : null}\n {children ?? computedChildren}\n </ui.select>\n\n <NativeSelectIcon {...iconProps} {...formControlProps} />\n </ui.div>\n </NativeSelectProvider>\n )\n },\n)\n\nNativeSelect.displayName = \"NativeSelect\"\nNativeSelect.__ui__ = \"NativeSelect\"\n\ninterface NativeSelectIconProps extends HTMLUIProps {}\n\nconst NativeSelectIcon: FC<NativeSelectIconProps> = ({\n className,\n children,\n ...rest\n}) => {\n const styles = useNativeSelect()\n\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"inline-flex\",\n justifyContent: \"center\",\n pointerEvents: \"none\",\n position: \"absolute\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n ...styles.icon,\n }\n\n const validChildren = getValidChildren(children)\n\n const cloneChildren = validChildren.map((child) =>\n cloneElement(child, {\n style: {\n color: \"currentColor\",\n height: \"1em\",\n width: \"1em\",\n },\n \"aria-hidden\": true,\n focusable: false,\n }),\n )\n\n return (\n <ui.div className={cx(\"ui-select__icon\", className)} __css={css} {...rest}>\n {isValidElement(children) ? cloneChildren : <ChevronIcon />}\n </ui.div>\n )\n}\n\nNativeSelectIcon.displayName = \"NativeSelectIcon\"\nNativeSelectIcon.__ui__ = \"NativeSelectIcon\"\n\nexport interface NativeOptionGroupProps extends HTMLUIProps<\"optgroup\"> {}\n\nexport const NativeOptionGroup = forwardRef<NativeOptionGroupProps, \"optgroup\">(\n (props, ref) => <ui.optgroup ref={ref} {...props} />,\n)\n\nNativeOptionGroup.displayName = \"NativeOptionGroup\"\nNativeOptionGroup.__ui__ = \"NativeOptionGroup\"\n\nexport interface NativeOptionProps\n extends Omit<HTMLUIProps<\"option\">, \"children\"> {\n children?: string\n}\n\nexport const NativeOption = forwardRef<NativeOptionProps, \"option\">(\n (props, ref) => <ui.option ref={ref} {...props} />,\n)\n\nNativeOption.displayName = \"NativeOption\"\nNativeOption.__ui__ = \"NativeOption\"\n"],"mappings":"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","names":["props","items","label","i"]}