@cdx-ui/components 0.0.1-beta.170 → 0.0.1-beta.172

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 (45) hide show
  1. package/coverage.svg +1 -1
  2. package/lib/commonjs/components/Accordion/index.js +295 -0
  3. package/lib/commonjs/components/Accordion/index.js.map +1 -0
  4. package/lib/commonjs/components/Accordion/styles.js +49 -0
  5. package/lib/commonjs/components/Accordion/styles.js.map +1 -0
  6. package/lib/commonjs/components/Slider/getSliderPopupPosition.js +14 -0
  7. package/lib/commonjs/components/Slider/getSliderPopupPosition.js.map +1 -1
  8. package/lib/commonjs/components/Slider/index.js +43 -12
  9. package/lib/commonjs/components/Slider/index.js.map +1 -1
  10. package/lib/commonjs/components/index.js +12 -0
  11. package/lib/commonjs/components/index.js.map +1 -1
  12. package/lib/commonjs/figma/Accordion.figma.js +47 -0
  13. package/lib/commonjs/figma/Accordion.figma.js.map +1 -0
  14. package/lib/module/components/Accordion/index.js +291 -0
  15. package/lib/module/components/Accordion/index.js.map +1 -0
  16. package/lib/module/components/Accordion/styles.js +45 -0
  17. package/lib/module/components/Accordion/styles.js.map +1 -0
  18. package/lib/module/components/Slider/getSliderPopupPosition.js +13 -0
  19. package/lib/module/components/Slider/getSliderPopupPosition.js.map +1 -1
  20. package/lib/module/components/Slider/index.js +46 -15
  21. package/lib/module/components/Slider/index.js.map +1 -1
  22. package/lib/module/components/index.js +1 -0
  23. package/lib/module/components/index.js.map +1 -1
  24. package/lib/module/figma/Accordion.figma.js +41 -0
  25. package/lib/module/figma/Accordion.figma.js.map +1 -0
  26. package/lib/typescript/components/Accordion/index.d.ts +85 -0
  27. package/lib/typescript/components/Accordion/index.d.ts.map +1 -0
  28. package/lib/typescript/components/Accordion/styles.d.ts +18 -0
  29. package/lib/typescript/components/Accordion/styles.d.ts.map +1 -0
  30. package/lib/typescript/components/Slider/getSliderPopupPosition.d.ts +5 -0
  31. package/lib/typescript/components/Slider/getSliderPopupPosition.d.ts.map +1 -1
  32. package/lib/typescript/components/Slider/index.d.ts +6 -1
  33. package/lib/typescript/components/Slider/index.d.ts.map +1 -1
  34. package/lib/typescript/components/index.d.ts +1 -0
  35. package/lib/typescript/components/index.d.ts.map +1 -1
  36. package/lib/typescript/figma/Accordion.figma.d.ts +8 -0
  37. package/lib/typescript/figma/Accordion.figma.d.ts.map +1 -0
  38. package/lib/typescript/figma/Alert.Button.figma.d.ts +1 -1
  39. package/lib/typescript/figma/Alert.Close.figma.d.ts +1 -1
  40. package/package.json +5 -5
  41. package/src/components/Accordion/index.tsx +388 -0
  42. package/src/components/Accordion/styles.ts +82 -0
  43. package/src/components/Slider/getSliderPopupPosition.ts +21 -0
  44. package/src/components/Slider/index.tsx +71 -23
  45. package/src/components/index.ts +1 -0
@@ -3,8 +3,11 @@ import {
3
3
  cloneElement,
4
4
  forwardRef,
5
5
  isValidElement,
6
+ useCallback,
6
7
  useId,
7
8
  useMemo,
9
+ useRef,
10
+ useState,
8
11
  type ReactElement,
9
12
  type ReactNode,
10
13
  } from 'react';
@@ -18,16 +21,19 @@ import {
18
21
  createPortalFn,
19
22
  useAnchoredOverlay,
20
23
  dataAttributes,
24
+ getFillExtent,
21
25
  getMarkerPositionStyle,
22
26
  getMarkerStepValues,
23
27
  mergeDataAttributes,
24
- percentToFillExtent,
25
28
  useSliderContext,
29
+ useSliderThumbContext,
26
30
  valueToPercent,
27
31
  type ISliderProps,
28
32
  type ISliderRailProps,
29
33
  type ISliderThumbProps,
30
34
  type SliderOrientation,
35
+ type SliderRangeValueProps,
36
+ type SliderSingleValueProps,
31
37
  } from '@cdx-ui/primitives';
