@spark-ui/components 10.11.14 → 10.13.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.
@@ -51,6 +51,10 @@ interface UseCarouselProps {
51
51
  scrollBehavior?: 'instant' | 'smooth';
52
52
  onPageChange?: (pageIndex: number) => void;
53
53
  pagePickerInset?: boolean;
54
+ /**
55
+ * Maximum number of dots to display in the page picker.
56
+ */
57
+ maxDots?: number;
54
58
  }
55
59
  interface ComputedRootProps {
56
60
  id: string;
@@ -120,7 +124,7 @@ interface ComputedIndicatorProps {
120
124
  'data-part': 'indicator';
121
125
  'data-orientation': 'horizontal';
122
126
  'data-index': number;
123
- 'data-state': 'active' | 'inactive';
127
+ 'data-state': 'active' | 'edge' | 'hidden' | 'idle';
124
128
  tabIndex: 0 | -1;
125
129
  onClick: () => void;
126
130
  onKeyDown: (event: KeyboardEvent) => void;
@@ -159,6 +163,7 @@ interface CarouselAPI extends AnatomyPropsSetters {
159
163
  snapType: UseCarouselProps['snapType'];
160
164
  snapStop: UseCarouselProps['snapStop'];
161
165
  scrollBehavior: UseCarouselProps['scrollBehavior'];
166
+ maxDots: number;
162
167
  }
163
168
 
164
169
  interface Props$4 extends UseCarouselProps, ComponentProps<'div'> {
@@ -166,7 +171,7 @@ interface Props$4 extends UseCarouselProps, ComponentProps<'div'> {
166
171
  className?: string;
167
172
  }
168
173
  declare const Carousel$1: {
169
- ({ className, snapType, snapStop, scrollBehavior, slidesPerMove, pagePickerInset, slidesPerPage, loop, children, gap, defaultPage, page, onPageChange, ...props }: Props$4): react_jsx_runtime.JSX.Element;
174
+ ({ className, snapType, snapStop, scrollBehavior, slidesPerMove, pagePickerInset, slidesPerPage, loop, children, gap, defaultPage, page, onPageChange, maxDots, ...props }: Props$4): react_jsx_runtime.JSX.Element;
170
175
  displayName: string;
171
176
  };
172
177
 
@@ -51,6 +51,10 @@ interface UseCarouselProps {
51
51
  scrollBehavior?: 'instant' | 'smooth';
52
52
  onPageChange?: (pageIndex: number) => void;
53
53
  pagePickerInset?: boolean;
54
+ /**
55
+ * Maximum number of dots to display in the page picker.
56
+ */
57
+ maxDots?: number;
54
58
  }
55
59
  interface ComputedRootProps {
56
60
  id: string;
@@ -120,7 +124,7 @@ interface ComputedIndicatorProps {
120
124
  'data-part': 'indicator';
121
125
  'data-orientation': 'horizontal';
122
126
  'data-index': number;
123
- 'data-state': 'active' | 'inactive';
127
+ 'data-state': 'active' | 'edge' | 'hidden' | 'idle';
124
128
  tabIndex: 0 | -1;
125
129
  onClick: () => void;
126
130
  onKeyDown: (event: KeyboardEvent) => void;
@@ -159,6 +163,7 @@ interface CarouselAPI extends AnatomyPropsSetters {
159
163
  snapType: UseCarouselProps['snapType'];
160
164
  snapStop: UseCarouselProps['snapStop'];
161
165
  scrollBehavior: UseCarouselProps['scrollBehavior'];
166
+ maxDots: number;
162
167
  }
163
168
 
164
169
  interface Props$4 extends UseCarouselProps, ComponentProps<'div'> {
@@ -166,7 +171,7 @@ interface Props$4 extends UseCarouselProps, ComponentProps<'div'> {
166
171
  className?: string;
167
172
  }
168
173
  declare const Carousel$1: {
169
- ({ className, snapType, snapStop, scrollBehavior, slidesPerMove, pagePickerInset, slidesPerPage, loop, children, gap, defaultPage, page, onPageChange, ...props }: Props$4): react_jsx_runtime.JSX.Element;
174
+ ({ className, snapType, snapStop, scrollBehavior, slidesPerMove, pagePickerInset, slidesPerPage, loop, children, gap, defaultPage, page, onPageChange, maxDots, ...props }: Props$4): react_jsx_runtime.JSX.Element;
170
175
  displayName: string;
171
176
  };
172
177
 
@@ -163,6 +163,35 @@ function getSnapPositions({
163
163
  });
164
164
  }).map((slide) => slide.offsetLeft);
165
165
  }
166
+ function computeDotState({
167
+ dotIndex,
168
+ pageState,
169
+ totalPages,
170
+ maxDots = 5
171
+ }) {
172
+ if (totalPages <= maxDots) {
173
+ return dotIndex === pageState ? "active" : "idle";
174
+ }
175
+ if (pageState <= Math.floor(maxDots / 2)) {
176
+ if (dotIndex > maxDots - 1) return "hidden";
177
+ if (dotIndex === pageState) return "active";
178
+ if (dotIndex === maxDots - 1) return "edge";
179
+ return "idle";
180
+ }
181
+ if (pageState >= totalPages - Math.ceil(maxDots / 2)) {
182
+ const startIndex2 = totalPages - maxDots;
183
+ if (dotIndex < startIndex2) return "hidden";
184
+ if (dotIndex === pageState) return "active";
185
+ if (dotIndex === startIndex2) return "edge";
186
+ return "idle";
187
+ }
188
+ const startIndex = pageState - Math.floor(maxDots / 2);
189
+ const endIndex = pageState + Math.floor(maxDots / 2);
190
+ if (dotIndex < startIndex || dotIndex > endIndex) return "hidden";
191
+ if (dotIndex === pageState) return "active";
192
+ if (dotIndex === startIndex || dotIndex === endIndex) return "edge";
193
+ return "idle";
194
+ }
166
195
 
167
196
  // src/carousel/useSnapPoints.ts
168
197
  function useSnapPoints(initialSnapPoints = [], {
@@ -199,6 +228,7 @@ var useCarousel = ({
199
228
  scrollBehavior = "smooth",
200
229
  loop = false,
201
230
  pagePickerInset = false,
231
+ maxDots = 5,
202
232
  // state control
203
233
  page: controlledPage,
204
234
  onPageChange: onPageChangeProp
@@ -301,6 +331,7 @@ var useCarousel = ({
301
331
  scrollBehavior,
302
332
  loop,
303
333
  pagePickerInset,
334
+ maxDots,
304
335
  // computed state
305
336
  page: pageState,
306
337
  pageSnapPoints,
@@ -409,17 +440,22 @@ var useCarousel = ({
409
440
  dir: DIRECTION
410
441
  }),
411
442
  getIndicatorProps: ({ index }) => {
412
- const isActivePage = index === pageState;
443
+ const dotState = computeDotState({
444
+ dotIndex: index,
445
+ pageState,
446
+ totalPages: pageSnapPoints.length,
447
+ maxDots
448
+ });
413
449
  return {
414
450
  role: "radio",
415
451
  id: `carousel::${carouselId}::indicator:${index}`,
416
- "aria-checked": isActivePage,
452
+ "aria-checked": index === pageState,
417
453
  "data-scope": DATA_SCOPE,
418
454
  "data-part": "indicator",
419
455
  "data-orientation": "horizontal",
420
456
  "data-index": index,
421
- "data-state": isActivePage ? "active" : "inactive",
422
- tabIndex: isActivePage ? 0 : -1,
457
+ "data-state": dotState,
458
+ tabIndex: index === pageState ? 0 : -1,
423
459
  onClick: () => {
424
460
  scrollTo(index, scrollBehavior);
425
461
  },
@@ -456,6 +492,7 @@ var Carousel = ({
456
492
  defaultPage,
457
493
  page,
458
494
  onPageChange,
495
+ maxDots = 5,
459
496
  ...props
460
497
  }) => {
461
498
  const carouselApi = useCarousel({
@@ -469,7 +506,8 @@ var Carousel = ({
469
506
  snapType,
470
507
  page,
471
508
  pagePickerInset,
472
- onPageChange
509
+ onPageChange,
510
+ maxDots
473
511
  });
474
512
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
475
513
  CarouselContext.Provider,
@@ -1576,28 +1614,26 @@ var CarouselPageIndicator = ({
1576
1614
  ctx.pageIndicatorsRefs.current[index] = ref.current;
1577
1615
  }
1578
1616
  });
1579
- const styles = (0, import_class_variance_authority8.cx)(
1580
- "group h-sz-16 relative flex",
1581
- "hover:cursor-pointer",
1582
- "w-sz-16 data-[state=active]:w-sz-44"
1583
- );
1584
- const dotsStyles = (0, import_class_variance_authority8.cx)(
1585
- "before:rounded-sm before:block before:size-md",
1586
- "before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
1587
- "data-[state=active]:before:w-sz-32",
1588
- intent === "surface" ? "data-[state=active]:before:bg-surface data-[state=inactive]:before:bg-surface/dim-2" : "data-[state=active]:before:bg-basic data-[state=inactive]:before:bg-on-surface/dim-2"
1589
- );
1617
+ const indicatorProps = ctx.getIndicatorProps({ index });
1590
1618
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1591
1619
  "button",
1592
1620
  {
1593
1621
  "data-spark-component": "carousel-page-indicator",
1594
1622
  ref,
1595
- ...ctx.getIndicatorProps({ index }),
1623
+ ...indicatorProps,
1596
1624
  "aria-label": ariaLabel,
1597
1625
  className: (0, import_class_variance_authority8.cx)(
1598
1626
  {
1599
- [styles]: !unstyled,
1600
- [dotsStyles]: !unstyled
1627
+ [(0, import_class_variance_authority8.cx)(
1628
+ "border-outline group relative flex justify-center border-0 hover:cursor-pointer",
1629
+ "m-sm rounded-sm transition-all duration-[200ms] ease-linear",
1630
+ "w-sz-8 h-sz-8",
1631
+ "data-[state=active]:w-sz-32 data-[state=active]:h-sz-8",
1632
+ "data-[state=edge]:w-sz-4 data-[state=edge]:h-sz-4",
1633
+ "data-[state=hidden]:size-0",
1634
+ intent === "surface" ? "data-[state=active]:bg-surface bg-surface/dim-2" : "data-[state=active]:bg-basic bg-on-surface/dim-2"
1635
+ )]: !unstyled
1636
+ // [dotsStyles]: !unstyled,
1601
1637
  },
1602
1638
  className
1603
1639
  ),
@@ -1619,7 +1655,8 @@ var CarouselPagePicker = ({ children, className }) => {
1619
1655
  "data-spark-component": "carousel-page-picker",
1620
1656
  ...ctx.getIndicatorGroupProps(),
1621
1657
  className: (0, import_class_variance_authority9.cx)(
1622
- "default:min-h-sz-16 flex w-full flex-wrap items-center justify-center",
1658
+ "flex-wrap items-center justify-center",
1659
+ "default:min-h-sz-16 flex",
1623
1660
  ctx.pagePickerInset && "bottom-sz-12 absolute inset-x-0",
1624
1661
  className
1625
1662
  ),