@metamask/design-system-react-native 0.35.0 → 0.36.0

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.
Files changed (106) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/dist/components/BannerBase/BannerBase.cjs +8 -6
  3. package/dist/components/BannerBase/BannerBase.cjs.map +1 -1
  4. package/dist/components/BannerBase/BannerBase.d.cts.map +1 -1
  5. package/dist/components/BannerBase/BannerBase.d.mts.map +1 -1
  6. package/dist/components/BannerBase/BannerBase.mjs +9 -7
  7. package/dist/components/BannerBase/BannerBase.mjs.map +1 -1
  8. package/dist/components/BannerBase/index.cjs +3 -1
  9. package/dist/components/BannerBase/index.cjs.map +1 -1
  10. package/dist/components/BannerBase/index.d.cts +1 -0
  11. package/dist/components/BannerBase/index.d.cts.map +1 -1
  12. package/dist/components/BannerBase/index.d.mts +1 -0
  13. package/dist/components/BannerBase/index.d.mts.map +1 -1
  14. package/dist/components/BannerBase/index.mjs +1 -0
  15. package/dist/components/BannerBase/index.mjs.map +1 -1
  16. package/dist/components/Content/Content.cjs +27 -13
  17. package/dist/components/Content/Content.cjs.map +1 -1
  18. package/dist/components/Content/Content.d.cts.map +1 -1
  19. package/dist/components/Content/Content.d.mts.map +1 -1
  20. package/dist/components/Content/Content.mjs +28 -14
  21. package/dist/components/Content/Content.mjs.map +1 -1
  22. package/dist/components/Content/index.cjs +3 -3
  23. package/dist/components/Content/index.cjs.map +1 -1
  24. package/dist/components/Content/index.d.cts +1 -1
  25. package/dist/components/Content/index.d.cts.map +1 -1
  26. package/dist/components/Content/index.d.mts +1 -1
  27. package/dist/components/Content/index.d.mts.map +1 -1
  28. package/dist/components/Content/index.mjs +1 -1
  29. package/dist/components/Content/index.mjs.map +1 -1
  30. package/dist/components/ListItem/ListItem.cjs +19 -8
  31. package/dist/components/ListItem/ListItem.cjs.map +1 -1
  32. package/dist/components/ListItem/ListItem.d.cts.map +1 -1
  33. package/dist/components/ListItem/ListItem.d.mts.map +1 -1
  34. package/dist/components/ListItem/ListItem.mjs +20 -9
  35. package/dist/components/ListItem/ListItem.mjs.map +1 -1
  36. package/dist/components/ListItem/index.cjs +3 -3
  37. package/dist/components/ListItem/index.cjs.map +1 -1
  38. package/dist/components/ListItem/index.d.cts +1 -1
  39. package/dist/components/ListItem/index.d.cts.map +1 -1
  40. package/dist/components/ListItem/index.d.mts +1 -1
  41. package/dist/components/ListItem/index.d.mts.map +1 -1
  42. package/dist/components/ListItem/index.mjs +1 -1
  43. package/dist/components/ListItem/index.mjs.map +1 -1
  44. package/dist/components/Slider/Slider.cjs +26 -13
  45. package/dist/components/Slider/Slider.cjs.map +1 -1
  46. package/dist/components/Slider/Slider.constants.cjs +8 -3
  47. package/dist/components/Slider/Slider.constants.cjs.map +1 -1
  48. package/dist/components/Slider/Slider.constants.d.cts +2 -2
  49. package/dist/components/Slider/Slider.constants.d.cts.map +1 -1
  50. package/dist/components/Slider/Slider.constants.d.mts +2 -2
  51. package/dist/components/Slider/Slider.constants.d.mts.map +1 -1
  52. package/dist/components/Slider/Slider.constants.mjs +7 -2
  53. package/dist/components/Slider/Slider.constants.mjs.map +1 -1
  54. package/dist/components/Slider/Slider.d.cts +1 -1
  55. package/dist/components/Slider/Slider.d.cts.map +1 -1
  56. package/dist/components/Slider/Slider.d.mts +1 -1
  57. package/dist/components/Slider/Slider.d.mts.map +1 -1
  58. package/dist/components/Slider/Slider.mjs +31 -18
  59. package/dist/components/Slider/Slider.mjs.map +1 -1
  60. package/dist/components/Slider/Slider.types.cjs.map +1 -1
  61. package/dist/components/Slider/Slider.types.d.cts +14 -16
  62. package/dist/components/Slider/Slider.types.d.cts.map +1 -1
  63. package/dist/components/Slider/Slider.types.d.mts +14 -16
  64. package/dist/components/Slider/Slider.types.d.mts.map +1 -1
  65. package/dist/components/Slider/Slider.types.mjs.map +1 -1
  66. package/dist/components/Slider/Slider.utilities.cjs +96 -11
  67. package/dist/components/Slider/Slider.utilities.cjs.map +1 -1
  68. package/dist/components/Slider/Slider.utilities.d.cts +57 -8
  69. package/dist/components/Slider/Slider.utilities.d.cts.map +1 -1
  70. package/dist/components/Slider/Slider.utilities.d.mts +57 -8
  71. package/dist/components/Slider/Slider.utilities.d.mts.map +1 -1
  72. package/dist/components/Slider/Slider.utilities.mjs +89 -9
  73. package/dist/components/Slider/Slider.utilities.mjs.map +1 -1
  74. package/dist/components/Slider/index.cjs +4 -3
  75. package/dist/components/Slider/index.cjs.map +1 -1
  76. package/dist/components/Slider/index.d.cts +3 -1
  77. package/dist/components/Slider/index.d.cts.map +1 -1
  78. package/dist/components/Slider/index.d.mts +3 -1
  79. package/dist/components/Slider/index.d.mts.map +1 -1
  80. package/dist/components/Slider/index.mjs +2 -1
  81. package/dist/components/Slider/index.mjs.map +1 -1
  82. package/dist/components/Slider/useSliderGesture.cjs +55 -22
  83. package/dist/components/Slider/useSliderGesture.cjs.map +1 -1
  84. package/dist/components/Slider/useSliderGesture.d.cts +2 -2
  85. package/dist/components/Slider/useSliderGesture.d.cts.map +1 -1
  86. package/dist/components/Slider/useSliderGesture.d.mts +2 -2
  87. package/dist/components/Slider/useSliderGesture.d.mts.map +1 -1
  88. package/dist/components/Slider/useSliderGesture.mjs +58 -25
  89. package/dist/components/Slider/useSliderGesture.mjs.map +1 -1
  90. package/dist/components/index.cjs +8 -7
  91. package/dist/components/index.cjs.map +1 -1
  92. package/dist/components/index.d.cts +5 -5
  93. package/dist/components/index.d.cts.map +1 -1
  94. package/dist/components/index.d.mts +5 -5
  95. package/dist/components/index.d.mts.map +1 -1
  96. package/dist/components/index.mjs +4 -4
  97. package/dist/components/index.mjs.map +1 -1
  98. package/package.json +4 -4
  99. package/dist/components/Content/Content.constants.cjs +0 -9
  100. package/dist/components/Content/Content.constants.cjs.map +0 -1
  101. package/dist/components/Content/Content.constants.d.cts +0 -3
  102. package/dist/components/Content/Content.constants.d.cts.map +0 -1
  103. package/dist/components/Content/Content.constants.d.mts +0 -3
  104. package/dist/components/Content/Content.constants.d.mts.map +0 -1
  105. package/dist/components/Content/Content.constants.mjs +0 -6
  106. package/dist/components/Content/Content.constants.mjs.map +0 -1
@@ -4,21 +4,32 @@ function $importDefault(module) {
4
4
  }
5
5
  return module;
6
6
  }
7
- import { FontWeight, TextColor, TextVariant } from "@metamask/design-system-shared";
8
- import { useTailwind } from "@metamask/design-system-twrnc-preset";
9
- import $React, { useCallback } from "react";
7
+ import { FontWeight, TextColor, TextVariant, SliderMarkColor } from "@metamask/design-system-shared";
8
+ import { getThemeColors, usePureBlack, useTailwind, useTheme } from "@metamask/design-system-twrnc-preset";
9
+ import $React, { useCallback, useMemo } from "react";
10
10
  const React = $importDefault($React);
11
11
  import { Pressable } from "react-native";
12
12
  import { GestureDetector } from "react-native-gesture-handler";
13
13
  import Animated from "react-native-reanimated";
14
14
  import { Box } from "../Box/index.mjs";
15
15
  import { Text } from "../Text/index.mjs";
16
- import { DEFAULT_RANGE_LABEL_STEPS, DEFAULT_TICK_THRESHOLDS, RANGE_LABEL_TOP, SLIDER_BOTTOM_PADDING, SLIDER_TRACK_INSET, THUMB_BOTTOM_OFFSET, THUMB_LEFT_OFFSET, THUMB_SIZE, THUMB_TOP_OFFSET } from "./Slider.constants.mjs";
17
- import { clampValueToRange, defaultFormatStepLabel, getDotLeftPercent, getTrackPercentFromValue } from "./Slider.utilities.mjs";
16
+ import { DEFAULT_MARKS, RANGE_LABEL_TOP, SLIDER_BOTTOM_PADDING, SLIDER_TRACK_INSET, THUMB_BOTTOM_OFFSET, THUMB_LEFT_OFFSET, THUMB_SIZE, THUMB_TOP_OFFSET } from "./Slider.constants.mjs";
17
+ import { buildColorStops, clampValueToRange, getDotLeftPercent, getTrackPercentFromValue, hasThemedMarkColors } from "./Slider.utilities.mjs";
18
18
  import { useSliderGesture } from "./useSliderGesture.mjs";