32
38
  import {
33
39
  cn,
@@ -49,7 +55,12 @@ import {
49
55
  type SliderColor,
50
56
  type SliderVariantProps,
51
57
  } from './styles';
52
- import { SLIDER_POPUP_OFFSET, SLIDER_POPUP_Z_INDEX } from './getSliderPopupPosition';
58
+ import {
59
+ getSliderPopupPortalStyle,
60
+ SLIDER_POPUP_OFFSET,
61
+ SLIDER_POPUP_Z_INDEX,
62
+ type SliderPopupPortalOrigin,
63
+ } from './getSliderPopupPosition';
53
64
 
54
65
  const SCOPE = 'SLIDER';
55
66
 
@@ -76,6 +87,8 @@ export interface SliderProps extends Omit<ISliderProps, 'orientation'> {
76
87
  children?: ReactNode;
77
88
  }
78
89
 
90
+ export type { SliderRangeValueProps, SliderSingleValueProps };
91
+
79
92
  const SliderRoot = forwardRef<View, SliderProps>(
80
93
  (
81
94
  {
@@ -153,7 +166,7 @@ export interface SliderTrackProps extends ViewProps {
153
166
  const SliderTrack = forwardRef<View, SliderTrackProps>(
154
167
  ({ asChild, className, style, children, testID, ...props }, ref) => {
155
168
  const { color, orientation } = useSliderStyleContext();
156
- const { percent, isDragging, trackLayout, thumbSize } = useSliderContext();
169
+ const { values, isDragging, trackLayout, thumbSize, getThumbPercent } = useSliderContext();
157
170
 
158
171
  const fillStyle = useMemo((): ViewStyle => {
159
172
  const trackSize =
@@ -169,15 +182,18 @@ const SliderTrack = forwardRef<View, SliderTrackProps>(
169
182
  : { position: 'absolute', top: 0, bottom: 0, left: 0, width: 0 };
170
183
  }
171
184
 
172
- const extent = percentToFillExtent(percent, trackSize, thumbSize);
185
+ const isSingleThumb = values.length <= 1;
186
+ const startPercent = isSingleThumb ? 0 : getThumbPercent(0);
187
+ const endPercent = isSingleThumb ? getThumbPercent(0) : getThumbPercent(values.length - 1);
188
+ const { offset, length } = getFillExtent(startPercent, endPercent, trackSize, thumbSize);
173
189
 
174
190
  if (orientation === 'vertical') {
175
191
  return {
176
192
  position: 'absolute',
177
193
  left: 0,
178
194
  right: 0,
179
- bottom: 0,
180
- height: extent,
195
+ bottom: offset,
196
+ height: length,
181
197
  };
182
198
  }
183
199
 
@@ -185,10 +201,10 @@ const SliderTrack = forwardRef<View, SliderTrackProps>(
185
201
  position: 'absolute',
186
202
  top: 0,
187
203
  bottom: 0,
188
- left: 0,
189
- width: extent,
204
+ left: offset,
205
+ width: length,
190
206
  };
191
- }, [orientation, percent, thumbSize, trackLayout]);
207
+ }, [getThumbPercent, orientation, thumbSize, trackLayout, values.length]);
192
208
 
193
209
  const computedClassName = cn(
194
210
  sliderTrackVariants({ orientation }),
@@ -221,17 +237,27 @@ SliderTrack.displayName = 'Slider.Track';
221
237
 
222
238
  export interface SliderThumbProps extends ISliderThumbProps {
223
239
  className?: string;
240
+ /**
241
+ * Zero-based thumb index. Defaults to `0` for single-value sliders.
242
+ */
243
+ index?: number;
224
244
  children?: ReactNode;
225
245
  }
226
246
 
227
247
  const SliderThumb = forwardRef<View, SliderThumbProps>(
228
- ({ className, style, children, ...props }, ref) => {
248
+ ({ className, style, index, children, ...props }, ref) => {
229
249
  const { color } = useSliderStyleContext();
230
250
 
231
251
  const computedClassName = cn(sliderThumbVariants({ color }), className);
232
252
 
233
253
  return (
234
- <SliderThumbPrimitive ref={ref} className={computedClassName} style={style} {...props}>
254
+ <SliderThumbPrimitive
255
+ ref={ref}
256
+ index={index}
257
+ className={computedClassName}
258
+ style={style}
259
+ {...props}
260
+ >
235
261
  {children}
236
262
  </SliderThumbPrimitive>
237
263
  );
@@ -265,9 +291,11 @@ export interface SliderPopupProps extends ViewProps {
265
291
  const SliderPopup = forwardRef<View, SliderPopupProps>(
266
292
  ({ asChild, className, style, children, onLayout, ...props }, ref) => {
267
293
  const { orientation } = useSliderStyleContext();
268
- const { isDragging, isHovered, isFocused, getValueLabel, thumbRef, percent } =
269
- useSliderContext();
294
+ const { index, isDragging, isHovered, isFocused, thumbRef, percent } = useSliderThumbContext();
295
+ const { getThumbValueLabel } = useSliderContext();
270
296
  const portalName = useId();
297
+ const portalRef = useRef<View>(null);
298
+ const [portalOrigin, setPortalOrigin] = useState<SliderPopupPortalOrigin | null>(null);
271
299
 
272
300
  const visible = isDragging || isHovered || isFocused;
273
301
  const {
@@ -282,17 +310,39 @@ const SliderPopup = forwardRef<View, SliderPopupProps>(
282
310
  remeasureKey: percent,
283
311
  trackWhileOpen: true,
284
312
  });
313
+ const measurePortalOrigin = useCallback(() => {
314
+ if (Platform.OS === 'web' || orientation !== 'vertical') {
315
+ return;
316
+ }
317
+
318
+ portalRef.current?.measureInWindow((x, y) => {
319
+ setPortalOrigin((previous) =>
320
+ previous?.x === x && previous.y === y ? previous : { x, y },
321
+ );
322
+ });
323
+ }, [orientation]);
324
+ const resolvedPopupPositionStyle = useMemo(
325
+ () =>
326
+ Platform.OS !== 'web' && orientation === 'vertical'
327
+ ? getSliderPopupPortalStyle(popupPositionStyle, portalOrigin)
328
+ : popupPositionStyle,
329
+ [orientation, popupPositionStyle, portalOrigin],
330
+ );
285
331
 
286
332
  if (!visible) {
287
333
  return null;
288
334
  }
289
335
 
336
+ const getValueLabel = () => getThumbValueLabel(index);
290
337
  const label = renderPopupLabel(children, getValueLabel);
291
338
  const computedClassName = cn(sliderPopupBaseVariants(), className);
292
339
  const Comp = asChild ? Slot : View;
293
340
 
294
341
  const popup = (
295
- <View pointerEvents="none" style={[popupPositionStyle, { zIndex: SLIDER_POPUP_Z_INDEX }]}>
342
+ <View
343
+ pointerEvents="none"
344
+ style={[resolvedPopupPositionStyle, { zIndex: SLIDER_POPUP_Z_INDEX }]}
345
+ >
296
346
  <Comp
297
347
  ref={mergeRefs(ref, floatingRef)}
298
348
  className={computedClassName}
@@ -319,8 +369,10 @@ const SliderPopup = forwardRef<View, SliderPopupProps>(
319
369
  return (
320
370
  <Portal name={portalName}>
321
371
  <View
372
+ ref={portalRef}
322
373
  pointerEvents="box-none"
323
374
  style={[StyleSheet.absoluteFill, { zIndex: SLIDER_POPUP_Z_INDEX }]}
375
+ onLayout={measurePortalOrigin}
324
376
  >
325
377
  {popup}
326
378
  </View>
@@ -340,14 +392,7 @@ export interface SliderMarkerProps extends ViewProps {
340
392
 
341
393
  const SliderMarker = forwardRef<View, SliderMarkerProps>(
342
394
  ({ asChild, className, style, value, testID, ...props }, ref) => {
343
- const {
344
- value: currentValue,
345
- min,
346
- max,
347
- orientation,
348
- trackLayout,
349
- thumbSize,
350
- } = useSliderContext();
395
+ const { values, min, max, orientation, trackLayout, thumbSize } = useSliderContext();
351
396
 
352
397
  const markerStyle = useMemo(() => {
353
398
  if (value == null) {
@@ -357,7 +402,10 @@ const SliderMarker = forwardRef<View, SliderMarkerProps>(
357
402
  return getMarkerPositionStyle(percent, orientation, trackLayout, thumbSize);
358
403
  }, [max, min, orientation, thumbSize, trackLayout, value]);
359
404
 
360
- const isFilled = value != null && value <= currentValue;
405
+ const low = values[0] ?? min;
406
+ const high = values[values.length - 1] ?? low;
407
+ const isFilled =
408
+ value != null && (values.length <= 1 ? value <= low : value >= low && value <= high);
361
409
  const computedClassName = cn(sliderMarkerVariants({ filled: isFilled }), className);
362
410
  const Comp = asChild ? Slot : View;
363
411
 
@@ -31,6 +31,7 @@ export * from './Input';
31
31
  export * from './OtpInput';
32
32
  export * from './Link';
33
33
  export * from './ListItem';
34
+ export * from './Accordion';
34
35
  export * from './Menu';
35
36
  export * from './ProgressBar';
36
37
  export * from './ProgressCircle';