@pindoba/core-carousel 0.0.0-alpha-20260617191010
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.
- package/LICENSE +12 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/src/connect-carousel-item.d.ts +7 -0
- package/dist/src/connect-carousel-item.d.ts.map +1 -0
- package/dist/src/connect-carousel-item.js +32 -0
- package/dist/src/connect-carousel-item.js.map +1 -0
- package/dist/src/connect-carousel.d.ts +17 -0
- package/dist/src/connect-carousel.d.ts.map +1 -0
- package/dist/src/connect-carousel.js +133 -0
- package/dist/src/connect-carousel.js.map +1 -0
- package/dist/src/create-carousel.d.ts +16 -0
- package/dist/src/create-carousel.d.ts.map +1 -0
- package/dist/src/create-carousel.js +479 -0
- package/dist/src/create-carousel.js.map +1 -0
- package/dist/src/snap-math.d.ts +64 -0
- package/dist/src/snap-math.d.ts.map +1 -0
- package/dist/src/snap-math.js +81 -0
- package/dist/src/snap-math.js.map +1 -0
- package/dist/src/types.d.ts +313 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/snap-math.ts
|
|
2
|
+
/**
|
|
3
|
+
* The anchor point of an extent for a given snap alignment:
|
|
4
|
+
* - `start` → the leading edge,
|
|
5
|
+
* - `center` → the midpoint,
|
|
6
|
+
* - `end` → the trailing edge.
|
|
7
|
+
*
|
|
8
|
+
* For RTL horizontal carousels the caller passes an `effectiveAlign` with
|
|
9
|
+
* `start`/`end` swapped, so this stays direction-agnostic.
|
|
10
|
+
*/
|
|
11
|
+
function anchorFor(start, end, align) {
|
|
12
|
+
if (align === "center") return (start + end) / 2;
|
|
13
|
+
if (align === "end") return end;
|
|
14
|
+
return start;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Index of the item whose anchor is closest to the viewport's anchor, optionally
|
|
18
|
+
* biased by `bias` px in the drag direction. The bias is what lets a drag-release
|
|
19
|
+
* commit to the next slide at ~30% drag instead of the 50% a strict nearest-snap
|
|
20
|
+
* would impose. Ties resolve to the lower index (first wins). Returns 0 for an
|
|
21
|
+
* empty list.
|
|
22
|
+
*/
|
|
23
|
+
function nearestIndex(items, vp, align, bias = 0) {
|
|
24
|
+
const anchor = anchorFor(vp.start, vp.end, align) + bias;
|
|
25
|
+
let bestIdx = 0;
|
|
26
|
+
let bestDist = Infinity;
|
|
27
|
+
for (let i = 0; i < items.length; i++) {
|
|
28
|
+
const iAnchor = anchorFor(items[i].start, items[i].end, align);
|
|
29
|
+
const d = Math.abs(iAnchor - anchor);
|
|
30
|
+
if (d < bestDist) {
|
|
31
|
+
bestDist = d;
|
|
32
|
+
bestIdx = i;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return bestIdx;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Clamp / wrap an index into `[0, count)`. Non-loop clamps to the ends; loop
|
|
39
|
+
* wraps (handling negatives via `((i % count) + count) % count`). Returns 0 when
|
|
40
|
+
* `count <= 0`. This unifies the two near-identical clamp formulas that
|
|
41
|
+
* `create-carousel` previously kept in `clamp()` and `scrollToIndex()`.
|
|
42
|
+
*/
|
|
43
|
+
function clampIndex(i, count, loop) {
|
|
44
|
+
if (count <= 0) return 0;
|
|
45
|
+
if (loop) return (i % count + count) % count;
|
|
46
|
+
if (i < 0) return 0;
|
|
47
|
+
if (i >= count) return count - 1;
|
|
48
|
+
return i;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Derive the at-start / at-end edge state from the current scroll offset and the
|
|
52
|
+
* maximum scrollable offset (both in px on the main axis; the caller passes
|
|
53
|
+
* `Math.abs(scrollLeft)` for RTL so this stays direction-agnostic). Tolerates
|
|
54
|
+
* ~1px slop. When there's no overflow (`max <= 0`) it reports at-start but NOT
|
|
55
|
+
* at-end, so a next button stays clickable while async layout settles — the
|
|
56
|
+
* first real scroll event corrects it.
|
|
57
|
+
*/
|
|
58
|
+
function edgeState(current, max) {
|
|
59
|
+
const hasOverflow = max > 0;
|
|
60
|
+
return {
|
|
61
|
+
atStart: !hasOverflow || current <= 1,
|
|
62
|
+
atEnd: hasOverflow && current >= max - 1
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Swap `start` ↔ `end` alignment for RTL horizontal carousels. In RTL the visual
|
|
67
|
+
* "start" of the track is the viewport's right edge, so an item aligned to
|
|
68
|
+
* `start` should anchor on its right edge — achieved by feeding `anchorFor` the
|
|
69
|
+
* swapped value. `center` is unaffected; vertical/LTR callers pass `rtl=false`
|
|
70
|
+
* and get the alignment back unchanged (zero behavior change).
|
|
71
|
+
*/
|
|
72
|
+
function effectiveAlign(align, rtl) {
|
|
73
|
+
if (!rtl) return align;
|
|
74
|
+
if (align === "start") return "end";
|
|
75
|
+
if (align === "end") return "start";
|
|
76
|
+
return align;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { anchorFor, clampIndex, edgeState, effectiveAlign, nearestIndex };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=snap-math.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snap-math.js","names":[],"sources":["../../src/snap-math.ts"],"sourcesContent":["import type { CarouselAlign } from \"./types.js\";\n\n/**\n * Pure, DOM-free geometry helpers for the carousel engine. Extracted from\n * `create-carousel` so the alignment / wrap / edge math is unit-testable without a\n * layout engine — happy-dom (and any non-browser test env) reports `0` for every\n * `getBoundingClientRect` / `scrollWidth`, which would otherwise strand all of\n * this logic in e2e-only territory. The DOM functions in `create-carousel` read\n * rects, then delegate the actual math here.\n */\n\n/** A 1-D extent on the main scroll axis (left/right or top/bottom, in px). */\nexport interface Extent {\n start: number;\n end: number;\n}\n\n/**\n * The anchor point of an extent for a given snap alignment:\n * - `start` → the leading edge,\n * - `center` → the midpoint,\n * - `end` → the trailing edge.\n *\n * For RTL horizontal carousels the caller passes an `effectiveAlign` with\n * `start`/`end` swapped, so this stays direction-agnostic.\n */\nexport function anchorFor(\n start: number,\n end: number,\n align: CarouselAlign,\n): number {\n if (align === \"center\") return (start + end) / 2;\n if (align === \"end\") return end;\n return start;\n}\n\n/**\n * Index of the item whose anchor is closest to the viewport's anchor, optionally\n * biased by `bias` px in the drag direction. The bias is what lets a drag-release\n * commit to the next slide at ~30% drag instead of the 50% a strict nearest-snap\n * would impose. Ties resolve to the lower index (first wins). Returns 0 for an\n * empty list.\n */\nexport function nearestIndex(\n items: ReadonlyArray<Extent>,\n vp: Extent,\n align: CarouselAlign,\n bias = 0,\n): number {\n const anchor = anchorFor(vp.start, vp.end, align) + bias;\n let bestIdx = 0;\n let bestDist = Infinity;\n for (let i = 0; i < items.length; i++) {\n const iAnchor = anchorFor(items[i].start, items[i].end, align);\n const d = Math.abs(iAnchor - anchor);\n if (d < bestDist) {\n bestDist = d;\n bestIdx = i;\n }\n }\n return bestIdx;\n}\n\n/**\n * Clamp / wrap an index into `[0, count)`. Non-loop clamps to the ends; loop\n * wraps (handling negatives via `((i % count) + count) % count`). Returns 0 when\n * `count <= 0`. This unifies the two near-identical clamp formulas that\n * `create-carousel` previously kept in `clamp()` and `scrollToIndex()`.\n */\nexport function clampIndex(i: number, count: number, loop: boolean): number {\n if (count <= 0) return 0;\n if (loop) return ((i % count) + count) % count;\n if (i < 0) return 0;\n if (i >= count) return count - 1;\n return i;\n}\n\n/**\n * Derive the at-start / at-end edge state from the current scroll offset and the\n * maximum scrollable offset (both in px on the main axis; the caller passes\n * `Math.abs(scrollLeft)` for RTL so this stays direction-agnostic). Tolerates\n * ~1px slop. When there's no overflow (`max <= 0`) it reports at-start but NOT\n * at-end, so a next button stays clickable while async layout settles — the\n * first real scroll event corrects it.\n */\nexport function edgeState(\n current: number,\n max: number,\n): { atStart: boolean; atEnd: boolean } {\n const hasOverflow = max > 0;\n const atStart = !hasOverflow || current <= 1;\n const atEnd = hasOverflow && current >= max - 1;\n return { atStart, atEnd };\n}\n\n/**\n * Swap `start` ↔ `end` alignment for RTL horizontal carousels. In RTL the visual\n * \"start\" of the track is the viewport's right edge, so an item aligned to\n * `start` should anchor on its right edge — achieved by feeding `anchorFor` the\n * swapped value. `center` is unaffected; vertical/LTR callers pass `rtl=false`\n * and get the alignment back unchanged (zero behavior change).\n */\nexport function effectiveAlign(\n align: CarouselAlign,\n rtl: boolean,\n): CarouselAlign {\n if (!rtl) return align;\n if (align === \"start\") return \"end\";\n if (align === \"end\") return \"start\";\n return align;\n}\n"],"mappings":";;;;;;;;;;AA0BA,SAAgB,UACd,OACA,KACA,OACQ;CACR,IAAI,UAAU,UAAU,QAAQ,QAAQ,OAAO;CAC/C,IAAI,UAAU,OAAO,OAAO;CAC5B,OAAO;AACT;;;;;;;;AASA,SAAgB,aACd,OACA,IACA,OACA,OAAO,GACC;CACR,MAAM,SAAS,UAAU,GAAG,OAAO,GAAG,KAAK,KAAK,IAAI;CACpD,IAAI,UAAU;CACd,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,UAAU,UAAU,MAAM,EAAE,CAAC,OAAO,MAAM,EAAE,CAAC,KAAK,KAAK;EAC7D,MAAM,IAAI,KAAK,IAAI,UAAU,MAAM;EACnC,IAAI,IAAI,UAAU;GAChB,WAAW;GACX,UAAU;EACZ;CACF;CACA,OAAO;AACT;;;;;;;AAQA,SAAgB,WAAW,GAAW,OAAe,MAAuB;CAC1E,IAAI,SAAS,GAAG,OAAO;CACvB,IAAI,MAAM,QAAS,IAAI,QAAS,SAAS;CACzC,IAAI,IAAI,GAAG,OAAO;CAClB,IAAI,KAAK,OAAO,OAAO,QAAQ;CAC/B,OAAO;AACT;;;;;;;;;AAUA,SAAgB,UACd,SACA,KACsC;CACtC,MAAM,cAAc,MAAM;CAG1B,OAAO;EAAE,SAFO,CAAC,eAAe,WAAW;EAEzB,OADJ,eAAe,WAAW,MAAM;CACtB;AAC1B;;;;;;;;AASA,SAAgB,eACd,OACA,KACe;CACf,IAAI,CAAC,KAAK,OAAO;CACjB,IAAI,UAAU,SAAS,OAAO;CAC9B,IAAI,UAAU,OAAO,OAAO;CAC5B,OAAO;AACT"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { WritableAtom } from "nanostores";
|
|
2
|
+
import { CarouselSlots, CarouselStyleProps } from "@pindoba/styles-carousel";
|
|
3
|
+
import { SystemStyleObject } from "@pindoba/styled-system/types";
|
|
4
|
+
import { ElementAttributes, ElementAttributes as ElementAttributes$1, PanelFeedback, PanelFeedback as PanelFeedback$1, PanelRadius, PanelRadius as PanelRadius$1 } from "@pindoba/core-panel";
|
|
5
|
+
|
|
6
|
+
//#region src/types.d.ts
|
|
7
|
+
type CarouselOrientation = NonNullable<CarouselStyleProps["orientation"]>;
|
|
8
|
+
type CarouselSize = NonNullable<CarouselStyleProps["size"]>;
|
|
9
|
+
type CarouselSlidesPerView = NonNullable<CarouselStyleProps["slidesPerView"]>;
|
|
10
|
+
type CarouselAlign = NonNullable<CarouselStyleProps["align"]>;
|
|
11
|
+
type CarouselItemValue = string;
|
|
12
|
+
/**
|
|
13
|
+
* Metadata for an item rendered via the `items` prop on `<Carousel>`. Body
|
|
14
|
+
* content is provided framework-idiomatically by the consumer — named slots
|
|
15
|
+
* in Astro (`<Fragment slot="<value>">`) or named snippets in Svelte
|
|
16
|
+
* (`{#snippet <value>()}...{/snippet}`).
|
|
17
|
+
*/
|
|
18
|
+
interface CarouselItemData {
|
|
19
|
+
value: CarouselItemValue;
|
|
20
|
+
/** Optional label for accessibility and dot indicators (e.g. "Slide 1"). */
|
|
21
|
+
label?: string;
|
|
22
|
+
/** Per-item snap alignment override. */
|
|
23
|
+
align?: CarouselAlign;
|
|
24
|
+
}
|
|
25
|
+
interface CarouselSlotPassThrough<T = ElementAttributes$1> {
|
|
26
|
+
style?: SystemStyleObject;
|
|
27
|
+
props?: T;
|
|
28
|
+
}
|
|
29
|
+
interface CarouselPassThrough<RootEl = ElementAttributes$1, ViewportEl = ElementAttributes$1, TrackEl = ElementAttributes$1, ItemEl = ElementAttributes$1, ControlsEl = ElementAttributes$1, PrevButtonEl = ElementAttributes$1, NextButtonEl = ElementAttributes$1, IndicatorsEl = ElementAttributes$1, IndicatorEl = ElementAttributes$1> {
|
|
30
|
+
root?: CarouselSlotPassThrough<RootEl>;
|
|
31
|
+
viewport?: CarouselSlotPassThrough<ViewportEl>;
|
|
32
|
+
track?: CarouselSlotPassThrough<TrackEl>;
|
|
33
|
+
item?: CarouselSlotPassThrough<ItemEl>;
|
|
34
|
+
controls?: CarouselSlotPassThrough<ControlsEl>;
|
|
35
|
+
prevButton?: CarouselSlotPassThrough<PrevButtonEl>;
|
|
36
|
+
nextButton?: CarouselSlotPassThrough<NextButtonEl>;
|
|
37
|
+
indicators?: CarouselSlotPassThrough<IndicatorsEl>;
|
|
38
|
+
indicator?: CarouselSlotPassThrough<IndicatorEl>;
|
|
39
|
+
/** Visually-hidden ARIA live region announcing the active slide. */
|
|
40
|
+
liveRegion?: CarouselSlotPassThrough;
|
|
41
|
+
}
|
|
42
|
+
interface CarouselBaseProps<RootEl = ElementAttributes$1, ViewportEl = ElementAttributes$1, TrackEl = ElementAttributes$1, ItemEl = ElementAttributes$1, ControlsEl = ElementAttributes$1, PrevButtonEl = ElementAttributes$1, NextButtonEl = ElementAttributes$1, IndicatorsEl = ElementAttributes$1, IndicatorEl = ElementAttributes$1> {
|
|
43
|
+
/**
|
|
44
|
+
* Axis of scrolling. Horizontal flips the scroll-snap axis to x; vertical
|
|
45
|
+
* flips it to y and bounds the viewport height.
|
|
46
|
+
* @default "horizontal"
|
|
47
|
+
* @group Layout
|
|
48
|
+
*/
|
|
49
|
+
orientation?: CarouselOrientation;
|
|
50
|
+
/**
|
|
51
|
+
* Scale for the gap between slides and the size of indicator dots. Cascades
|
|
52
|
+
* to items via CSS custom properties.
|
|
53
|
+
* @default "md"
|
|
54
|
+
* @group Appearance
|
|
55
|
+
*/
|
|
56
|
+
size?: CarouselSize;
|
|
57
|
+
/**
|
|
58
|
+
* Number of slides visible in the viewport. `"auto"` lets each slide size
|
|
59
|
+
* itself.
|
|
60
|
+
* @default 1
|
|
61
|
+
* @group Layout
|
|
62
|
+
*/
|
|
63
|
+
slidesPerView?: CarouselSlidesPerView;
|
|
64
|
+
/**
|
|
65
|
+
* Scroll-snap alignment applied to each slide.
|
|
66
|
+
* @default "start"
|
|
67
|
+
* @group Layout
|
|
68
|
+
*/
|
|
69
|
+
align?: CarouselAlign;
|
|
70
|
+
/**
|
|
71
|
+
* Semantic feedback color forwarded via colorPalette. Controls indicator
|
|
72
|
+
* color and accent surfaces.
|
|
73
|
+
* @group Appearance
|
|
74
|
+
*/
|
|
75
|
+
feedback?: PanelFeedback$1;
|
|
76
|
+
/**
|
|
77
|
+
* Border radius applied via connectPanel on the root.
|
|
78
|
+
* @group Appearance
|
|
79
|
+
*/
|
|
80
|
+
radius?: PanelRadius$1;
|
|
81
|
+
/**
|
|
82
|
+
* Render circular Prev/Next buttons over the viewport.
|
|
83
|
+
* @default false
|
|
84
|
+
* @group Behavior
|
|
85
|
+
*/
|
|
86
|
+
controls?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Render a tablist of dots that reflect the active slide and jump to a slide
|
|
89
|
+
* when clicked.
|
|
90
|
+
* @default false
|
|
91
|
+
* @group Behavior
|
|
92
|
+
*/
|
|
93
|
+
indicators?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* When true, next/prev wrap past the ends. Controls the button-disabled
|
|
96
|
+
* state and autoplay wrap behavior.
|
|
97
|
+
* @default false
|
|
98
|
+
* @group Behavior
|
|
99
|
+
*/
|
|
100
|
+
loop?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* When true, slides scrolled off-screen are marked `aria-hidden` + `inert`
|
|
103
|
+
* so assistive tech and the tab order skip them (APG carousel pattern).
|
|
104
|
+
* Off by default because `inert` changes focus reachability.
|
|
105
|
+
* @default false
|
|
106
|
+
* @group Accessibility
|
|
107
|
+
*/
|
|
108
|
+
inertOffscreenSlides?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Auto-advance interval in milliseconds. `false`/`0` disables autoplay.
|
|
111
|
+
* Pauses on hover, focus-within, tab-hidden, and prefers-reduced-motion:
|
|
112
|
+
* reduce.
|
|
113
|
+
* @default false
|
|
114
|
+
* @group Behavior
|
|
115
|
+
*/
|
|
116
|
+
autoplay?: number | false;
|
|
117
|
+
/**
|
|
118
|
+
* Accessible label for the carousel region. Forwarded to `aria-label` on the
|
|
119
|
+
* viewport, and used to announce the active slide via a polite live region.
|
|
120
|
+
* @group Accessibility
|
|
121
|
+
*/
|
|
122
|
+
label?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Data-driven array of slides. Each item needs a unique `value`; optional
|
|
125
|
+
* `label` and `align` override the root defaults per item. Body content is
|
|
126
|
+
* provided via named slots (Astro) or named snippets (Svelte) keyed by
|
|
127
|
+
* `value`. Mutually exclusive with slot composition.
|
|
128
|
+
* @group Behavior
|
|
129
|
+
*/
|
|
130
|
+
items?: CarouselItemData[];
|
|
131
|
+
/**
|
|
132
|
+
* Per-slot style and HTML-attribute override bag for the carousel's slots.
|
|
133
|
+
* @group Advanced
|
|
134
|
+
*/
|
|
135
|
+
passThrough?: CarouselPassThrough<RootEl, ViewportEl, TrackEl, ItemEl, ControlsEl, PrevButtonEl, NextButtonEl, IndicatorsEl, IndicatorEl>;
|
|
136
|
+
}
|
|
137
|
+
interface CarouselItemBaseProps<ItemEl = ElementAttributes$1> {
|
|
138
|
+
/**
|
|
139
|
+
* Unique identifier for the slide, used to key named slots/snippets and to
|
|
140
|
+
* track the active slide.
|
|
141
|
+
* @group Behavior
|
|
142
|
+
*/
|
|
143
|
+
value?: CarouselItemValue;
|
|
144
|
+
/**
|
|
145
|
+
* Optional label for accessibility and dot indicators (e.g. "Slide 1").
|
|
146
|
+
* @group Accessibility
|
|
147
|
+
*/
|
|
148
|
+
label?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Per-item snap alignment override for this slide.
|
|
151
|
+
* @group Layout
|
|
152
|
+
*/
|
|
153
|
+
align?: CarouselAlign;
|
|
154
|
+
/**
|
|
155
|
+
* Per-slot style and HTML-attribute override bag for the item slot.
|
|
156
|
+
* @group Advanced
|
|
157
|
+
*/
|
|
158
|
+
passThrough?: {
|
|
159
|
+
item?: CarouselSlotPassThrough<ItemEl>;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
interface ConnectCarouselOptions extends Partial<CarouselBaseProps<object, object, object, object, object, object, object, object, object>> {
|
|
163
|
+
class?: unknown;
|
|
164
|
+
/**
|
|
165
|
+
* Active slide index. Drives the indicators' `aria-current` / `data-active`
|
|
166
|
+
* mirrors. Frameworks pass their reactive index in.
|
|
167
|
+
* @default 0
|
|
168
|
+
*/
|
|
169
|
+
currentIndex?: number;
|
|
170
|
+
/**
|
|
171
|
+
* Whether the viewport is scrolled to the very start. Drives the prev
|
|
172
|
+
* button's `disabled` state (prev is disabled when at start and not looping).
|
|
173
|
+
* @default false
|
|
174
|
+
*/
|
|
175
|
+
atScrollStart?: boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Whether the viewport is scrolled to the very end. Drives the next button's
|
|
178
|
+
* `disabled` state (next is disabled when at end and not looping).
|
|
179
|
+
* @default false
|
|
180
|
+
*/
|
|
181
|
+
atScrollEnd?: boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Number of slides — used to compute the number of indicator dots. Falls back
|
|
184
|
+
* to `items.length` when omitted.
|
|
185
|
+
*/
|
|
186
|
+
itemCount?: number;
|
|
187
|
+
}
|
|
188
|
+
interface CarouselRootProps {
|
|
189
|
+
class: string;
|
|
190
|
+
"data-component": "carousel";
|
|
191
|
+
"data-orientation": CarouselOrientation;
|
|
192
|
+
[key: string]: unknown;
|
|
193
|
+
}
|
|
194
|
+
interface CarouselSlotProps {
|
|
195
|
+
class: string;
|
|
196
|
+
[key: string]: unknown;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* `<Button>` bag for the prev/next controls. Carries the composed class plus
|
|
200
|
+
* the literal `<Button>` variant props and reactive `disabled` state. Templates
|
|
201
|
+
* spread it directly onto `<Button {...api.prevButtonProps}>`.
|
|
202
|
+
*/
|
|
203
|
+
interface CarouselControlButtonProps {
|
|
204
|
+
class: string;
|
|
205
|
+
emphasis: "secondary";
|
|
206
|
+
shape: "circle";
|
|
207
|
+
size: "sm";
|
|
208
|
+
type: "button";
|
|
209
|
+
"aria-label": string;
|
|
210
|
+
disabled: boolean;
|
|
211
|
+
[key: string]: unknown;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* `<button>` bag for a single indicator dot. Carries the composed class, static
|
|
215
|
+
* markers, and reactive active-state mirrors keyed off `currentIndex`.
|
|
216
|
+
*/
|
|
217
|
+
interface CarouselIndicatorProps {
|
|
218
|
+
class: string;
|
|
219
|
+
type: "button";
|
|
220
|
+
role: "tab";
|
|
221
|
+
"aria-label": string;
|
|
222
|
+
"aria-current": "true" | "false";
|
|
223
|
+
"data-active": "true" | "false";
|
|
224
|
+
"data-carousel-indicator": "";
|
|
225
|
+
"data-index": string;
|
|
226
|
+
[key: string]: unknown;
|
|
227
|
+
}
|
|
228
|
+
/** One indicator entry in the `items` array — id + its pre-computed bag. */
|
|
229
|
+
interface CarouselIndicatorItem {
|
|
230
|
+
id: string;
|
|
231
|
+
indicatorProps: CarouselIndicatorProps;
|
|
232
|
+
}
|
|
233
|
+
interface CarouselApi {
|
|
234
|
+
rootProps: CarouselRootProps;
|
|
235
|
+
viewportWrapperProps: CarouselSlotProps;
|
|
236
|
+
viewportProps: CarouselSlotProps;
|
|
237
|
+
trackProps: CarouselSlotProps;
|
|
238
|
+
controlsProps: CarouselSlotProps;
|
|
239
|
+
prevButtonProps: CarouselControlButtonProps;
|
|
240
|
+
nextButtonProps: CarouselControlButtonProps;
|
|
241
|
+
indicatorsProps: CarouselSlotProps;
|
|
242
|
+
/** One bag per indicator dot, indexed by id. Empty when no item count. */
|
|
243
|
+
items: CarouselIndicatorItem[];
|
|
244
|
+
liveRegionProps: CarouselSlotProps;
|
|
245
|
+
element: "div";
|
|
246
|
+
}
|
|
247
|
+
interface ConnectCarouselItemOptions extends Partial<CarouselItemBaseProps<object>> {
|
|
248
|
+
/** Size inherited from root via CSS vars if omitted. */
|
|
249
|
+
size?: CarouselSize;
|
|
250
|
+
slidesPerView?: CarouselSlidesPerView;
|
|
251
|
+
orientation?: CarouselOrientation;
|
|
252
|
+
class?: unknown;
|
|
253
|
+
}
|
|
254
|
+
interface CarouselItemRootProps {
|
|
255
|
+
class: string;
|
|
256
|
+
"data-component": "carousel-item";
|
|
257
|
+
"data-orientation": CarouselOrientation;
|
|
258
|
+
[key: string]: unknown;
|
|
259
|
+
}
|
|
260
|
+
interface CarouselItemApi {
|
|
261
|
+
itemProps: CarouselItemRootProps;
|
|
262
|
+
element: "div";
|
|
263
|
+
}
|
|
264
|
+
interface CarouselConfig {
|
|
265
|
+
orientation?: CarouselOrientation;
|
|
266
|
+
align?: CarouselAlign;
|
|
267
|
+
loop?: boolean;
|
|
268
|
+
/** Auto-advance interval in ms. `false` / `0` disables. */
|
|
269
|
+
autoplay?: number | false;
|
|
270
|
+
/** Mark off-screen slides `aria-hidden` + `inert` (opt-in). */
|
|
271
|
+
inertOffscreenSlides?: boolean;
|
|
272
|
+
slideCount?: number;
|
|
273
|
+
initialIndex?: number;
|
|
274
|
+
onActiveIndexChange?: (index: number) => void;
|
|
275
|
+
}
|
|
276
|
+
interface ScrollToIndexOptions {
|
|
277
|
+
behavior?: ScrollBehavior;
|
|
278
|
+
}
|
|
279
|
+
interface HeadlessCarousel {
|
|
280
|
+
$activeIndex: WritableAtom<number>;
|
|
281
|
+
$slideCount: WritableAtom<number>;
|
|
282
|
+
/** Reactive config — frameworks push prop changes via the `set*` methods. */
|
|
283
|
+
$orientation: WritableAtom<CarouselOrientation>;
|
|
284
|
+
$align: WritableAtom<CarouselAlign>;
|
|
285
|
+
$loop: WritableAtom<boolean>;
|
|
286
|
+
$autoplayMs: WritableAtom<number>;
|
|
287
|
+
/** Scroll boundaries — derived from the viewport's scroll position. */
|
|
288
|
+
$atScrollStart: WritableAtom<boolean>;
|
|
289
|
+
$atScrollEnd: WritableAtom<boolean>;
|
|
290
|
+
setActiveIndex: (index: number) => void;
|
|
291
|
+
setSlideCount: (count: number) => void;
|
|
292
|
+
setOrientation: (orientation: CarouselOrientation) => void;
|
|
293
|
+
setAlign: (align: CarouselAlign) => void;
|
|
294
|
+
setLoop: (loop: boolean) => void;
|
|
295
|
+
setAutoplay: (autoplay: number | false) => void;
|
|
296
|
+
next: () => void;
|
|
297
|
+
prev: () => void;
|
|
298
|
+
/**
|
|
299
|
+
* Wires the viewport's `scroll` and `keydown` listeners, autoplay, and
|
|
300
|
+
* keeps the `[data-carousel-prev]` / `[data-carousel-next]` buttons inside
|
|
301
|
+
* `root` in sync with the actual scroll boundaries. Returns a cleanup
|
|
302
|
+
* function. Calling `registerViewport` again unwires the previous one.
|
|
303
|
+
*/
|
|
304
|
+
registerViewport: (viewport: HTMLElement, root: HTMLElement) => () => void;
|
|
305
|
+
/** Smoothly scroll the viewport so `index` is aligned per `$align`. */
|
|
306
|
+
scrollToIndex: (index: number, options?: ScrollToIndexOptions) => void;
|
|
307
|
+
/** Like `scrollToIndex` but also resets the autoplay timer. */
|
|
308
|
+
userGoTo: (index: number) => void;
|
|
309
|
+
destroy: () => void;
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
export { CarouselAlign, CarouselApi, CarouselBaseProps, CarouselConfig, CarouselControlButtonProps, CarouselIndicatorItem, CarouselIndicatorProps, CarouselItemApi, CarouselItemBaseProps, CarouselItemData, CarouselItemRootProps, CarouselItemValue, CarouselOrientation, CarouselPassThrough, CarouselRootProps, CarouselSize, CarouselSlidesPerView, CarouselSlotPassThrough, CarouselSlotProps, type CarouselSlots, ConnectCarouselItemOptions, ConnectCarouselOptions, type ElementAttributes, HeadlessCarousel, type PanelFeedback, type PanelRadius, ScrollToIndexOptions };
|
|
313
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/types.ts"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pindoba/core-carousel",
|
|
3
|
+
"version": "0.0.0-alpha-20260617191010",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./*": {
|
|
15
|
+
"types": "./dist/src/*.d.ts",
|
|
16
|
+
"import": "./dist/src/*.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"nanostores": "^1.3.0",
|
|
24
|
+
"@pindoba/styles-carousel": "0.0.0-alpha-20260617191010",
|
|
25
|
+
"@pindoba/styled-system": "0.0.0-alpha-20260617191010",
|
|
26
|
+
"@pindoba/core-panel": "0.0.0-alpha-20260617191010",
|
|
27
|
+
"@pindoba/styles-panel": "0.0.0-alpha-20260617191010"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsdown": "^0.22.2",
|
|
31
|
+
"typescript": "^6.0.3"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsdown",
|
|
35
|
+
"dev": "tsdown --watch",
|
|
36
|
+
"clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo"
|
|
37
|
+
}
|
|
38
|
+
}
|