@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
1 lines • 11.4 kB
Source Map (JSON)
{"version":3,"file":"SegmentedControl.cjs","names":["createVarsResolver","getRadius","getThemeColor","getSize","getFontSize","genericFactory","useProps","useStyles","useMantineTheme","isPrimitive","Box","getContrastColor","FloatingIndicator","classes"],"sources":["../../../src/components/SegmentedControl/SegmentedControl.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n randomId,\n useId,\n useMergedRef,\n useMounted,\n useShallowEffect,\n useUncontrolled,\n} from '@mantine/hooks';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n Factory,\n genericFactory,\n getContrastColor,\n getFontSize,\n getRadius,\n getSize,\n getThemeColor,\n isPrimitive,\n MantineColor,\n MantineRadius,\n MantineSize,\n Primitive,\n StylesApiProps,\n useMantineTheme,\n useProps,\n useStyles,\n} from '../../core';\nimport { FloatingIndicator } from '../FloatingIndicator';\nimport classes from './SegmentedControl.module.css';\n\nexport type SegmentedControlStylesNames =\n | 'root'\n | 'input'\n | 'label'\n | 'control'\n | 'indicator'\n | 'innerLabel';\nexport type SegmentedControlCssVariables = {\n root:\n | '--sc-radius'\n | '--sc-color'\n | '--sc-font-size'\n | '--sc-padding'\n | '--sc-shadow'\n | '--sc-transition-duration'\n | '--sc-transition-timing-function';\n};\n\nexport interface SegmentedControlItem<Value = string> {\n value: Value;\n label: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps<Value extends Primitive = string>\n extends\n BoxProps,\n StylesApiProps<SegmentedControlFactory>,\n ElementProps<'div', 'onChange' | 'value' | 'defaultValue'> {\n /** Data based on which controls are rendered */\n data: (Value | SegmentedControlItem<Value>)[];\n\n /** Controlled component value */\n value?: Value;\n\n /** Uncontrolled component default value */\n defaultValue?: Value;\n\n /** Called when value changes */\n onChange?: (value: Value) => void;\n\n /** Determines whether the component is disabled */\n disabled?: boolean;\n\n /** Name attribute for the radio group. A random name is auto-generated if not provided */\n name?: string;\n\n /** Determines whether the component should take 100% width of its parent @default false */\n fullWidth?: boolean;\n\n /** Key of `theme.colors` or any valid CSS color, changes indicator background color. By default, uses white in light mode and dark.5 in dark mode */\n color?: MantineColor;\n\n /** Controls `font-size`, `padding` and `height` properties @default 'sm' */\n size?: MantineSize | (string & {});\n\n /** Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** Indicator `transition-duration` in ms, set `0` to turn off transitions @default 200 */\n transitionDuration?: number;\n\n /** Indicator `transition-timing-function` property @default ease */\n transitionTimingFunction?: string;\n\n /** Component orientation @default 'horizontal' */\n orientation?: 'vertical' | 'horizontal';\n\n /** If set to `false`, prevents changing the value */\n readOnly?: boolean;\n\n /** If set, automatically adjusts label text color for optimal contrast against the indicator background color */\n autoContrast?: boolean;\n\n /** Determines whether there should be borders between items @default true */\n withItemsBorders?: boolean;\n}\n\nexport type SegmentedControlFactory = Factory<{\n props: SegmentedControlProps;\n ref: HTMLDivElement;\n stylesNames: SegmentedControlStylesNames;\n vars: SegmentedControlCssVariables;\n signature: <Value extends Primitive = string>(\n props: SegmentedControlProps<Value>\n ) => React.JSX.Element | null;\n}>;\n\nconst defaultProps = {\n withItemsBorders: true,\n} satisfies Partial<SegmentedControlProps>;\n\nconst varsResolver = createVarsResolver<SegmentedControlFactory>(\n (theme, { radius, color, transitionDuration, size, transitionTimingFunction }) => ({\n root: {\n '--sc-radius': radius === undefined ? undefined : getRadius(radius),\n '--sc-color': color ? getThemeColor(color, theme) : undefined,\n '--sc-shadow': color ? undefined : 'var(--mantine-shadow-xs)',\n '--sc-transition-duration':\n transitionDuration === undefined ? undefined : `${transitionDuration}ms`,\n '--sc-transition-timing-function': transitionTimingFunction,\n '--sc-padding': getSize(size, 'sc-padding'),\n '--sc-font-size': getFontSize(size),\n },\n })\n);\n\nexport const SegmentedControl = genericFactory<SegmentedControlFactory>((_props) => {\n const props = useProps('SegmentedControl', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n value,\n defaultValue,\n onChange,\n size,\n name,\n disabled,\n readOnly,\n fullWidth,\n orientation,\n radius,\n color,\n transitionDuration,\n transitionTimingFunction,\n variant,\n autoContrast,\n withItemsBorders,\n mod,\n attributes,\n ref,\n ...others\n } = props;\n\n const getStyles = useStyles<SegmentedControlFactory>({\n name: 'SegmentedControl',\n props: props as any,\n classes,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const theme = useMantineTheme();\n\n const _data = data.map((item) => (isPrimitive(item) ? { label: `${item}`, value: item } : item));\n\n const initialized = useMounted();\n const [key, setKey] = useState(randomId());\n const [parent, setParent] = useState<HTMLElement | null>(null);\n const [refs, setRefs] = useState<Record<string, HTMLElement | null>>({});\n const setElementRef = (element: HTMLElement | null, val: string) => {\n refs[val] = element;\n setRefs(refs);\n };\n\n const [_value, handleValueChange] = useUncontrolled({\n value,\n defaultValue,\n finalValue: Array.isArray(data)\n ? (_data.find((item) => !item.disabled)?.value ?? (data[0] as any)?.value ?? null)\n : null,\n onChange,\n });\n\n const uuid = useId(name);\n\n const controls = _data.map((item) => (\n <Box\n {...getStyles('control')}\n mod={{ active: _value === item.value, orientation }}\n key={`${item.value}`}\n >\n <input\n {...getStyles('input')}\n disabled={disabled || item.disabled}\n type=\"radio\"\n name={uuid}\n value={`${item.value}`}\n id={`${uuid}-${item.value}`}\n checked={_value === item.value}\n onChange={() => !readOnly && handleValueChange(item.value)}\n data-focus-ring={theme.focusRing}\n key={`${item.value}-input`}\n />\n\n <Box\n component=\"label\"\n {...getStyles('label')}\n mod={{\n active: _value === item.value && !(disabled || item.disabled),\n disabled: disabled || item.disabled,\n 'read-only': readOnly,\n }}\n htmlFor={`${uuid}-${item.value}`}\n ref={(node) => setElementRef(node, `${item.value}`)}\n __vars={{\n '--sc-label-color':\n color !== undefined ? getContrastColor({ color, theme, autoContrast }) : undefined,\n }}\n key={`${item.value}-label`}\n >\n <span {...getStyles('innerLabel')}>{item.label}</span>\n </Box>\n </Box>\n ));\n\n const mergedRef = useMergedRef(ref, (node) => setParent(node));\n\n useShallowEffect(() => {\n setKey(randomId());\n }, [data.length]);\n\n if (data.length === 0) {\n return null;\n }\n\n return (\n <Box\n {...getStyles('root')}\n variant={variant}\n size={size}\n ref={mergedRef}\n mod={[\n {\n 'full-width': fullWidth,\n orientation,\n initialized,\n 'with-items-borders': withItemsBorders,\n },\n mod,\n ]}\n {...others}\n role=\"radiogroup\"\n data-disabled={disabled}\n >\n {typeof _value !== 'undefined' && (\n <FloatingIndicator\n target={refs[`${_value}`]}\n parent={parent}\n component=\"span\"\n transitionDuration=\"var(--sc-transition-duration)\"\n key={key}\n {...getStyles('indicator')}\n />\n )}\n\n {controls}\n </Box>\n );\n});\n\nSegmentedControl.classes = classes;\nSegmentedControl.varsResolver = varsResolver;\nSegmentedControl.displayName = '@mantine/core/SegmentedControl';\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0HA,MAAM,eAAe,EACnB,kBAAkB,MACnB;AAED,MAAM,eAAeA,6BAAAA,oBAClB,OAAO,EAAE,QAAQ,OAAO,oBAAoB,MAAM,gCAAgC,EACjF,MAAM;CACJ,eAAe,WAAW,KAAA,IAAY,KAAA,IAAYC,iBAAAA,UAAU,OAAO;CACnE,cAAc,QAAQC,wBAAAA,cAAc,OAAO,MAAM,GAAG,KAAA;CACpD,eAAe,QAAQ,KAAA,IAAY;CACnC,4BACE,uBAAuB,KAAA,IAAY,KAAA,IAAY,GAAG,mBAAmB;CACvE,mCAAmC;CACnC,gBAAgBC,iBAAAA,QAAQ,MAAM,aAAa;CAC3C,kBAAkBC,iBAAAA,YAAY,KAAK;CACpC,EACF,EACF;AAED,MAAa,mBAAmBC,gBAAAA,gBAAyC,WAAW;CAClF,MAAM,QAAQC,kBAAAA,SAAS,oBAAoB,cAAc,OAAO;CAChE,MAAM,EACJ,YACA,WACA,OACA,QACA,UACA,MACA,MACA,OACA,cACA,UACA,MACA,MACA,UACA,UACA,WACA,aACA,QACA,OACA,oBACA,0BACA,SACA,cACA,kBACA,KACA,YACA,KACA,GAAG,WACD;CAEJ,MAAM,YAAYC,mBAAAA,UAAmC;EACnD,MAAM;EACC;EACP,SAAA,gCAAA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,MAAM,QAAQC,6BAAAA,iBAAiB;CAE/B,MAAM,QAAQ,KAAK,KAAK,SAAUC,kBAAAA,YAAY,KAAK,GAAG;EAAE,OAAO,GAAG;EAAQ,OAAO;EAAM,GAAG,KAAM;CAEhG,MAAM,eAAA,GAAA,eAAA,aAA0B;CAChC,MAAM,CAAC,KAAK,WAAA,GAAA,MAAA,WAAA,GAAA,eAAA,WAA6B,CAAC;CAC1C,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,UAA0C,KAAK;CAC9D,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAwD,EAAE,CAAC;CACxE,MAAM,iBAAiB,SAA6B,QAAgB;AAClE,OAAK,OAAO;AACZ,UAAQ,KAAK;;CAGf,MAAM,CAAC,QAAQ,sBAAA,GAAA,eAAA,iBAAqC;EAClD;EACA;EACA,YAAY,MAAM,QAAQ,KAAK,GAC1B,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,EAAE,SAAU,KAAK,IAAY,SAAS,OAC3E;EACJ;EACD,CAAC;CAEF,MAAM,QAAA,GAAA,eAAA,OAAa,KAAK;CAExB,MAAM,WAAW,MAAM,KAAK,SAC1B,iBAAA,GAAA,MAAA,eAACC,YAAAA,KAAD;EACE,GAAI,UAAU,UAAU;EACxB,KAAK;GAAE,QAAQ,WAAW,KAAK;GAAO;GAAa;EACnD,KAAK,GAAG,KAAK;EAiCT,EA/BJ,iBAAA,GAAA,MAAA,eAAC,SAAD;EACE,GAAI,UAAU,QAAQ;EACtB,UAAU,YAAY,KAAK;EAC3B,MAAK;EACL,MAAM;EACN,OAAO,GAAG,KAAK;EACf,IAAI,GAAG,KAAK,GAAG,KAAK;EACpB,SAAS,WAAW,KAAK;EACzB,gBAAgB,CAAC,YAAY,kBAAkB,KAAK,MAAM;EAC1D,mBAAiB,MAAM;EACvB,KAAK,GAAG,KAAK,MAAM;EACnB,CAAA,EAEF,iBAAA,GAAA,MAAA,eAACA,YAAAA,KAAD;EACE,WAAU;EACV,GAAI,UAAU,QAAQ;EACtB,KAAK;GACH,QAAQ,WAAW,KAAK,SAAS,EAAE,YAAY,KAAK;GACpD,UAAU,YAAY,KAAK;GAC3B,aAAa;GACd;EACD,SAAS,GAAG,KAAK,GAAG,KAAK;EACzB,MAAM,SAAS,cAAc,MAAM,GAAG,KAAK,QAAQ;EACnD,QAAQ,EACN,oBACE,UAAU,KAAA,IAAYC,2BAAAA,iBAAiB;GAAE;GAAO;GAAO;GAAc,CAAC,GAAG,KAAA,GAC5E;EACD,KAAK,GAAG,KAAK,MAAM;EAGf,EADJ,iBAAA,GAAA,kBAAA,KAAC,QAAD;EAAM,GAAI,UAAU,aAAa;YAAG,KAAK;EAAa,CAAA,CAClD,CACF,CACN;CAEF,MAAM,aAAA,GAAA,eAAA,cAAyB,MAAM,SAAS,UAAU,KAAK,CAAC;AAE9D,EAAA,GAAA,eAAA,wBAAuB;AACrB,UAAA,GAAA,eAAA,WAAiB,CAAC;IACjB,CAAC,KAAK,OAAO,CAAC;AAEjB,KAAI,KAAK,WAAW,EAClB,QAAO;AAGT,QACE,iBAAA,GAAA,kBAAA,MAACD,YAAAA,KAAD;EACE,GAAI,UAAU,OAAO;EACZ;EACH;EACN,KAAK;EACL,KAAK,CACH;GACE,cAAc;GACd;GACA;GACA,sBAAsB;GACvB,EACD,IACD;EACD,GAAI;EACJ,MAAK;EACL,iBAAe;YAhBjB,CAkBG,OAAO,WAAW,eACjB,iBAAA,GAAA,kBAAA,KAACE,0BAAAA,mBAAD;GACE,QAAQ,KAAK,GAAG;GACR;GACR,WAAU;GACV,oBAAmB;GAEnB,GAAI,UAAU,YAAY;GAC1B,EAFK,IAEL,EAGH,SACG;;EAER;AAEF,iBAAiB,UAAUC,gCAAAA;AAC3B,iBAAiB,eAAe;AAChC,iBAAiB,cAAc"}