19
- export const Slider = ({ value, onValueChange, onDragEnd, minimumValue = 0, maximumValue = 100, step = 1, isDisabled = false, testID, rangeLabelSteps = DEFAULT_RANGE_LABEL_STEPS, showRangeLabels = false, showRangeDots = false, onGrip, onTick, tickThresholds = DEFAULT_TICK_THRESHOLDS, mapValueToTrackPercent, mapTrackPercentToValue, formatStepLabel, stepToValue: stepToValueProp, trackInset = SLIDER_TRACK_INSET, twClassName, style, ...props }) => {
19
+ export const Slider = ({ value, onValueChange, onDragEnd, minimumValue = 0, maximumValue = 100, step = 1, isDisabled = false, testID, marks = DEFAULT_MARKS, showRangeLabels = false, showRangeDots = false, onGrip, onMark, mapValueToTrackPercent, mapTrackPercentToValue, trackInset = SLIDER_TRACK_INSET, twClassName, style, ...props }) => {
20
20
  const tw = useTailwind();
21
- const formatLabel = formatStepLabel ?? defaultFormatStepLabel;
21
+ const theme = useTheme();
22
+ const isPureBlack = usePureBlack();
23
+ const palette = useMemo(() => getThemeColors(theme, isPureBlack), [isPureBlack, theme]);
24
+ const themedColors = useMemo(() => {
25
+ const hasThemedColors = hasThemedMarkColors(marks);
26
+ return {
27
+ hasThemedColors,
28
+ fillColorStops: buildColorStops(marks, palette, SliderMarkColor.IconAlternative),
29
+ thumbColorStops: buildColorStops(marks, palette, SliderMarkColor.IconDefault),
30
+ };
31
+ }, [palette, marks]);
32
+ const labeledMarks = useMemo(() => marks.filter((mark) => mark.label !== undefined), [marks]);
22
33
  const { handleLayout, progressStyle, thumbStyle, gesture, handlePressStep } = useSliderGesture({
23
34
  value,
24
35
  minimumValue,
@@ -28,11 +39,13 @@ export const Slider = ({ value, onValueChange, onDragEnd, minimumValue = 0, maxi
28
39
  onValueChange,
29
40
  onDragEnd,
30
41
  onGrip,
31
- onTick,
32
- tickThresholds,
42
+ onMark,
43
+ marks,
44
+ fillColorStops: themedColors.fillColorStops,
45
+ thumbColorStops: themedColors.thumbColorStops,
46
+ hasThemedColors: themedColors.hasThemedColors,
33
47
  mapValueToTrackPercent,
34
48
  mapTrackPercentToValue,
35
- stepToValue: stepToValueProp,
36
49
  });
37
50
  const getAccessibilityText = useCallback(() => {
38
51
  const trackPercent = Math.round(getTrackPercentFromValue(value, minimumValue, maximumValue, mapValueToTrackPercent));
@@ -74,17 +87,17 @@ export const Slider = ({ value, onValueChange, onDragEnd, minimumValue = 0, maxi
74
87
  <Animated.View style={[tw.style('relative'), { height: THUMB_BOTTOM_OFFSET }]}>
75
88
  <Animated.View style={tw.style('absolute left-0 top-0 h-2 w-full rounded-full bg-border-muted')}/>
76
89
  <Animated.View style={[
77
- tw.style('absolute left-0 top-0 h-2 rounded-full bg-icon-alternative'),
90
+ tw.style('absolute left-0 top-0 h-2 rounded-full', !themedColors.hasThemedColors && 'bg-icon-alternative'),
78
91
  progressStyle,
79
92
  ]}/>
80
93
  {showRangeDots &&
81
- rangeLabelSteps.map((rangeStep) => (<Box key={`dot-${rangeStep}`} pointerEvents="none" twClassName="absolute top-0.5 h-1 w-1 rounded-full bg-text-muted" style={{
82
- left: getDotLeftPercent(rangeStep),
94
+ marks.map((mark) => (<Box key={`dot-${mark.step}`} pointerEvents="none" twClassName="absolute top-0.5 h-1 w-1 rounded-full bg-text-muted" style={{
95
+ left: getDotLeftPercent(mark.step),
83
96
  transform: [{ translateX: -2 }],
84
97
  zIndex: -2,
85
98
  }}/>))}
86
99
  <Animated.View style={[
87
- tw.style('absolute rounded-full bg-icon-default'),
100
+ tw.style('absolute rounded-full', !themedColors.hasThemedColors && 'bg-icon-default'),
88
101
  {
89
102
  width: THUMB_SIZE,
90
103
  height: THUMB_SIZE,
@@ -98,16 +111,16 @@ export const Slider = ({ value, onValueChange, onDragEnd, minimumValue = 0, maxi
98
111
  </GestureDetector>
99
112
 
100
113
  {showRangeLabels &&
101
- rangeLabelSteps.map((rangeStep) => (<Pressable key={`label-${rangeStep}`} style={[
114
+ labeledMarks.map((mark) => (<Pressable key={`label-${mark.step}`} style={[
102
115
  tw.style('absolute items-center'),
103
116
  {
104
117
  top: RANGE_LABEL_TOP,
105
- left: getDotLeftPercent(rangeStep),
118
+ left: getDotLeftPercent(mark.step),
106
119
  transform: [{ translateX: '-50%' }],
107
120
  },
108
- ]} onPress={() => handlePressStep(rangeStep)} disabled={isDisabled} accessibilityRole="button">
121
+ ]} onPress={() => handlePressStep(mark.step)} disabled={isDisabled} accessibilityRole="button">
109
122
  <Text variant={TextVariant.BodyMd} fontWeight={FontWeight.Medium} color={TextColor.TextAlternative}>
110
- {formatLabel(rangeStep)}
123
+ {mark.label}
111
124
  </Text>
112
125
  </Pressable>))}
113
126
  </Box>);
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.mjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n FontWeight,\n TextColor,\n TextVariant,\n} from '@metamask/design-system-shared';\nimport { useTailwind } from '@metamask/design-system-twrnc-preset';\nimport React, { useCallback } from 'react';\nimport { AccessibilityActionEvent, Pressable } from 'react-native';\nimport type { ViewStyle } from 'react-native';\nimport { GestureDetector } from 'react-native-gesture-handler';\nimport Animated from 'react-native-reanimated';\n\nimport { Box } from '../Box';\nimport { Text } from '../Text';\n\nimport {\n DEFAULT_RANGE_LABEL_STEPS,\n DEFAULT_TICK_THRESHOLDS,\n RANGE_LABEL_TOP,\n SLIDER_BOTTOM_PADDING,\n SLIDER_TRACK_INSET,\n THUMB_BOTTOM_OFFSET,\n THUMB_LEFT_OFFSET,\n THUMB_SIZE,\n THUMB_TOP_OFFSET,\n} from './Slider.constants';\nimport type { SliderProps } from './Slider.types';\nimport {\n clampValueToRange,\n defaultFormatStepLabel,\n getDotLeftPercent,\n getTrackPercentFromValue,\n} from './Slider.utilities';\nimport { useSliderGesture } from './useSliderGesture';\n\nexport const Slider = ({\n value,\n onValueChange,\n onDragEnd,\n minimumValue = 0,\n maximumValue = 100,\n step = 1,\n isDisabled = false,\n testID,\n rangeLabelSteps = DEFAULT_RANGE_LABEL_STEPS,\n showRangeLabels = false,\n showRangeDots = false,\n onGrip,\n onTick,\n tickThresholds = DEFAULT_TICK_THRESHOLDS,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n formatStepLabel,\n stepToValue: stepToValueProp,\n trackInset = SLIDER_TRACK_INSET,\n twClassName,\n style,\n ...props\n}: SliderProps) => {\n const tw = useTailwind();\n\n const formatLabel = formatStepLabel ?? defaultFormatStepLabel;\n\n const { handleLayout, progressStyle, thumbStyle, gesture, handlePressStep } =\n useSliderGesture({\n value,\n minimumValue,\n maximumValue,\n step,\n isDisabled,\n onValueChange,\n onDragEnd,\n onGrip,\n onTick,\n tickThresholds,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n stepToValue: stepToValueProp,\n });\n\n const getAccessibilityText = useCallback(() => {\n const trackPercent = Math.round(\n getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n ),\n );\n return `${trackPercent}%`;\n }, [mapValueToTrackPercent, maximumValue, minimumValue, value]);\n\n const handleAccessibilityAction = useCallback(\n (event: AccessibilityActionEvent) => {\n if (isDisabled) {\n return;\n }\n\n const delta = event.nativeEvent.actionName === 'increment' ? step : -step;\n const nextValue = clampValueToRange(\n value + delta,\n minimumValue,\n maximumValue,\n step,\n );\n\n if (nextValue !== value) {\n onValueChange(nextValue);\n onDragEnd?.(nextValue);\n }\n },\n [\n isDisabled,\n maximumValue,\n minimumValue,\n onDragEnd,\n onValueChange,\n step,\n value,\n ],\n );\n\n return (\n <Box\n {...props}\n testID={testID}\n accessibilityRole=\"adjustable\"\n accessibilityState={{ disabled: isDisabled }}\n accessibilityValue={{\n min: minimumValue,\n max: maximumValue,\n now: value,\n text: getAccessibilityText(),\n }}\n accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}\n onAccessibilityAction={handleAccessibilityAction}\n onLayout={handleLayout}\n style={[\n tw.style(\n 'relative self-stretch',\n isDisabled ? 'py-2 opacity-40' : 'py-2',\n ),\n {\n marginHorizontal: trackInset,\n ...(showRangeLabels && { paddingBottom: SLIDER_BOTTOM_PADDING }),\n },\n style,\n ]}\n twClassName={twClassName}\n >\n <GestureDetector gesture={gesture}>\n <Animated.View\n style={[tw.style('relative'), { height: THUMB_BOTTOM_OFFSET }]}\n >\n <Animated.View\n style={tw.style(\n 'absolute left-0 top-0 h-2 w-full rounded-full bg-border-muted',\n )}\n />\n <Animated.View\n style={[\n tw.style(\n 'absolute left-0 top-0 h-2 rounded-full bg-icon-alternative',\n ),\n progressStyle,\n ]}\n />\n {showRangeDots &&\n rangeLabelSteps.map((rangeStep) => (\n <Box\n key={`dot-${rangeStep}`}\n pointerEvents=\"none\"\n twClassName=\"absolute top-0.5 h-1 w-1 rounded-full bg-text-muted\"\n style={{\n left: getDotLeftPercent(rangeStep) as ViewStyle['left'],\n transform: [{ translateX: -2 }],\n zIndex: -2,\n }}\n />\n ))}\n <Animated.View\n style={[\n tw.style('absolute rounded-full bg-icon-default'),\n {\n width: THUMB_SIZE,\n height: THUMB_SIZE,\n top: THUMB_TOP_OFFSET,\n left: THUMB_LEFT_OFFSET,\n elevation: 4,\n },\n thumbStyle,\n ]}\n hitSlop={{ top: 25, bottom: 25, left: 25, right: 25 }}\n />\n </Animated.View>\n </GestureDetector>\n\n {showRangeLabels &&\n rangeLabelSteps.map((rangeStep) => (\n <Pressable\n key={`label-${rangeStep}`}\n style={[\n tw.style('absolute items-center'),\n {\n top: RANGE_LABEL_TOP,\n left: getDotLeftPercent(rangeStep) as ViewStyle['left'],\n transform: [{ translateX: '-50%' }],\n },\n ]}\n onPress={() => handlePressStep(rangeStep)}\n disabled={isDisabled}\n accessibilityRole=\"button\"\n >\n <Text\n variant={TextVariant.BodyMd}\n fontWeight={FontWeight.Medium}\n color={TextColor.TextAlternative}\n >\n {formatLabel(rangeStep)}\n </Text>\n </Pressable>\n ))}\n </Box>\n );\n};\n\nSlider.displayName = 'Slider';\n"]}
1
+ {"version":3,"file":"Slider.mjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n FontWeight,\n TextColor,\n TextVariant,\n SliderMarkColor,\n} from '@metamask/design-system-shared';\nimport {\n getThemeColors,\n usePureBlack,\n useTailwind,\n useTheme,\n} from '@metamask/design-system-twrnc-preset';\nimport React, { useCallback, useMemo } from 'react';\nimport { AccessibilityActionEvent, Pressable } from 'react-native';\nimport type { ViewStyle } from 'react-native';\nimport { GestureDetector } from 'react-native-gesture-handler';\nimport Animated from 'react-native-reanimated';\n\nimport { Box } from '../Box';\nimport { Text } from '../Text';\n\nimport {\n DEFAULT_MARKS,\n RANGE_LABEL_TOP,\n SLIDER_BOTTOM_PADDING,\n SLIDER_TRACK_INSET,\n THUMB_BOTTOM_OFFSET,\n THUMB_LEFT_OFFSET,\n THUMB_SIZE,\n THUMB_TOP_OFFSET,\n} from './Slider.constants';\nimport type { SliderProps } from './Slider.types';\nimport {\n buildColorStops,\n clampValueToRange,\n getDotLeftPercent,\n getTrackPercentFromValue,\n hasThemedMarkColors,\n} from './Slider.utilities';\nimport { useSliderGesture } from './useSliderGesture';\n\nexport const Slider = ({\n value,\n onValueChange,\n onDragEnd,\n minimumValue = 0,\n maximumValue = 100,\n step = 1,\n isDisabled = false,\n testID,\n marks = DEFAULT_MARKS,\n showRangeLabels = false,\n showRangeDots = false,\n onGrip,\n onMark,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n trackInset = SLIDER_TRACK_INSET,\n twClassName,\n style,\n ...props\n}: SliderProps) => {\n const tw = useTailwind();\n const theme = useTheme();\n const isPureBlack = usePureBlack();\n\n const palette = useMemo(\n () => getThemeColors(theme, isPureBlack),\n [isPureBlack, theme],\n );\n\n const themedColors = useMemo(() => {\n const hasThemedColors = hasThemedMarkColors(marks);\n\n return {\n hasThemedColors,\n fillColorStops: buildColorStops(\n marks,\n palette,\n SliderMarkColor.IconAlternative,\n ),\n thumbColorStops: buildColorStops(\n marks,\n palette,\n SliderMarkColor.IconDefault,\n ),\n };\n }, [palette, marks]);\n\n const labeledMarks = useMemo(\n () => marks.filter((mark) => mark.label !== undefined),\n [marks],\n );\n\n const { handleLayout, progressStyle, thumbStyle, gesture, handlePressStep } =\n useSliderGesture({\n value,\n minimumValue,\n maximumValue,\n step,\n isDisabled,\n onValueChange,\n onDragEnd,\n onGrip,\n onMark,\n marks,\n fillColorStops: themedColors.fillColorStops,\n thumbColorStops: themedColors.thumbColorStops,\n hasThemedColors: themedColors.hasThemedColors,\n mapValueToTrackPercent,\n mapTrackPercentToValue,\n });\n\n const getAccessibilityText = useCallback(() => {\n const trackPercent = Math.round(\n getTrackPercentFromValue(\n value,\n minimumValue,\n maximumValue,\n mapValueToTrackPercent,\n ),\n );\n return `${trackPercent}%`;\n }, [mapValueToTrackPercent, maximumValue, minimumValue, value]);\n\n const handleAccessibilityAction = useCallback(\n (event: AccessibilityActionEvent) => {\n if (isDisabled) {\n return;\n }\n\n const delta = event.nativeEvent.actionName === 'increment' ? step : -step;\n const nextValue = clampValueToRange(\n value + delta,\n minimumValue,\n maximumValue,\n step,\n );\n\n if (nextValue !== value) {\n onValueChange(nextValue);\n onDragEnd?.(nextValue);\n }\n },\n [\n isDisabled,\n maximumValue,\n minimumValue,\n onDragEnd,\n onValueChange,\n step,\n value,\n ],\n );\n\n return (\n <Box\n {...props}\n testID={testID}\n accessibilityRole=\"adjustable\"\n accessibilityState={{ disabled: isDisabled }}\n accessibilityValue={{\n min: minimumValue,\n max: maximumValue,\n now: value,\n text: getAccessibilityText(),\n }}\n accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}\n onAccessibilityAction={handleAccessibilityAction}\n onLayout={handleLayout}\n style={[\n tw.style(\n 'relative self-stretch',\n isDisabled ? 'py-2 opacity-40' : 'py-2',\n ),\n {\n marginHorizontal: trackInset,\n ...(showRangeLabels && { paddingBottom: SLIDER_BOTTOM_PADDING }),\n },\n style,\n ]}\n twClassName={twClassName}\n >\n <GestureDetector gesture={gesture}>\n <Animated.View\n style={[tw.style('relative'), { height: THUMB_BOTTOM_OFFSET }]}\n >\n <Animated.View\n style={tw.style(\n 'absolute left-0 top-0 h-2 w-full rounded-full bg-border-muted',\n )}\n />\n <Animated.View\n style={[\n tw.style(\n 'absolute left-0 top-0 h-2 rounded-full',\n !themedColors.hasThemedColors && 'bg-icon-alternative',\n ),\n progressStyle,\n ]}\n />\n {showRangeDots &&\n marks.map((mark) => (\n <Box\n key={`dot-${mark.step}`}\n pointerEvents=\"none\"\n twClassName=\"absolute top-0.5 h-1 w-1 rounded-full bg-text-muted\"\n style={{\n left: getDotLeftPercent(mark.step) as ViewStyle['left'],\n transform: [{ translateX: -2 }],\n zIndex: -2,\n }}\n />\n ))}\n <Animated.View\n style={[\n tw.style(\n 'absolute rounded-full',\n !themedColors.hasThemedColors && 'bg-icon-default',\n ),\n {\n width: THUMB_SIZE,\n height: THUMB_SIZE,\n top: THUMB_TOP_OFFSET,\n left: THUMB_LEFT_OFFSET,\n elevation: 4,\n },\n thumbStyle,\n ]}\n hitSlop={{ top: 25, bottom: 25, left: 25, right: 25 }}\n />\n </Animated.View>\n </GestureDetector>\n\n {showRangeLabels &&\n labeledMarks.map((mark) => (\n <Pressable\n key={`label-${mark.step}`}\n style={[\n tw.style('absolute items-center'),\n {\n top: RANGE_LABEL_TOP,\n left: getDotLeftPercent(mark.step) as ViewStyle['left'],\n transform: [{ translateX: '-50%' }],\n },\n ]}\n onPress={() => handlePressStep(mark.step)}\n disabled={isDisabled}\n accessibilityRole=\"button\"\n >\n <Text\n variant={TextVariant.BodyMd}\n fontWeight={FontWeight.Medium}\n color={TextColor.TextAlternative}\n >\n {mark.label}\n </Text>\n </Pressable>\n ))}\n </Box>\n );\n};\n\nSlider.displayName = 'Slider';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.types.cjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { SliderPropsShared } from '@metamask/design-system-shared';\nimport type { ViewProps } from 'react-native';\nimport type { Gesture } from 'react-native-gesture-handler';\nimport type { useAnimatedStyle } from 'react-native-reanimated';\n\n/**\n * React Native Slider props.\n *\n * Extends {@link SliderPropsShared} for cross-platform API (value, range, labels,\n * custom scale hooks) and `ViewProps` for root container passthrough (e.g.\n * `testID`, `accessibilityLabel`). See README for consumer-facing prop docs.\n */\nexport type SliderProps = SliderPropsShared &\n ViewProps & {\n /**\n * Horizontal inset on the root container so the thumb can overhang the track\n * at min/max without clipping. Defaults to {@link SLIDER_TRACK_INSET} (16);\n * override when the parent already provides edge padding.\n *\n * @default 16\n */\n trackInset?: number;\n\n /**\n * Optional twrnc classes merged into the root container after component defaults.\n * Use for layout spacing the Box API does not cover (e.g. `mt-4`).\n */\n twClassName?: string;\n };\n\n/**\n * Inputs for `useSliderGesture` — gesture handling and animated thumb/fill sync.\n *\n * Only `value` and `onValueChange` are required. Remaining fields default to the\n * same values as {@link SliderPropsShared} when omitted.\n */\nexport type UseSliderGestureParams = {\n /** Controlled domain value (`minimumValue`…`maximumValue`). */\n value: number;\n\n /**\n * Lower bound of the domain range.\n *\n * @default 0\n */\n minimumValue?: number;\n\n /**\n * Upper bound of the domain range.\n *\n * @default 100\n */\n maximumValue?: number;\n\n /**\n * Step increment applied by the default `mapTrackPercentToValue` mapper.\n * Custom mappers handle stepping inside `mapTrackPercentToValue`.\n *\n * @default 1\n */\n step?: number;\n\n /**\n * When true, pan/tap gestures and range-label presses are disabled.\n *\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Called on every value change during pan drag, track tap, or range-label press.\n * Bridged from UI-thread worklets via `runOnJS`.\n */\n onValueChange: (value: number) => void;\n\n /**\n * Called when a gesture completes (finger lift, tap, or label press).\n * Omitted when the parent does not pass `onDragEnd`.\n */\n onDragEnd?: (value: number) => void;\n\n /**\n * Fires once when pan begins and once when pan ends; not fired on tap or\n * range-label press. Use for haptic feedback (e.g. ImpactMoment.SliderGrip).\n */\n onGrip?: () => void;\n\n /**\n * Called when track percent crosses a `tickThresholds` entry while dragging.\n * Evaluated on each pan `onUpdate` and on range-label press.\n */\n onTick?: () => void;\n\n /**\n * Track-percent positions (0–100) that trigger `onTick` when crossed.\n * Not domain values use the same coordinate system as `rangeLabelSteps`.\n *\n * @default [25, 50, 75]\n */\n tickThresholds?: readonly number[];\n\n /**\n * Maps domain value → 0–100 track position for thumb/fill sync.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapValueToTrackPercent?: (value: number) => number;\n\n /**\n * Maps 0–100 track position → domain value during gestures.\n * Apply step rounding and snapping here for non-linear scales.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapTrackPercentToValue?: (trackPercent: number) => number;\n\n /**\n * Converts a tapped `rangeLabelSteps` entry to a domain value.\n * Default: `(step / 100) * (max - min) + min`.\n */\n stepToValue?: (step: number) => number;\n};\n\n/**\n * Return value of `useSliderGesture`.\n *\n * Wire `handleLayout`, animated styles, and `gesture` into `Slider.tsx`;\n * `handlePressStep` is bound to range-label `Pressable` targets.\n */\nexport type UseSliderGestureResult = {\n /**\n * Root `onLayout` handler. Stores track width and re-syncs thumb position\n * from the current `value` prop.\n */\n handleLayout: (event: { nativeEvent: { layout: { width: number } } }) => void;\n\n /** Animated width for the filled portion of the track (follows thumb). */\n progressStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Animated `translateX` for the thumb relative to the track start. */\n thumbStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Combined pan + tap gesture for the track/thumb hit area. */\n gesture: ReturnType<typeof Gesture.Simultaneous>;\n\n /**\n * Sets value from a tapped range label: `stepToValue` → callbacks → thumb sync.\n * No-op when `isDisabled` is true.\n */\n handlePressStep: (rangeStep: number) => void;\n};\n"]}
1
+ {"version":3,"file":"Slider.types.cjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n SliderPropsShared,\n SliderMark,\n SliderMarkColor,\n} from '@metamask/design-system-shared';\nimport type { ViewProps } from 'react-native';\nimport type { Gesture } from 'react-native-gesture-handler';\nimport type { useAnimatedStyle } from 'react-native-reanimated';\n\nimport type { SliderColorStop } from './Slider.utilities';\n\nexport type { SliderMark, SliderMarkColor };\n\n/**\n * React Native Slider props.\n *\n * Extends {@link SliderPropsShared} for cross-platform API (value, range, labels,\n * custom scale hooks) and `ViewProps` for root container passthrough (e.g.\n * `testID`, `accessibilityLabel`). See README for consumer-facing prop docs.\n */\nexport type SliderProps = SliderPropsShared &\n ViewProps & {\n /**\n * Horizontal inset on the root container so the thumb can overhang the track\n * at min/max without clipping. Defaults to {@link SLIDER_TRACK_INSET} (16);\n * override when the parent already provides edge padding.\n *\n * @default 16\n */\n trackInset?: number;\n\n /**\n * Optional twrnc classes merged into the root container after component defaults.\n * Use for layout spacing the Box API does not cover (e.g. `mt-4`).\n */\n twClassName?: string;\n };\n\n/**\n * Inputs for `useSliderGesture` — gesture handling and animated thumb/fill sync.\n *\n * Only `value` and `onValueChange` are required. Remaining fields default to the\n * same values as {@link SliderPropsShared} when omitted.\n */\nexport type UseSliderGestureParams = {\n /** Controlled domain value (`minimumValue`…`maximumValue`). */\n value: number;\n\n /**\n * Lower bound of the domain range.\n *\n * @default 0\n */\n minimumValue?: number;\n\n /**\n * Upper bound of the domain range.\n *\n * @default 100\n */\n maximumValue?: number;\n\n /**\n * Step increment applied by the default `mapTrackPercentToValue` mapper.\n * Custom mappers handle stepping inside `mapTrackPercentToValue`.\n *\n * @default 1\n */\n step?: number;\n\n /**\n * When true, pan/tap gestures and range-label presses are disabled.\n *\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Called on every value change during pan drag, track tap, or range-label press.\n * Bridged from UI-thread worklets via `runOnJS`.\n */\n onValueChange: (value: number) => void;\n\n /**\n * Called when a gesture completes (finger lift, tap, or label press).\n * Omitted when the parent does not pass `onDragEnd`.\n */\n onDragEnd?: (value: number) => void;\n\n /**\n * Fires once when pan begins and once when pan ends; not fired on tap or\n * range-label press. Use for haptic feedback (e.g. ImpactMoment.SliderGrip).\n */\n onGrip?: () => void;\n\n /**\n * Called when track percent crosses a haptic mark threshold while dragging.\n * Evaluated on each pan `onUpdate` and on range-label press.\n */\n onMark?: () => void;\n\n /** Mark entries for label press value resolution and haptic thresholds. */\n marks: readonly SliderMark[];\n\n /** Resolved fill color stops for themed interpolation. */\n fillColorStops: readonly SliderColorStop[];\n\n /** Resolved thumb color stops for themed interpolation. */\n thumbColorStops: readonly SliderColorStop[];\n\n /** When true, thumb and fill use interpolated theme colors. */\n hasThemedColors: boolean;\n\n /**\n * Maps domain value → 0–100 track position for thumb/fill sync.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapValueToTrackPercent?: (value: number) => number;\n\n /**\n * Maps 0–100 track position → domain value during gestures.\n * Apply step rounding and snapping here for non-linear scales.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapTrackPercentToValue?: (trackPercent: number) => number;\n};\n\n/**\n * Return value of `useSliderGesture`.\n *\n * Wire `handleLayout`, animated styles, and `gesture` into `Slider.tsx`;\n * `handlePressStep` is bound to range-label `Pressable` targets.\n */\nexport type UseSliderGestureResult = {\n /**\n * Root `onLayout` handler. Stores track width and re-syncs thumb position\n * from the current `value` prop.\n */\n handleLayout: (event: { nativeEvent: { layout: { width: number } } }) => void;\n\n /** Animated width for the filled portion of the track (follows thumb). */\n progressStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Animated `translateX` for the thumb relative to the track start. */\n thumbStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Combined pan + tap gesture for the track/thumb hit area. */\n gesture: ReturnType<typeof Gesture.Simultaneous>;\n\n /**\n * Sets value from a tapped mark label: mark value → callbacks → thumb sync.\n * No-op when `isDisabled` is true.\n */\n handlePressStep: (rangeStep: number) => void;\n};\n"]}
@@ -1,7 +1,9 @@
1
- import type { SliderPropsShared } from "@metamask/design-system-shared";
1
+ import type { SliderPropsShared, SliderMark, SliderMarkColor } from "@metamask/design-system-shared";
2
2
  import type { ViewProps } from "react-native";
3
3
  import type { Gesture } from "react-native-gesture-handler";
4
4
  import type { useAnimatedStyle } from "react-native-reanimated";
5
+ import type { SliderColorStop } from "./Slider.utilities.cjs";
6
+ export type { SliderMark, SliderMarkColor };
5
7
  /**
6
8
  * React Native Slider props.
7
9
  *
@@ -74,17 +76,18 @@ export type UseSliderGestureParams = {
74
76
  */
75
77
  onGrip?: () => void;
76
78
  /**
77
- * Called when track percent crosses a `tickThresholds` entry while dragging.
79
+ * Called when track percent crosses a haptic mark threshold while dragging.
78
80
  * Evaluated on each pan `onUpdate` and on range-label press.
79
81
  */
80
- onTick?: () => void;
81
- /**
82
- * Track-percent positions (0–100) that trigger `onTick` when crossed.
83
- * Not domain values use the same coordinate system as `rangeLabelSteps`.
84
- *
85
- * @default [25, 50, 75]
86
- */
87
- tickThresholds?: readonly number[];
82
+ onMark?: () => void;
83
+ /** Mark entries for label press value resolution and haptic thresholds. */
84
+ marks: readonly SliderMark[];
85
+ /** Resolved fill color stops for themed interpolation. */
86
+ fillColorStops: readonly SliderColorStop[];
87
+ /** Resolved thumb color stops for themed interpolation. */
88
+ thumbColorStops: readonly SliderColorStop[];
89
+ /** When true, thumb and fill use interpolated theme colors. */
90
+ hasThemedColors: boolean;
88
91
  /**
89
92
  * Maps domain value → 0–100 track position for thumb/fill sync.
90
93
  * Must be a Reanimated worklet when provided (`'worklet';` in the function body).
@@ -96,11 +99,6 @@ export type UseSliderGestureParams = {
96
99
  * Must be a Reanimated worklet when provided (`'worklet';` in the function body).
97
100
  */
98
101
  mapTrackPercentToValue?: (trackPercent: number) => number;
99
- /**
100
- * Converts a tapped `rangeLabelSteps` entry to a domain value.
101
- * Default: `(step / 100) * (max - min) + min`.
102
- */
103
- stepToValue?: (step: number) => number;
104
102
  };
105
103
  /**
106
104
  * Return value of `useSliderGesture`.
@@ -127,7 +125,7 @@ export type UseSliderGestureResult = {
127
125
  /** Combined pan + tap gesture for the track/thumb hit area. */
128
126
  gesture: ReturnType<typeof Gesture.Simultaneous>;
129
127
  /**
130
- * Sets value from a tapped range label: `stepToValue` → callbacks → thumb sync.
128
+ * Sets value from a tapped mark label: mark value → callbacks → thumb sync.
131
129
  * No-op when `isDisabled` is true.
132
130
  */
133
131
  handlePressStep: (rangeStep: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.types.d.cts","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,uCAAuC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,qCAAqC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAAgC;AAEhE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,GACzC,SAAS,GAAG;IACV;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEnC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEnD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAE1D;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,MAAM,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAE9E,0EAA0E;IAC1E,aAAa,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEnD,uEAAuE;IACvE,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEhD,+DAA+D;IAC/D,OAAO,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjD;;;OAGG;IACH,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC"}
1
+ {"version":3,"file":"Slider.types.d.cts","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,eAAe,EAChB,uCAAuC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,qCAAqC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAAgC;AAEhE,OAAO,KAAK,EAAE,eAAe,EAAE,+BAA2B;AAE1D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,GACzC,SAAS,GAAG;IACV;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB,2EAA2E;IAC3E,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAE7B,0DAA0D;IAC1D,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IAE3C,2DAA2D;IAC3D,eAAe,EAAE,SAAS,eAAe,EAAE,CAAC;IAE5C,+DAA+D;IAC/D,eAAe,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEnD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3D,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,MAAM,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAE9E,0EAA0E;IAC1E,aAAa,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEnD,uEAAuE;IACvE,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEhD,+DAA+D;IAC/D,OAAO,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjD;;;OAGG;IACH,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC"}
@@ -1,7 +1,9 @@
1
- import type { SliderPropsShared } from "@metamask/design-system-shared";
1
+ import type { SliderPropsShared, SliderMark, SliderMarkColor } from "@metamask/design-system-shared";
2
2
  import type { ViewProps } from "react-native";
3
3
  import type { Gesture } from "react-native-gesture-handler";
4
4
  import type { useAnimatedStyle } from "react-native-reanimated";
5
+ import type { SliderColorStop } from "./Slider.utilities.mjs";
6
+ export type { SliderMark, SliderMarkColor };
5
7
  /**
6
8
  * React Native Slider props.
7
9
  *
@@ -74,17 +76,18 @@ export type UseSliderGestureParams = {
74
76
  */
75
77
  onGrip?: () => void;
76
78
  /**
77
- * Called when track percent crosses a `tickThresholds` entry while dragging.
79
+ * Called when track percent crosses a haptic mark threshold while dragging.
78
80
  * Evaluated on each pan `onUpdate` and on range-label press.
79
81
  */
80
- onTick?: () => void;
81
- /**
82
- * Track-percent positions (0–100) that trigger `onTick` when crossed.
83
- * Not domain values use the same coordinate system as `rangeLabelSteps`.
84
- *
85
- * @default [25, 50, 75]
86
- */
87
- tickThresholds?: readonly number[];
82
+ onMark?: () => void;
83
+ /** Mark entries for label press value resolution and haptic thresholds. */
84
+ marks: readonly SliderMark[];
85
+ /** Resolved fill color stops for themed interpolation. */
86
+ fillColorStops: readonly SliderColorStop[];
87
+ /** Resolved thumb color stops for themed interpolation. */
88
+ thumbColorStops: readonly SliderColorStop[];
89
+ /** When true, thumb and fill use interpolated theme colors. */
90
+ hasThemedColors: boolean;
88
91
  /**
89
92
  * Maps domain value → 0–100 track position for thumb/fill sync.
90
93
  * Must be a Reanimated worklet when provided (`'worklet';` in the function body).
@@ -96,11 +99,6 @@ export type UseSliderGestureParams = {
96
99
  * Must be a Reanimated worklet when provided (`'worklet';` in the function body).
97
100
  */
98
101
  mapTrackPercentToValue?: (trackPercent: number) => number;
99
- /**
100
- * Converts a tapped `rangeLabelSteps` entry to a domain value.
101
- * Default: `(step / 100) * (max - min) + min`.
102
- */
103
- stepToValue?: (step: number) => number;
104
102
  };
105
103
  /**
106
104
  * Return value of `useSliderGesture`.
@@ -127,7 +125,7 @@ export type UseSliderGestureResult = {
127
125
  /** Combined pan + tap gesture for the track/thumb hit area. */
128
126
  gesture: ReturnType<typeof Gesture.Simultaneous>;
129
127
  /**
130
- * Sets value from a tapped range label: `stepToValue` → callbacks → thumb sync.
128
+ * Sets value from a tapped mark label: mark value → callbacks → thumb sync.
131
129
  * No-op when `isDisabled` is true.
132
130
  */
133
131
  handlePressStep: (rangeStep: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.types.d.mts","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,uCAAuC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,qCAAqC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAAgC;AAEhE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,GACzC,SAAS,GAAG;IACV;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEnC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEnD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAE1D;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,MAAM,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAE9E,0EAA0E;IAC1E,aAAa,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEnD,uEAAuE;IACvE,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEhD,+DAA+D;IAC/D,OAAO,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjD;;;OAGG;IACH,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC"}
1
+ {"version":3,"file":"Slider.types.d.mts","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,eAAe,EAChB,uCAAuC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,qCAAqC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAAgC;AAEhE,OAAO,KAAK,EAAE,eAAe,EAAE,+BAA2B;AAE1D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,GACzC,SAAS,GAAG;IACV;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB,2EAA2E;IAC3E,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAE7B,0DAA0D;IAC1D,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IAE3C,2DAA2D;IAC3D,eAAe,EAAE,SAAS,eAAe,EAAE,CAAC;IAE5C,+DAA+D;IAC/D,eAAe,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEnD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3D,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,MAAM,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAE9E,0EAA0E;IAC1E,aAAa,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEnD,uEAAuE;IACvE,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAEhD,+DAA+D;IAC/D,OAAO,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjD;;;OAGG;IACH,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.types.mjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { SliderPropsShared } from '@metamask/design-system-shared';\nimport type { ViewProps } from 'react-native';\nimport type { Gesture } from 'react-native-gesture-handler';\nimport type { useAnimatedStyle } from 'react-native-reanimated';\n\n/**\n * React Native Slider props.\n *\n * Extends {@link SliderPropsShared} for cross-platform API (value, range, labels,\n * custom scale hooks) and `ViewProps` for root container passthrough (e.g.\n * `testID`, `accessibilityLabel`). See README for consumer-facing prop docs.\n */\nexport type SliderProps = SliderPropsShared &\n ViewProps & {\n /**\n * Horizontal inset on the root container so the thumb can overhang the track\n * at min/max without clipping. Defaults to {@link SLIDER_TRACK_INSET} (16);\n * override when the parent already provides edge padding.\n *\n * @default 16\n */\n trackInset?: number;\n\n /**\n * Optional twrnc classes merged into the root container after component defaults.\n * Use for layout spacing the Box API does not cover (e.g. `mt-4`).\n */\n twClassName?: string;\n };\n\n/**\n * Inputs for `useSliderGesture` — gesture handling and animated thumb/fill sync.\n *\n * Only `value` and `onValueChange` are required. Remaining fields default to the\n * same values as {@link SliderPropsShared} when omitted.\n */\nexport type UseSliderGestureParams = {\n /** Controlled domain value (`minimumValue`…`maximumValue`). */\n value: number;\n\n /**\n * Lower bound of the domain range.\n *\n * @default 0\n */\n minimumValue?: number;\n\n /**\n * Upper bound of the domain range.\n *\n * @default 100\n */\n maximumValue?: number;\n\n /**\n * Step increment applied by the default `mapTrackPercentToValue` mapper.\n * Custom mappers handle stepping inside `mapTrackPercentToValue`.\n *\n * @default 1\n */\n step?: number;\n\n /**\n * When true, pan/tap gestures and range-label presses are disabled.\n *\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Called on every value change during pan drag, track tap, or range-label press.\n * Bridged from UI-thread worklets via `runOnJS`.\n */\n onValueChange: (value: number) => void;\n\n /**\n * Called when a gesture completes (finger lift, tap, or label press).\n * Omitted when the parent does not pass `onDragEnd`.\n */\n onDragEnd?: (value: number) => void;\n\n /**\n * Fires once when pan begins and once when pan ends; not fired on tap or\n * range-label press. Use for haptic feedback (e.g. ImpactMoment.SliderGrip).\n */\n onGrip?: () => void;\n\n /**\n * Called when track percent crosses a `tickThresholds` entry while dragging.\n * Evaluated on each pan `onUpdate` and on range-label press.\n */\n onTick?: () => void;\n\n /**\n * Track-percent positions (0–100) that trigger `onTick` when crossed.\n * Not domain values use the same coordinate system as `rangeLabelSteps`.\n *\n * @default [25, 50, 75]\n */\n tickThresholds?: readonly number[];\n\n /**\n * Maps domain value → 0–100 track position for thumb/fill sync.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapValueToTrackPercent?: (value: number) => number;\n\n /**\n * Maps 0–100 track position → domain value during gestures.\n * Apply step rounding and snapping here for non-linear scales.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapTrackPercentToValue?: (trackPercent: number) => number;\n\n /**\n * Converts a tapped `rangeLabelSteps` entry to a domain value.\n * Default: `(step / 100) * (max - min) + min`.\n */\n stepToValue?: (step: number) => number;\n};\n\n/**\n * Return value of `useSliderGesture`.\n *\n * Wire `handleLayout`, animated styles, and `gesture` into `Slider.tsx`;\n * `handlePressStep` is bound to range-label `Pressable` targets.\n */\nexport type UseSliderGestureResult = {\n /**\n * Root `onLayout` handler. Stores track width and re-syncs thumb position\n * from the current `value` prop.\n */\n handleLayout: (event: { nativeEvent: { layout: { width: number } } }) => void;\n\n /** Animated width for the filled portion of the track (follows thumb). */\n progressStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Animated `translateX` for the thumb relative to the track start. */\n thumbStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Combined pan + tap gesture for the track/thumb hit area. */\n gesture: ReturnType<typeof Gesture.Simultaneous>;\n\n /**\n * Sets value from a tapped range label: `stepToValue` → callbacks → thumb sync.\n * No-op when `isDisabled` is true.\n */\n handlePressStep: (rangeStep: number) => void;\n};\n"]}
1
+ {"version":3,"file":"Slider.types.mjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n SliderPropsShared,\n SliderMark,\n SliderMarkColor,\n} from '@metamask/design-system-shared';\nimport type { ViewProps } from 'react-native';\nimport type { Gesture } from 'react-native-gesture-handler';\nimport type { useAnimatedStyle } from 'react-native-reanimated';\n\nimport type { SliderColorStop } from './Slider.utilities';\n\nexport type { SliderMark, SliderMarkColor };\n\n/**\n * React Native Slider props.\n *\n * Extends {@link SliderPropsShared} for cross-platform API (value, range, labels,\n * custom scale hooks) and `ViewProps` for root container passthrough (e.g.\n * `testID`, `accessibilityLabel`). See README for consumer-facing prop docs.\n */\nexport type SliderProps = SliderPropsShared &\n ViewProps & {\n /**\n * Horizontal inset on the root container so the thumb can overhang the track\n * at min/max without clipping. Defaults to {@link SLIDER_TRACK_INSET} (16);\n * override when the parent already provides edge padding.\n *\n * @default 16\n */\n trackInset?: number;\n\n /**\n * Optional twrnc classes merged into the root container after component defaults.\n * Use for layout spacing the Box API does not cover (e.g. `mt-4`).\n */\n twClassName?: string;\n };\n\n/**\n * Inputs for `useSliderGesture` — gesture handling and animated thumb/fill sync.\n *\n * Only `value` and `onValueChange` are required. Remaining fields default to the\n * same values as {@link SliderPropsShared} when omitted.\n */\nexport type UseSliderGestureParams = {\n /** Controlled domain value (`minimumValue`…`maximumValue`). */\n value: number;\n\n /**\n * Lower bound of the domain range.\n *\n * @default 0\n */\n minimumValue?: number;\n\n /**\n * Upper bound of the domain range.\n *\n * @default 100\n */\n maximumValue?: number;\n\n /**\n * Step increment applied by the default `mapTrackPercentToValue` mapper.\n * Custom mappers handle stepping inside `mapTrackPercentToValue`.\n *\n * @default 1\n */\n step?: number;\n\n /**\n * When true, pan/tap gestures and range-label presses are disabled.\n *\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Called on every value change during pan drag, track tap, or range-label press.\n * Bridged from UI-thread worklets via `runOnJS`.\n */\n onValueChange: (value: number) => void;\n\n /**\n * Called when a gesture completes (finger lift, tap, or label press).\n * Omitted when the parent does not pass `onDragEnd`.\n */\n onDragEnd?: (value: number) => void;\n\n /**\n * Fires once when pan begins and once when pan ends; not fired on tap or\n * range-label press. Use for haptic feedback (e.g. ImpactMoment.SliderGrip).\n */\n onGrip?: () => void;\n\n /**\n * Called when track percent crosses a haptic mark threshold while dragging.\n * Evaluated on each pan `onUpdate` and on range-label press.\n */\n onMark?: () => void;\n\n /** Mark entries for label press value resolution and haptic thresholds. */\n marks: readonly SliderMark[];\n\n /** Resolved fill color stops for themed interpolation. */\n fillColorStops: readonly SliderColorStop[];\n\n /** Resolved thumb color stops for themed interpolation. */\n thumbColorStops: readonly SliderColorStop[];\n\n /** When true, thumb and fill use interpolated theme colors. */\n hasThemedColors: boolean;\n\n /**\n * Maps domain value → 0–100 track position for thumb/fill sync.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapValueToTrackPercent?: (value: number) => number;\n\n /**\n * Maps 0–100 track position → domain value during gestures.\n * Apply step rounding and snapping here for non-linear scales.\n * Must be a Reanimated worklet when provided (`'worklet';` in the function body).\n */\n mapTrackPercentToValue?: (trackPercent: number) => number;\n};\n\n/**\n * Return value of `useSliderGesture`.\n *\n * Wire `handleLayout`, animated styles, and `gesture` into `Slider.tsx`;\n * `handlePressStep` is bound to range-label `Pressable` targets.\n */\nexport type UseSliderGestureResult = {\n /**\n * Root `onLayout` handler. Stores track width and re-syncs thumb position\n * from the current `value` prop.\n */\n handleLayout: (event: { nativeEvent: { layout: { width: number } } }) => void;\n\n /** Animated width for the filled portion of the track (follows thumb). */\n progressStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Animated `translateX` for the thumb relative to the track start. */\n thumbStyle: ReturnType<typeof useAnimatedStyle>;\n\n /** Combined pan + tap gesture for the track/thumb hit area. */\n gesture: ReturnType<typeof Gesture.Simultaneous>;\n\n /**\n * Sets value from a tapped mark label: mark value → callbacks → thumb sync.\n * No-op when `isDisabled` is true.\n */\n handlePressStep: (rangeStep: number) => void;\n};\n"]}
@@ -5,14 +5,15 @@
5
5
  * Three coordinate systems:
6
6
  * - **Domain value** — the controlled `value` prop (`minimumValue`…`maximumValue`).
7
7
  * - **Track percent** — normalized 0–100 position along the track (used for dots,
8
- * labels, and `tickThresholds`; may be non-linear via `map*` hooks).
8
+ * labels, and haptic thresholds; may be non-linear via `map*` hooks).
9
9
  * - **Pixel position** — thumb/fill offset in layout pixels (`translateX`).
10
10
  *
11
11
  * Functions marked with `'worklet'` run on the UI thread inside gesture handlers.
12
12
  * JS-thread callers use the non-worklet wrappers (`getTrackPercentFromValue`, etc.).
13
13
  */
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.clampValueToRange = exports.getDotLeftPercent = exports.defaultFormatStepLabel = exports.defaultStepToValue = exports.getTrackPercentFromValue = exports.clampGesturePosition = exports.positionToTrackPercent = exports.trackPercentToPosition = exports.resolveValueToTrackPercent = exports.resolveTrackPercentToValue = exports.defaultMapTrackPercentToValue = exports.defaultMapValueToTrackPercent = exports.clampTrackPercent = void 0;
15
+ exports.clampValueToRange = exports.getDotLeftPercent = exports.hasThemedMarkColors = exports.interpolateMarkColor = exports.buildColorStops = exports.resolveMarkColor = exports.getMarkHapticThresholds = exports.getMarkValue = exports.defaultStepToValue = exports.getTrackPercentFromValue = exports.clampGesturePosition = exports.positionToTrackPercent = exports.trackPercentToPosition = exports.resolveValueToTrackPercent = exports.resolveTrackPercentToValue = exports.defaultMapTrackPercentToValue = exports.defaultMapValueToTrackPercent = exports.clampTrackPercent = void 0;
16
+ const react_native_reanimated_1 = require("react-native-reanimated");
16
17
  const Slider_constants_1 = require("./Slider.constants.cjs");
17
18
  // --- Track-percent primitives (worklet) ---
18
19
  function clampTrackPercent(trackPercent) {
@@ -143,9 +144,9 @@ function getTrackPercentFromValue(value, minimumValue, maximumValue, mapValueToT
143
144
  exports.getTrackPercentFromValue = getTrackPercentFromValue;
144
145
  // --- Range label / dot defaults (Slider.tsx) ---
145
146
  /**
146
- * Default `stepToValue`: linear track-percent → domain value.
147
+ * Default linear track-percent → domain value for a mark.
147
148
  *
148
- * @param step - Track-percent step from `rangeLabelSteps`.
149
+ * @param step - Track-percent step from a mark entry.
149
150
  * @param minimumValue - Lower bound of the domain range.
150
151
  * @param maximumValue - Upper bound of the domain range.
151
152
  * @returns Domain value for the step.
@@ -155,19 +156,103 @@ function defaultStepToValue(step, minimumValue, maximumValue) {
155
156
  }
156
157
  exports.defaultStepToValue = defaultStepToValue;
157
158
  /**
158
- * Default `formatStepLabel`: display track percent as a percent string.
159
+ * Domain value for a mark: explicit `value` or linear default from step.
159
160
  *
160
- * @param step - Track-percent step from `rangeLabelSteps`.
161
- * @returns Formatted label string.
161
+ * @param mark - Mark entry.
162
+ * @param minimumValue - Lower bound of the domain range.
163
+ * @param maximumValue - Upper bound of the domain range.
164
+ * @returns Domain value for the mark.
162
165
  */
163
- function defaultFormatStepLabel(step) {
164
- return `${step}%`;
166
+ function getMarkValue(mark, minimumValue, maximumValue) {
167
+ if (mark.value !== undefined) {
168
+ return mark.value;
169
+ }
170
+ return defaultStepToValue(mark.step, minimumValue, maximumValue);
171
+ }
172
+ exports.getMarkValue = getMarkValue;
173
+ /**
174
+ * Track-percent thresholds that trigger onMark while dragging.
175
+ *
176
+ * @param marks - Mark entries.
177
+ * @returns Haptic threshold positions.
178
+ */
179
+ function getMarkHapticThresholds(marks) {
180
+ return marks
181
+ .filter((mark) => mark.haptic ?? Boolean(mark.label))
182
+ .map((mark) => mark.step);
183
+ }
184
+ exports.getMarkHapticThresholds = getMarkHapticThresholds;
185
+ /**
186
+ * Resolves a mark color to a concrete color string for Reanimated.
187
+ * Design tokens are looked up on the palette; raw hex/rgb pass through
188
+ * (temporary migration bridge — prefer `SliderMarkColor` tokens in app code).
189
+ *
190
+ * @param color - Theme token key (or legacy hex/rgb string).
191
+ * @param palette - Flattened theme color palette.
192
+ * @param fallback - Fallback color when token is not found.
193
+ * @returns Resolved color string.
194
+ */
195
+ function resolveMarkColor(color, palette, fallback) {
196
+ if (color.startsWith('#') || color.startsWith('rgb')) {
197
+ return color;
198
+ }
199
+ return palette[color] ?? fallback;
200
+ }
201
+ exports.resolveMarkColor = resolveMarkColor;
202
+ /**
203
+ * Builds color interpolation stops from marks, applying fallback for missing colors.
204
+ *
205
+ * @param marks - Mark entries.
206
+ * @param palette - Flattened theme color palette.
207
+ * @param fallbackToken - Default token key when mark.color is omitted.
208
+ * @returns Sorted color stops for interpolation.
209
+ */
210
+ function buildColorStops(marks, palette, fallbackToken) {
211
+ const fallback = palette[fallbackToken] ?? '#000000';
212
+ return [...marks]
213
+ .sort((a, b) => a.step - b.step)
214
+ .map((mark) => ({
215
+ step: mark.step,
216
+ color: mark.color
217
+ ? resolveMarkColor(mark.color, palette, fallback)
218
+ : fallback,
219
+ }));
220
+ }
221
+ exports.buildColorStops = buildColorStops;
222
+ /**
223
+ * Interpolates a color along the track based on mark color stops.
224
+ *
225
+ * @param trackPercent - Current track position from 0–100.
226
+ * @param stops - Sorted color stops.
227
+ * @returns Interpolated color string.
228
+ */
229
+ function interpolateMarkColor(trackPercent, stops) {
230
+ 'worklet';
231
+ if (stops.length === 0) {
232
+ return '#000000';
233
+ }
234
+ if (stops.length === 1) {
235
+ return stops[0].color;
236
+ }
237
+ const inputRange = stops.map((stop) => stop.step);
238
+ const outputRange = stops.map((stop) => stop.color);
239
+ return (0, react_native_reanimated_1.interpolateColor)(clampTrackPercent(trackPercent), inputRange, outputRange, 'RGB');
240
+ }
241
+ exports.interpolateMarkColor = interpolateMarkColor;
242
+ /**
243
+ * Whether any mark defines a theme color.
244
+ *
245
+ * @param marks - Mark entries.
246
+ * @returns True when at least one mark has a color.
247
+ */
248
+ function hasThemedMarkColors(marks) {
249
+ return marks.some((mark) => Boolean(mark.color));
165
250
  }
166
- exports.defaultFormatStepLabel = defaultFormatStepLabel;
251
+ exports.hasThemedMarkColors = hasThemedMarkColors;
167
252
  /**
168
253
  * Marker `left` percent for range dots and labels; edge steps inset to stay on track.
169
254
  *
170
- * @param step - Track-percent step from `rangeLabelSteps`.
255
+ * @param step - Track-percent step from a mark entry.
171
256
  * @returns CSS `left` percentage string.
172
257
  */
173
258
  function getDotLeftPercent(step) {
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.utilities.cjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.utilities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure helpers for Slider coordinate conversion and UI defaults.\n *\n * Three coordinate systems:\n * - **Domain value** — the controlled `value` prop (`minimumValue`…`maximumValue`).\n * - **Track percent** — normalized 0–100 position along the track (used for dots,\n * labels, and `tickThresholds`; may be non-linear via `map*` hooks).\n * - **Pixel position** — thumb/fill offset in layout pixels (`translateX`).\n *\n * Functions marked with `'worklet'` run on the UI thread inside gesture handlers.\n * JS-thread callers use the non-worklet wrappers (`getTrackPercentFromValue`, etc.).\n */\n\nimport {\n DOT_EDGE_INSET_PERCENT,\n DOT_EDGE_MAX_PERCENT,\n} from './Slider.constants';\n\n// --- Track-percent primitives (worklet) ---\n\nexport function clampTrackPercent(trackPercent: number): number {\n 'worklet';\n\n return Math.max(0, Math.min(100, trackPercent));\n}\n\n// --- Domain ↔ track-percent mappers (worklet) ---\n\n/**\n * Linear default: domain value → 0–100 track position.\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @returns Track percent clamped to 0–100.\n */\nexport function defaultMapValueToTrackPercent(\n value: number,\n minimumValue: number,\n maximumValue: number,\n): number {\n 'worklet';\n\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return 0;\n }\n\n const percent = ((value - minimumValue) / range) * 100;\n return clampTrackPercent(percent);\n}\n\n/**\n * Linear default: track position → stepped domain value.\n *\n * @param trackPercent - Track position from 0–100.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for rounding.\n * @returns Stepped domain value clamped to the range.\n */\nexport function defaultMapTrackPercentToValue(\n trackPercent: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n): number {\n 'worklet';\n\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return minimumValue;\n }\n\n const rawValue =\n (clampTrackPercent(trackPercent) / 100) * range + minimumValue;\n const stepped = Math.round(rawValue / step) * step;\n return Math.max(minimumValue, Math.min(maximumValue, stepped));\n}\n\n/**\n * UI-thread entry: custom `mapTrackPercentToValue` or linear default.\n *\n * @param trackPercent - Track position from 0–100.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for the default mapper.\n * @param mapTrackPercentToValue - Optional custom mapper.\n * @returns Domain value for the track position.\n */\nexport function resolveTrackPercentToValue(\n trackPercent: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n mapTrackPercentToValue?: (trackPercent: number) => number,\n): number {\n 'worklet';\n\n if (mapTrackPercentToValue) {\n return mapTrackPercentToValue(trackPercent);\n }\n\n return defaultMapTrackPercentToValue(\n trackPercent,\n minimumValue,\n maximumValue,\n step,\n );\n}\n\n/**\n * UI-thread entry: custom `mapValueToTrackPercent` or linear default.\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param mapValueToTrackPercent - Optional custom mapper.\n * @returns Track percent for the domain value.\n */\nexport function resolveValueToTrackPercent(\n value: number,\n minimumValue: number,\n maximumValue: number,\n mapValueToTrackPercent?: (value: number) => number,\n): number {\n 'worklet';\n\n if (mapValueToTrackPercent) {\n return mapValueToTrackPercent(value);\n }\n\n return defaultMapValueToTrackPercent(value, minimumValue, maximumValue);\n}\n\n// --- Track-percent ↔ pixel position (worklet) ---\n\nexport function trackPercentToPosition(\n trackPercent: number,\n width: number,\n): number {\n 'worklet';\n\n if (width === 0) {\n return 0;\n }\n\n return (clampTrackPercent(trackPercent) / 100) * width;\n}\n\nexport function positionToTrackPercent(\n position: number,\n width: number,\n): number {\n 'worklet';\n\n if (width === 0) {\n return 0;\n }\n\n return clampTrackPercent((position / width) * 100);\n}\n\n/**\n * Clamps a touch X coordinate to the track bounds.\n *\n * @param position - Touch X in track coordinates.\n * @param width - Track width in pixels.\n * @returns Clamped pixel position.\n */\nexport function clampGesturePosition(position: number, width: number): number {\n 'worklet';\n\n return Math.max(0, Math.min(position, width));\n}\n\n// --- JS-thread domain ↔ track-percent ---\n\n/**\n * JS-thread entry for mapping domain value → track percent.\n * Used by Slider (labels, a11y) and useSliderGesture (prop/layout sync).\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param mapValueToTrackPercent - Optional custom mapper.\n * @returns Track percent for the domain value.\n */\nexport function getTrackPercentFromValue(\n value: number,\n minimumValue: number,\n maximumValue: number,\n mapValueToTrackPercent?: (value: number) => number,\n): number {\n if (mapValueToTrackPercent) {\n return mapValueToTrackPercent(value);\n }\n\n return defaultMapValueToTrackPercent(value, minimumValue, maximumValue);\n}\n\n// --- Range label / dot defaults (Slider.tsx) ---\n\n/**\n * Default `stepToValue`: linear track-percent → domain value.\n *\n * @param step - Track-percent step from `rangeLabelSteps`.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @returns Domain value for the step.\n */\nexport function defaultStepToValue(\n step: number,\n minimumValue: number,\n maximumValue: number,\n): number {\n return (step / 100) * (maximumValue - minimumValue) + minimumValue;\n}\n\n/**\n * Default `formatStepLabel`: display track percent as a percent string.\n *\n * @param step - Track-percent step from `rangeLabelSteps`.\n * @returns Formatted label string.\n */\nexport function defaultFormatStepLabel(step: number): string {\n return `${step}%`;\n}\n\n/**\n * Marker `left` percent for range dots and labels; edge steps inset to stay on track.\n *\n * @param step - Track-percent step from `rangeLabelSteps`.\n * @returns CSS `left` percentage string.\n */\nexport function getDotLeftPercent(step: number): string {\n if (step === 0) {\n return DOT_EDGE_INSET_PERCENT;\n }\n if (step === 100) {\n return DOT_EDGE_MAX_PERCENT;\n }\n\n return `${step}%`;\n}\n\n// --- Accessibility (Slider.tsx) ---\n\n/**\n * Clamps and steps a domain value for increment/decrement actions.\n *\n * @param value - Domain value to clamp.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for rounding.\n * @returns Clamped and stepped domain value.\n */\nexport function clampValueToRange(\n value: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n): number {\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return minimumValue;\n }\n\n const clamped = Math.max(minimumValue, Math.min(maximumValue, value));\n return Math.round(clamped / step) * step;\n}\n"]}
1
+ {"version":3,"file":"Slider.utilities.cjs","sourceRoot":"","sources":["../../../src/components/Slider/Slider.utilities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure helpers for Slider coordinate conversion and UI defaults.\n *\n * Three coordinate systems:\n * - **Domain value** — the controlled `value` prop (`minimumValue`…`maximumValue`).\n * - **Track percent** — normalized 0–100 position along the track (used for dots,\n * labels, and haptic thresholds; may be non-linear via `map*` hooks).\n * - **Pixel position** — thumb/fill offset in layout pixels (`translateX`).\n *\n * Functions marked with `'worklet'` run on the UI thread inside gesture handlers.\n * JS-thread callers use the non-worklet wrappers (`getTrackPercentFromValue`, etc.).\n */\n\nimport type {\n SliderMark,\n SliderMarkColor,\n} from '@metamask/design-system-shared';\nimport { interpolateColor } from 'react-native-reanimated';\n\nimport {\n DOT_EDGE_INSET_PERCENT,\n DOT_EDGE_MAX_PERCENT,\n} from './Slider.constants';\n\nexport type SliderColorStop = {\n step: number;\n color: string;\n};\n\n// --- Track-percent primitives (worklet) ---\n\nexport function clampTrackPercent(trackPercent: number): number {\n 'worklet';\n\n return Math.max(0, Math.min(100, trackPercent));\n}\n\n// --- Domain ↔ track-percent mappers (worklet) ---\n\n/**\n * Linear default: domain value → 0–100 track position.\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @returns Track percent clamped to 0–100.\n */\nexport function defaultMapValueToTrackPercent(\n value: number,\n minimumValue: number,\n maximumValue: number,\n): number {\n 'worklet';\n\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return 0;\n }\n\n const percent = ((value - minimumValue) / range) * 100;\n return clampTrackPercent(percent);\n}\n\n/**\n * Linear default: track position → stepped domain value.\n *\n * @param trackPercent - Track position from 0–100.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for rounding.\n * @returns Stepped domain value clamped to the range.\n */\nexport function defaultMapTrackPercentToValue(\n trackPercent: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n): number {\n 'worklet';\n\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return minimumValue;\n }\n\n const rawValue =\n (clampTrackPercent(trackPercent) / 100) * range + minimumValue;\n const stepped = Math.round(rawValue / step) * step;\n return Math.max(minimumValue, Math.min(maximumValue, stepped));\n}\n\n/**\n * UI-thread entry: custom `mapTrackPercentToValue` or linear default.\n *\n * @param trackPercent - Track position from 0–100.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for the default mapper.\n * @param mapTrackPercentToValue - Optional custom mapper.\n * @returns Domain value for the track position.\n */\nexport function resolveTrackPercentToValue(\n trackPercent: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n mapTrackPercentToValue?: (trackPercent: number) => number,\n): number {\n 'worklet';\n\n if (mapTrackPercentToValue) {\n return mapTrackPercentToValue(trackPercent);\n }\n\n return defaultMapTrackPercentToValue(\n trackPercent,\n minimumValue,\n maximumValue,\n step,\n );\n}\n\n/**\n * UI-thread entry: custom `mapValueToTrackPercent` or linear default.\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param mapValueToTrackPercent - Optional custom mapper.\n * @returns Track percent for the domain value.\n */\nexport function resolveValueToTrackPercent(\n value: number,\n minimumValue: number,\n maximumValue: number,\n mapValueToTrackPercent?: (value: number) => number,\n): number {\n 'worklet';\n\n if (mapValueToTrackPercent) {\n return mapValueToTrackPercent(value);\n }\n\n return defaultMapValueToTrackPercent(value, minimumValue, maximumValue);\n}\n\n// --- Track-percent ↔ pixel position (worklet) ---\n\nexport function trackPercentToPosition(\n trackPercent: number,\n width: number,\n): number {\n 'worklet';\n\n if (width === 0) {\n return 0;\n }\n\n return (clampTrackPercent(trackPercent) / 100) * width;\n}\n\nexport function positionToTrackPercent(\n position: number,\n width: number,\n): number {\n 'worklet';\n\n if (width === 0) {\n return 0;\n }\n\n return clampTrackPercent((position / width) * 100);\n}\n\n/**\n * Clamps a touch X coordinate to the track bounds.\n *\n * @param position - Touch X in track coordinates.\n * @param width - Track width in pixels.\n * @returns Clamped pixel position.\n */\nexport function clampGesturePosition(position: number, width: number): number {\n 'worklet';\n\n return Math.max(0, Math.min(position, width));\n}\n\n// --- JS-thread domain ↔ track-percent ---\n\n/**\n * JS-thread entry for mapping domain value → track percent.\n * Used by Slider (labels, a11y) and useSliderGesture (prop/layout sync).\n *\n * @param value - Domain value to map.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param mapValueToTrackPercent - Optional custom mapper.\n * @returns Track percent for the domain value.\n */\nexport function getTrackPercentFromValue(\n value: number,\n minimumValue: number,\n maximumValue: number,\n mapValueToTrackPercent?: (value: number) => number,\n): number {\n if (mapValueToTrackPercent) {\n return mapValueToTrackPercent(value);\n }\n\n return defaultMapValueToTrackPercent(value, minimumValue, maximumValue);\n}\n\n// --- Range label / dot defaults (Slider.tsx) ---\n\n/**\n * Default linear track-percent → domain value for a mark.\n *\n * @param step - Track-percent step from a mark entry.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @returns Domain value for the step.\n */\nexport function defaultStepToValue(\n step: number,\n minimumValue: number,\n maximumValue: number,\n): number {\n return (step / 100) * (maximumValue - minimumValue) + minimumValue;\n}\n\n/**\n * Domain value for a mark: explicit `value` or linear default from step.\n *\n * @param mark - Mark entry.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @returns Domain value for the mark.\n */\nexport function getMarkValue(\n mark: SliderMark,\n minimumValue: number,\n maximumValue: number,\n): number {\n if (mark.value !== undefined) {\n return mark.value;\n }\n\n return defaultStepToValue(mark.step, minimumValue, maximumValue);\n}\n\n/**\n * Track-percent thresholds that trigger onMark while dragging.\n *\n * @param marks - Mark entries.\n * @returns Haptic threshold positions.\n */\nexport function getMarkHapticThresholds(\n marks: readonly SliderMark[],\n): number[] {\n return marks\n .filter((mark) => mark.haptic ?? Boolean(mark.label))\n .map((mark) => mark.step);\n}\n\n/**\n * Resolves a mark color to a concrete color string for Reanimated.\n * Design tokens are looked up on the palette; raw hex/rgb pass through\n * (temporary migration bridge — prefer `SliderMarkColor` tokens in app code).\n *\n * @param color - Theme token key (or legacy hex/rgb string).\n * @param palette - Flattened theme color palette.\n * @param fallback - Fallback color when token is not found.\n * @returns Resolved color string.\n */\nexport function resolveMarkColor(\n color: SliderMarkColor | string,\n palette: Record<string, string>,\n fallback: string,\n): string {\n if (color.startsWith('#') || color.startsWith('rgb')) {\n return color;\n }\n\n return palette[color] ?? fallback;\n}\n\n/**\n * Builds color interpolation stops from marks, applying fallback for missing colors.\n *\n * @param marks - Mark entries.\n * @param palette - Flattened theme color palette.\n * @param fallbackToken - Default token key when mark.color is omitted.\n * @returns Sorted color stops for interpolation.\n */\nexport function buildColorStops(\n marks: readonly SliderMark[],\n palette: Record<string, string>,\n fallbackToken: string,\n): SliderColorStop[] {\n const fallback = palette[fallbackToken] ?? '#000000';\n\n return [...marks]\n .sort((a, b) => a.step - b.step)\n .map((mark) => ({\n step: mark.step,\n color: mark.color\n ? resolveMarkColor(mark.color, palette, fallback)\n : fallback,\n }));\n}\n\n/**\n * Interpolates a color along the track based on mark color stops.\n *\n * @param trackPercent - Current track position from 0–100.\n * @param stops - Sorted color stops.\n * @returns Interpolated color string.\n */\nexport function interpolateMarkColor(\n trackPercent: number,\n stops: readonly SliderColorStop[],\n): string {\n 'worklet';\n\n if (stops.length === 0) {\n return '#000000';\n }\n\n if (stops.length === 1) {\n return stops[0].color;\n }\n\n const inputRange = stops.map((stop) => stop.step);\n const outputRange = stops.map((stop) => stop.color);\n\n return interpolateColor(\n clampTrackPercent(trackPercent),\n inputRange,\n outputRange,\n 'RGB',\n );\n}\n\n/**\n * Whether any mark defines a theme color.\n *\n * @param marks - Mark entries.\n * @returns True when at least one mark has a color.\n */\nexport function hasThemedMarkColors(marks: readonly SliderMark[]): boolean {\n return marks.some((mark) => Boolean(mark.color));\n}\n\n/**\n * Marker `left` percent for range dots and labels; edge steps inset to stay on track.\n *\n * @param step - Track-percent step from a mark entry.\n * @returns CSS `left` percentage string.\n */\nexport function getDotLeftPercent(step: number): string {\n if (step === 0) {\n return DOT_EDGE_INSET_PERCENT;\n }\n if (step === 100) {\n return DOT_EDGE_MAX_PERCENT;\n }\n\n return `${step}%`;\n}\n\n// --- Accessibility (Slider.tsx) ---\n\n/**\n * Clamps and steps a domain value for increment/decrement actions.\n *\n * @param value - Domain value to clamp.\n * @param minimumValue - Lower bound of the domain range.\n * @param maximumValue - Upper bound of the domain range.\n * @param step - Step increment for rounding.\n * @returns Clamped and stepped domain value.\n */\nexport function clampValueToRange(\n value: number,\n minimumValue: number,\n maximumValue: number,\n step: number,\n): number {\n const range = maximumValue - minimumValue;\n if (range === 0) {\n return minimumValue;\n }\n\n const clamped = Math.max(minimumValue, Math.min(maximumValue, value));\n return Math.round(clamped / step) * step;\n}\n"]}