@rcarls/rc-carousel 0.1.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.
@@ -0,0 +1,937 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/define.ts",
8
+ "declarations": [],
9
+ "exports": [
10
+ {
11
+ "kind": "custom-element-definition",
12
+ "name": "rc-carousel-item",
13
+ "declaration": {
14
+ "name": "RCCarouselItem",
15
+ "module": "/src/index.js"
16
+ }
17
+ },
18
+ {
19
+ "kind": "custom-element-definition",
20
+ "name": "rc-carousel",
21
+ "declaration": {
22
+ "name": "RCCarousel",
23
+ "module": "/src/index.js"
24
+ }
25
+ },
26
+ {
27
+ "kind": "js",
28
+ "name": "*",
29
+ "declaration": {
30
+ "name": "*",
31
+ "module": "src/index.js"
32
+ }
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "kind": "javascript-module",
38
+ "path": "src/index.ts",
39
+ "declarations": [],
40
+ "exports": [
41
+ {
42
+ "kind": "js",
43
+ "name": "*",
44
+ "declaration": {
45
+ "name": "*",
46
+ "module": "src/rc-carousel-item.js"
47
+ }
48
+ },
49
+ {
50
+ "kind": "js",
51
+ "name": "*",
52
+ "declaration": {
53
+ "name": "*",
54
+ "module": "src/rc-carousel.js"
55
+ }
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "kind": "javascript-module",
61
+ "path": "src/rc-carousel-item.ts",
62
+ "declarations": [
63
+ {
64
+ "kind": "class",
65
+ "description": "One slide of an `rc-carousel`. Participates directly in the parent's\nscroll-snap track as a grid-auto-flow child — `rc-carousel-item` owns its\nown snap alignment and accessibility state, but authored content (an\n`<img>` with real alt text, arbitrary markup) stays exactly as slotted,\nnever cloned or re-parented, so it remains directly available to forms,\nlabels, and assistive technology.\n\nWhile off-screen (not the intersecting slide, including a partially\nvisible peek), the slide is marked `aria-hidden` and `inert`: it stays\nvisually and pointer-interactively present as a peek affordance, but\ndrops out of the accessibility tree and the Tab sequence, so a slide's\ninteractive descendants (a button, a link) can't be reached by keyboard\nor announced by a screen reader until their slide is actually active.",
66
+ "name": "RCCarouselItem",
67
+ "cssProperties": [
68
+ {
69
+ "description": "Slide foreground color.",
70
+ "name": "--rc-carousel-item-color",
71
+ "default": "CanvasText"
72
+ },
73
+ {
74
+ "description": "Snap alignment within the track. Override for a center-aligned layout.",
75
+ "name": "--rc-carousel-item-scroll-snap-align",
76
+ "default": "start"
77
+ },
78
+ {
79
+ "description": "Slide surface background, e.g. for an MD3 card-like slide shape.",
80
+ "name": "--rc-carousel-item-background",
81
+ "default": "transparent"
82
+ },
83
+ {
84
+ "description": "Slide corner radius.",
85
+ "name": "--rc-carousel-item-border-radius",
86
+ "default": "0"
87
+ },
88
+ {
89
+ "description": "Overflow behavior for slotted content that exceeds the slide's own box. `hidden` clips to the corner radius (matching media-item slides); text-heavy slides that need their own internal scroll may want `auto` instead.",
90
+ "name": "--rc-carousel-item-overflow",
91
+ "default": "hidden"
92
+ }
93
+ ],
94
+ "slots": [
95
+ {
96
+ "description": "Slide content.",
97
+ "name": ""
98
+ }
99
+ ],
100
+ "members": [
101
+ {
102
+ "kind": "field",
103
+ "name": "_internals",
104
+ "type": {
105
+ "text": "ElementInternals"
106
+ },
107
+ "privacy": "private",
108
+ "readonly": true
109
+ },
110
+ {
111
+ "kind": "field",
112
+ "name": "_intersectionObserver",
113
+ "type": {
114
+ "text": "IntersectionObserver | null"
115
+ },
116
+ "privacy": "private",
117
+ "default": "null"
118
+ },
119
+ {
120
+ "kind": "field",
121
+ "name": "position",
122
+ "type": {
123
+ "text": "string"
124
+ },
125
+ "default": "''",
126
+ "description": "\"N of M\" position assigned by the parent `rc-carousel`. Internal\nintegration point, not a public API — see the `@attr` note above."
127
+ },
128
+ {
129
+ "kind": "method",
130
+ "name": "_syncDefaultLabel",
131
+ "privacy": "private",
132
+ "return": {
133
+ "type": {
134
+ "text": "void"
135
+ }
136
+ }
137
+ },
138
+ {
139
+ "kind": "method",
140
+ "name": "_observeIntersection",
141
+ "privacy": "private",
142
+ "return": {
143
+ "type": {
144
+ "text": "Promise<void>"
145
+ }
146
+ },
147
+ "description": "Observes intersection against the parent carousel's own scroll\ncontainer (not the viewport — a slide can be viewport-visible yet\nstill clipped/off-screen within the track on a page where the\ncarousel isn't the whole viewport). Reads `trackElement` off the\nparent `rc-carousel`, an internal integration point rather than a\npublic API — awaits the parent's own first render first, since a\nslotted item's `connectedCallback` isn't guaranteed to run after its\nhost's, and `trackElement` only exists once the host has rendered."
148
+ },
149
+ {
150
+ "kind": "field",
151
+ "name": "role",
152
+ "type": {
153
+ "text": "string"
154
+ },
155
+ "default": "'group'"
156
+ }
157
+ ],
158
+ "superclass": {
159
+ "name": "LitElement",
160
+ "package": "lit"
161
+ },
162
+ "tagName": "rc-carousel-item",
163
+ "customElement": true
164
+ }
165
+ ],
166
+ "exports": [
167
+ {
168
+ "kind": "js",
169
+ "name": "RCCarouselItem",
170
+ "declaration": {
171
+ "name": "RCCarouselItem",
172
+ "module": "src/rc-carousel-item.ts"
173
+ }
174
+ }
175
+ ]
176
+ },
177
+ {
178
+ "kind": "javascript-module",
179
+ "path": "src/rc-carousel.ts",
180
+ "declarations": [
181
+ {
182
+ "kind": "class",
183
+ "description": "WAI-ARIA APG carousel pattern built on native CSS scroll-snap. One\n`rc-carousel-item` per slide, swiped or paged between; the track's own\nnative scroll-snap settling (not a hand-rolled drag simulation) is the\nprimary interaction, per this monorepo's \"build on native browser\nbehavior\" principle.\n\n`activeIndex` is a controlled/uncontrolled property, mirroring\n`rc-adaptive-menu`'s `open`/`defaultOpen` pair: leave it unset for\nuncontrolled usage (`default-active-index` seeds the initial slide),\nor set it directly to drive the carousel externally — a settle from\nswipe, a keyboard action, or the imperative API all report back through\n`rc-carousel-change` rather than silently self-correcting a controlled\nvalue out from under the consumer.\n\nPrevious/next navigation and a slide picker are both opt-in\n(`navigation`/`pagination`), following the WAI-ARIA APG carousel\npattern's \"grouped\" (non-tab) picker style deliberately: the tabbed\n`role=\"tabpanel\"` variant requires cross-references between light-DOM\nslides and shadow-DOM tab buttons that, in comparable shadow-DOM\ncarousels, has hit real accessibility-tooling failures across the\nshadow boundary (including non-recognition by some screen readers\nentirely). `loop` wraps seamlessly via cloned lead/trail slides rather\nthan a discontinuous jump back to the other end.",
184
+ "name": "RCCarousel",
185
+ "cssProperties": [
186
+ {
187
+ "description": "Carousel foreground color.",
188
+ "name": "--rc-carousel-color",
189
+ "default": "CanvasText"
190
+ },
191
+ {
192
+ "description": "Space between slides.",
193
+ "name": "--rc-carousel-gap",
194
+ "default": "8px"
195
+ },
196
+ {
197
+ "description": "Rendered size of each slide along the scroll axis. Set this directly or from a consumer container query to coordinate hero and multi-browse layouts.",
198
+ "name": "--rc-carousel-slide-size",
199
+ "default": "calc(100% - 4rem)"
200
+ },
201
+ {
202
+ "description": "Previous/next button diameter.",
203
+ "name": "--rc-carousel-navigation-button-size",
204
+ "default": "40px"
205
+ },
206
+ {
207
+ "description": "Previous/next button background.",
208
+ "name": "--rc-carousel-navigation-button-background",
209
+ "default": "color-mix(in srgb, CanvasText 12%, transparent)"
210
+ },
211
+ {
212
+ "description": "Previous/next button icon color.",
213
+ "name": "--rc-carousel-navigation-button-color",
214
+ "default": "CanvasText"
215
+ },
216
+ {
217
+ "description": "Previous/next button inset from the track edge.",
218
+ "name": "--rc-carousel-navigation-inset",
219
+ "default": "8px"
220
+ },
221
+ {
222
+ "description": "Slide-picker dot diameter.",
223
+ "name": "--rc-carousel-pagination-item-size",
224
+ "default": "8px"
225
+ },
226
+ {
227
+ "description": "Inactive slide-picker dot color.",
228
+ "name": "--rc-carousel-pagination-item-color",
229
+ "default": "color-mix(in srgb, CanvasText 40%, transparent)"
230
+ },
231
+ {
232
+ "description": "Active slide-picker dot color.",
233
+ "name": "--rc-carousel-pagination-item-active-color",
234
+ "default": "Highlight"
235
+ }
236
+ ],
237
+ "cssParts": [
238
+ {
239
+ "description": "The scrollable slide track.",
240
+ "name": "track"
241
+ },
242
+ {
243
+ "description": "Previous/next button wrapper.",
244
+ "name": "navigation"
245
+ },
246
+ {
247
+ "description": "A previous or next button.",
248
+ "name": "navigation-button"
249
+ },
250
+ {
251
+ "description": "The previous button specifically.",
252
+ "name": "navigation-button-previous"
253
+ },
254
+ {
255
+ "description": "The next button specifically.",
256
+ "name": "navigation-button-next"
257
+ },
258
+ {
259
+ "description": "Slide-picker button group wrapper.",
260
+ "name": "pagination"
261
+ },
262
+ {
263
+ "description": "A slide-picker button.",
264
+ "name": "pagination-item"
265
+ },
266
+ {
267
+ "description": "The active slide's picker button.",
268
+ "name": "pagination-item-active"
269
+ }
270
+ ],
271
+ "slots": [
272
+ {
273
+ "description": "One or more `rc-carousel-item` elements.",
274
+ "name": ""
275
+ },
276
+ {
277
+ "description": "Optional icon for the previous button, replacing the default chevron. Only rendered when `navigation` is set.",
278
+ "name": "previous-icon"
279
+ },
280
+ {
281
+ "description": "Optional icon for the next button, replacing the default chevron. Only rendered when `navigation` is set.",
282
+ "name": "next-icon"
283
+ }
284
+ ],
285
+ "members": [
286
+ {
287
+ "kind": "field",
288
+ "name": "_internals",
289
+ "type": {
290
+ "text": "ElementInternals"
291
+ },
292
+ "privacy": "private",
293
+ "readonly": true
294
+ },
295
+ {
296
+ "kind": "field",
297
+ "name": "_trackEl",
298
+ "type": {
299
+ "text": "HTMLDivElement | undefined"
300
+ },
301
+ "privacy": "private"
302
+ },
303
+ {
304
+ "kind": "field",
305
+ "name": "_slotEl",
306
+ "type": {
307
+ "text": "HTMLSlotElement | undefined"
308
+ },
309
+ "privacy": "private"
310
+ },
311
+ {
312
+ "kind": "field",
313
+ "name": "_items",
314
+ "type": {
315
+ "text": "RCCarouselItem[]"
316
+ },
317
+ "privacy": "private",
318
+ "default": "[]"
319
+ },
320
+ {
321
+ "kind": "field",
322
+ "name": "_cloneItems",
323
+ "type": {
324
+ "text": "RCCarouselItem[]"
325
+ },
326
+ "privacy": "private",
327
+ "default": "[]"
328
+ },
329
+ {
330
+ "kind": "field",
331
+ "name": "_mounted",
332
+ "type": {
333
+ "text": "boolean"
334
+ },
335
+ "privacy": "private",
336
+ "default": "false"
337
+ },
338
+ {
339
+ "kind": "field",
340
+ "name": "_suppressSync",
341
+ "type": {
342
+ "text": "boolean"
343
+ },
344
+ "privacy": "private",
345
+ "default": "false"
346
+ },
347
+ {
348
+ "kind": "field",
349
+ "name": "_pendingInstant",
350
+ "type": {
351
+ "text": "boolean"
352
+ },
353
+ "privacy": "private",
354
+ "default": "false"
355
+ },
356
+ {
357
+ "kind": "field",
358
+ "name": "_settleTimer",
359
+ "type": {
360
+ "text": "ReturnType<typeof setTimeout> | undefined"
361
+ },
362
+ "privacy": "private"
363
+ },
364
+ {
365
+ "kind": "field",
366
+ "name": "loop",
367
+ "type": {
368
+ "text": "boolean"
369
+ },
370
+ "default": "false",
371
+ "description": "Wraps past the first/last slide back to the other end, seamlessly.",
372
+ "attribute": "loop",
373
+ "reflects": true
374
+ },
375
+ {
376
+ "kind": "field",
377
+ "name": "navigation",
378
+ "type": {
379
+ "text": "boolean"
380
+ },
381
+ "default": "false",
382
+ "description": "Shows previous/next buttons.",
383
+ "attribute": "navigation",
384
+ "reflects": true
385
+ },
386
+ {
387
+ "kind": "field",
388
+ "name": "pagination",
389
+ "type": {
390
+ "text": "boolean"
391
+ },
392
+ "default": "false",
393
+ "description": "Shows a slide-picker button group.",
394
+ "attribute": "pagination",
395
+ "reflects": true
396
+ },
397
+ {
398
+ "kind": "field",
399
+ "name": "mouseDragging",
400
+ "type": {
401
+ "text": "boolean"
402
+ },
403
+ "default": "false",
404
+ "description": "Enables click-and-drag scrolling with a mouse — native scroll-snap\ntouch physics already cover touch/pen, but a mouse has no built-in\nequivalent. Off by default.",
405
+ "attribute": "mouse-dragging",
406
+ "reflects": true
407
+ },
408
+ {
409
+ "kind": "field",
410
+ "name": "_dragging",
411
+ "type": {
412
+ "text": "boolean"
413
+ },
414
+ "privacy": "private",
415
+ "default": "false"
416
+ },
417
+ {
418
+ "kind": "field",
419
+ "name": "_dragStartLeft",
420
+ "type": {
421
+ "text": "number"
422
+ },
423
+ "privacy": "private",
424
+ "default": "0"
425
+ },
426
+ {
427
+ "kind": "field",
428
+ "name": "_suppressNextClick",
429
+ "type": {
430
+ "text": "boolean"
431
+ },
432
+ "privacy": "private",
433
+ "default": "false"
434
+ },
435
+ {
436
+ "kind": "field",
437
+ "name": "_dragController",
438
+ "privacy": "protected",
439
+ "readonly": true,
440
+ "default": "new DragGestureController(this, { target: () => this._trackEl ?? null, axis: 'x', activation: 'axis', canStart: (event) => this.mouseDragging && event.pointerType === 'mouse', onStart: () => { this._dragging = true; this._dragStartLeft = this._trackEl?.scrollLeft ?? 0; this._suppressNextClick = true; // Imperative, not reactive-class-driven: this must land before // onMove's very first scrollLeft write below, and a Lit re-render // (triggered by _dragging above) is a whole render pass too late for // that — with scroll-snap-type still active, the browser eagerly // resnaps a plain scrollLeft assignment straight back to the // nearest snap point, same as it would any other programmatic // scroll with no notion this is \"mid-gesture\". if (this._trackEl) { this._trackEl.style.scrollSnapType = 'none'; } }, onMove: (detail) => { if (this._trackEl) { this._trackEl.scrollLeft = this._dragStartLeft - detail.deltaX; } }, onEnd: (detail) => this._endDrag(detail), onCancel: (detail) => this._endDrag(detail), })",
441
+ "description": "Drives `scrollLeft` directly from pointer deltas while `mouseDragging`\nis on. `activation: 'axis'` (not `'immediate'`) means a plain click\nnever activates a drag at all — it requires clearing\n`activationDistance` (8px) of movement first — but a *real* drag still\nends in a native `click` on release, on whatever's under the pointer,\nwhich `_suppressNextClick` swallows so dragging across an unrelated\nlink or button inside a slide doesn't activate it (the same edge case\nShoelace's own `sl-carousel` handles for exactly this reason)."
442
+ },
443
+ {
444
+ "kind": "field",
445
+ "name": "_busy",
446
+ "type": {
447
+ "text": "boolean"
448
+ },
449
+ "privacy": "private",
450
+ "default": "false"
451
+ },
452
+ {
453
+ "kind": "field",
454
+ "name": "_activeIndex",
455
+ "type": {
456
+ "text": "number | undefined"
457
+ },
458
+ "privacy": "private"
459
+ },
460
+ {
461
+ "kind": "field",
462
+ "name": "_defaultActiveIndex",
463
+ "type": {
464
+ "text": "number"
465
+ },
466
+ "privacy": "private",
467
+ "default": "0"
468
+ },
469
+ {
470
+ "kind": "field",
471
+ "name": "_uncontrolledActiveIndex",
472
+ "type": {
473
+ "text": "number | undefined"
474
+ },
475
+ "privacy": "private"
476
+ },
477
+ {
478
+ "kind": "field",
479
+ "name": "_activeIndexInitialized",
480
+ "type": {
481
+ "text": "boolean"
482
+ },
483
+ "privacy": "private",
484
+ "default": "false"
485
+ },
486
+ {
487
+ "kind": "field",
488
+ "name": "activeIndex",
489
+ "type": {
490
+ "text": "number"
491
+ },
492
+ "description": "Controls the active slide. Host writes are silent.",
493
+ "attribute": "active-index"
494
+ },
495
+ {
496
+ "kind": "field",
497
+ "name": "defaultActiveIndex",
498
+ "type": {
499
+ "text": "number"
500
+ },
501
+ "description": "Initial active slide for uncontrolled usage.",
502
+ "attribute": "default-active-index"
503
+ },
504
+ {
505
+ "kind": "field",
506
+ "name": "trackElement",
507
+ "type": {
508
+ "text": "HTMLElement | null"
509
+ },
510
+ "description": "The scroll-snap track element. Internal integration point consumed by\n`rc-carousel-item`'s IntersectionObserver (its `root` must be this\ntrack, not the viewport, so peeking/clipped-but-viewport-visible\nslides are still correctly detected as off-screen) — not a public API.",
511
+ "readonly": true
512
+ },
513
+ {
514
+ "kind": "method",
515
+ "name": "next",
516
+ "return": {
517
+ "type": {
518
+ "text": "void"
519
+ }
520
+ },
521
+ "description": "Moves to the next slide."
522
+ },
523
+ {
524
+ "kind": "method",
525
+ "name": "previous",
526
+ "return": {
527
+ "type": {
528
+ "text": "void"
529
+ }
530
+ },
531
+ "description": "Moves to the previous slide."
532
+ },
533
+ {
534
+ "kind": "method",
535
+ "name": "goToIndex",
536
+ "return": {
537
+ "type": {
538
+ "text": "void"
539
+ }
540
+ },
541
+ "parameters": [
542
+ {
543
+ "name": "index",
544
+ "type": {
545
+ "text": "number"
546
+ }
547
+ },
548
+ {
549
+ "name": "instant",
550
+ "default": "false"
551
+ }
552
+ ],
553
+ "description": "Moves directly to a slide index."
554
+ },
555
+ {
556
+ "kind": "method",
557
+ "name": "_step",
558
+ "privacy": "private",
559
+ "return": {
560
+ "type": {
561
+ "text": "void"
562
+ }
563
+ },
564
+ "parameters": [
565
+ {
566
+ "name": "delta",
567
+ "type": {
568
+ "text": "1 | -1"
569
+ }
570
+ },
571
+ {
572
+ "name": "trigger",
573
+ "type": {
574
+ "text": "RCCarouselChangeTrigger"
575
+ }
576
+ }
577
+ ]
578
+ },
579
+ {
580
+ "kind": "method",
581
+ "name": "_canStep",
582
+ "privacy": "private",
583
+ "return": {
584
+ "type": {
585
+ "text": "boolean"
586
+ }
587
+ },
588
+ "parameters": [
589
+ {
590
+ "name": "delta",
591
+ "type": {
592
+ "text": "1 | -1"
593
+ }
594
+ }
595
+ ],
596
+ "description": "Whether a previous/next button (or an equivalent keyboard action)\ncurrently has anywhere to go — always true when `loop` is set and\nthere's more than one slide."
597
+ },
598
+ {
599
+ "kind": "method",
600
+ "name": "_clampIndex",
601
+ "privacy": "private",
602
+ "return": {
603
+ "type": {
604
+ "text": "number"
605
+ }
606
+ },
607
+ "parameters": [
608
+ {
609
+ "name": "index",
610
+ "type": {
611
+ "text": "number"
612
+ }
613
+ }
614
+ ],
615
+ "description": "Wraps when `loop` is set, otherwise clamps to the real slide range.\nWrapping here covers button/keyboard navigation; a swipe wraps\nseamlessly through `_trackSlots`'s cloned lead/trail slides instead,\nsince that needs the clones' own track positions, not just an index."
616
+ },
617
+ {
618
+ "kind": "method",
619
+ "name": "_snapPoints",
620
+ "privacy": "private",
621
+ "return": {
622
+ "type": {
623
+ "text": "number[]"
624
+ }
625
+ }
626
+ },
627
+ {
628
+ "kind": "method",
629
+ "name": "_trackSlots",
630
+ "privacy": "private",
631
+ "return": {
632
+ "type": {
633
+ "text": "{ point: number; index: number; isClone: boolean }[]"
634
+ }
635
+ },
636
+ "description": "Every scrollable track position in rendered order, including cloned\nlead/trail slides when `loop` is on — `[lastClone, item0, ..., itemN-1,\nfirstClone]`. Each slot reports which real slide index it represents\n(a clone mirrors the real slide it duplicates), so both scrolling to\nan index and reading back a settled scroll position can stay in terms\nof real indices while the clones do the seamless-wrap work."
637
+ },
638
+ {
639
+ "kind": "method",
640
+ "name": "_itemStep",
641
+ "privacy": "private",
642
+ "return": {
643
+ "type": {
644
+ "text": "number"
645
+ }
646
+ }
647
+ },
648
+ {
649
+ "kind": "method",
650
+ "name": "_setActiveIndex",
651
+ "privacy": "private",
652
+ "return": {
653
+ "type": {
654
+ "text": "void"
655
+ }
656
+ },
657
+ "parameters": [
658
+ {
659
+ "name": "index",
660
+ "type": {
661
+ "text": "number"
662
+ }
663
+ },
664
+ {
665
+ "name": "trigger",
666
+ "type": {
667
+ "text": "RCCarouselChangeTrigger"
668
+ }
669
+ }
670
+ ]
671
+ },
672
+ {
673
+ "kind": "method",
674
+ "name": "_scrollToIndex",
675
+ "privacy": "private",
676
+ "return": {
677
+ "type": {
678
+ "text": "void"
679
+ }
680
+ },
681
+ "parameters": [
682
+ {
683
+ "name": "index",
684
+ "type": {
685
+ "text": "number"
686
+ }
687
+ },
688
+ {
689
+ "name": "instant",
690
+ "type": {
691
+ "text": "boolean"
692
+ }
693
+ }
694
+ ]
695
+ },
696
+ {
697
+ "kind": "field",
698
+ "name": "_onSlotChange",
699
+ "privacy": "private"
700
+ },
701
+ {
702
+ "kind": "method",
703
+ "name": "_directItems",
704
+ "privacy": "private",
705
+ "return": {
706
+ "type": {
707
+ "text": "RCCarouselItem[]"
708
+ }
709
+ }
710
+ },
711
+ {
712
+ "kind": "method",
713
+ "name": "_setItemPositions",
714
+ "privacy": "private",
715
+ "return": {
716
+ "type": {
717
+ "text": "void"
718
+ }
719
+ }
720
+ },
721
+ {
722
+ "kind": "method",
723
+ "name": "_syncItems",
724
+ "privacy": "private",
725
+ "return": {
726
+ "type": {
727
+ "text": "void"
728
+ }
729
+ },
730
+ "description": "Prepending/appending the loop clones below is itself a light-DOM\nmutation on this host, which re-fires `slotchange` (asynchronously) —\n`_onSlotChange` calls back into this method, so a naive unconditional\nremove-then-recreate would recreate a fresh pair of clones on every\npass forever. Clones are always excluded from `nextItems`, so the\nreal item list is byte-for-byte identical on that re-entrant pass;\nonly rebuild clone DOM when either the real items or the desired\nclone presence has actually changed, so the re-entrant pass is a\ntrue no-op and the recursion terminates."
731
+ },
732
+ {
733
+ "kind": "method",
734
+ "name": "_addClones",
735
+ "privacy": "private",
736
+ "return": {
737
+ "type": {
738
+ "text": "void"
739
+ }
740
+ },
741
+ "description": "Clones the first and last slide and prepends/appends them\n(`data-clone=\"<real index>\"` marks them, excluded from `_items` and\nfrom position numbering) so the track has real scrollable content\npast both visual ends. `_trackSlots`/`_commitSettledIndex` detect\nwhen a clone settles and instantly re-anchor to the real slide it\nmirrors — Shoelace's proven technique for a seamless infinite swipe,\nrather than a discontinuous index-modulo jump back to the other end."
742
+ },
743
+ {
744
+ "kind": "method",
745
+ "name": "_sanitizeClone",
746
+ "privacy": "private",
747
+ "return": {
748
+ "type": {
749
+ "text": "void"
750
+ }
751
+ },
752
+ "parameters": [
753
+ {
754
+ "name": "$clone",
755
+ "type": {
756
+ "text": "RCCarouselItem"
757
+ }
758
+ }
759
+ ],
760
+ "description": "Keeps visual loop clones out of forms, focus order, and the accessibility tree."
761
+ },
762
+ {
763
+ "kind": "method",
764
+ "name": "_removeClones",
765
+ "privacy": "private",
766
+ "return": {
767
+ "type": {
768
+ "text": "void"
769
+ }
770
+ }
771
+ },
772
+ {
773
+ "kind": "method",
774
+ "name": "_endDrag",
775
+ "privacy": "private",
776
+ "return": {
777
+ "type": {
778
+ "text": "void"
779
+ }
780
+ },
781
+ "parameters": [
782
+ {
783
+ "name": "detail",
784
+ "type": {
785
+ "text": "DragGestureDetail"
786
+ }
787
+ }
788
+ ],
789
+ "description": "On release, a fast enough flick pre-nudges `scrollLeft` to the next\nsnap point in the drag direction (a \"decisive swipe\" — mirroring\n`rc-bottom-sheet`'s own velocity-vs-nearest-point settle heuristic,\nadapted from \"jump to the extreme end\" for a 2-point sheet to \"advance\none further point\" for a carousel that can have many). Either way,\nthis hands off to the same debounced settle path a native swipe\nalready goes through — our own `scrollLeft` writes during the drag\nalready fired real `scroll` events, so `_onScroll` just needs to run\nits usual timer to pick up wherever things ended."
790
+ },
791
+ {
792
+ "kind": "field",
793
+ "name": "_onScroll",
794
+ "privacy": "private",
795
+ "description": "Debounced, not per-frame: `_scrollToIndex`'s own smooth scroll fires\nmany `scroll` events while still mid-flight, and reading the settled\nindex from an in-progress position would report the wrong slide and\nimmediately fight the very scroll driving it. Waiting for scrolling to\nactually stop (swipe release or animation end) avoids that oscillation."
796
+ },
797
+ {
798
+ "kind": "field",
799
+ "name": "_commitSettledIndex",
800
+ "privacy": "private"
801
+ },
802
+ {
803
+ "kind": "field",
804
+ "name": "_onNavigate",
805
+ "privacy": "private"
806
+ },
807
+ {
808
+ "kind": "field",
809
+ "name": "_onTrackClickCapture",
810
+ "privacy": "private",
811
+ "description": "A real drag still ends in a native `click` on release (browsers fire\none on pointerup as long as pointerdown/pointerup share a target),\nlanding on whatever's currently under the pointer — which, mid-drag,\nis often unrelated slide content the user was scrolling past, not\nclicking. Capturing and swallowing exactly one click right after a\ndrag activated (`_suppressNextClick`, set in the drag controller's\n`onStart`) stops that from reaching a link/button inside a slide."
812
+ },
813
+ {
814
+ "kind": "method",
815
+ "name": "_paginationButtons",
816
+ "privacy": "private",
817
+ "return": {
818
+ "type": {
819
+ "text": "HTMLButtonElement[]"
820
+ }
821
+ }
822
+ },
823
+ {
824
+ "kind": "field",
825
+ "name": "_onPaginationFocus",
826
+ "privacy": "private",
827
+ "description": "Hand-rolled roving tabindex for the pagination row, not\n`RovingTabIndexMixin`: that mixin collects items from a real\n`slotchange`-firing `<slot>`, matching its intended use (consumer-\nauthored, slotted content, like `rc-toolbar`'s buttons) — these\nbuttons are shadow-DOM content this component renders itself, so\nthere's no slot to collect from. The pattern is otherwise the same\none the mixin itself implements: exactly one button is a tab stop,\narrow keys move focus among them (not activeIndex — matching\nrc-toolbar's own \"arrows move focus, Enter/Space activates\" model,\nnot a tablist's auto-activate-on-arrow), and focus keeps tabindex in\nsync wherever it lands (click, Tab, or a `.focus()` call below)."
828
+ },
829
+ {
830
+ "kind": "field",
831
+ "name": "_onPaginationNavigate",
832
+ "privacy": "private"
833
+ },
834
+ {
835
+ "kind": "method",
836
+ "name": "_initPaginationTabIndex",
837
+ "privacy": "private",
838
+ "return": {
839
+ "type": {
840
+ "text": "void"
841
+ }
842
+ },
843
+ "description": "One-time tabindex seed for pagination buttons that have never\nreceived focus yet (matching `activeIndex`, the sane default) —\n`_onPaginationFocus` takes over from there. Safe to call on every\nrender: a no-op once every button already has some tabindex value."
844
+ },
845
+ {
846
+ "kind": "field",
847
+ "name": "role",
848
+ "type": {
849
+ "text": "string"
850
+ },
851
+ "default": "'group'"
852
+ }
853
+ ],
854
+ "events": [
855
+ {
856
+ "name": "rc-carousel-change",
857
+ "type": {
858
+ "text": "CustomEvent"
859
+ },
860
+ "description": "Fires when the active slide changes, from a swipe settling, a keyboard action, or the imperative API. `detail: { index, trigger: 'swipe'|'button'|'keyboard'|'api' }`"
861
+ }
862
+ ],
863
+ "attributes": [
864
+ {
865
+ "description": "Controls the active slide. Host writes are silent.",
866
+ "name": "active-index",
867
+ "type": {
868
+ "text": "number"
869
+ },
870
+ "fieldName": "activeIndex"
871
+ },
872
+ {
873
+ "description": "Initial active slide for uncontrolled usage.",
874
+ "name": "default-active-index",
875
+ "type": {
876
+ "text": "number"
877
+ },
878
+ "fieldName": "defaultActiveIndex"
879
+ },
880
+ {
881
+ "description": "Wraps past the first/last slide back to the other end, seamlessly.",
882
+ "name": "loop",
883
+ "type": {
884
+ "text": "boolean"
885
+ },
886
+ "default": "false",
887
+ "fieldName": "loop"
888
+ },
889
+ {
890
+ "description": "Shows previous/next buttons.",
891
+ "name": "navigation",
892
+ "type": {
893
+ "text": "boolean"
894
+ },
895
+ "default": "false",
896
+ "fieldName": "navigation"
897
+ },
898
+ {
899
+ "description": "Shows a slide-picker button group.",
900
+ "name": "pagination",
901
+ "type": {
902
+ "text": "boolean"
903
+ },
904
+ "default": "false",
905
+ "fieldName": "pagination"
906
+ },
907
+ {
908
+ "description": "Enables click-and-drag scrolling with a mouse — native scroll-snap\ntouch physics already cover touch/pen, but a mouse has no built-in\nequivalent. Off by default.",
909
+ "name": "mouse-dragging",
910
+ "type": {
911
+ "text": "boolean"
912
+ },
913
+ "default": "false",
914
+ "fieldName": "mouseDragging"
915
+ }
916
+ ],
917
+ "superclass": {
918
+ "name": "LitElement",
919
+ "package": "lit"
920
+ },
921
+ "tagName": "rc-carousel",
922
+ "customElement": true
923
+ }
924
+ ],
925
+ "exports": [
926
+ {
927
+ "kind": "js",
928
+ "name": "RCCarousel",
929
+ "declaration": {
930
+ "name": "RCCarousel",
931
+ "module": "src/rc-carousel.ts"
932
+ }
933
+ }
934
+ ]
935
+ }
936
+ ]
937
+ }