@semcore/carousel 3.17.1-prerelease.1 → 3.18.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.
package/src/Carousel.jsx DELETED
@@ -1,458 +0,0 @@
1
- import React from 'react';
2
- import createComponent, { Component, sstyled, Root } from '@semcore/core';
3
-
4
- import { Box } from '@semcore/flex-box';
5
- import ChevronRight from '@semcore/icon/ChevronRight/l';
6
- import ChevronLeft from '@semcore/icon/ChevronLeft/l';
7
- import uniqueIDEnhancement from '@semcore/utils/lib/uniqueID';
8
- import i18nEnhance from '@semcore/utils/lib/enhances/i18nEnhance';
9
- import { localizedMessages } from './translations/__intergalactic-dynamic-locales';
10
-
11
- import style from './style/carousel.shadow.css';
12
-
13
- const position = {
14
- getItemMin: function (items) {
15
- let indexItem = 0;
16
- items.forEach(function (item, index) {
17
- if (item.position < items[indexItem].position) {
18
- indexItem = index;
19
- }
20
- });
21
- return indexItem;
22
- },
23
- getItemMax: function (items) {
24
- let indexItem = 0;
25
- items.forEach(function (item, index) {
26
- if (item.position > items[indexItem].position) {
27
- indexItem = index;
28
- }
29
- });
30
- return indexItem;
31
- },
32
- getMin: function (items) {
33
- return items[position.getItemMin(items)].position;
34
- },
35
- getMax: function (items) {
36
- return items[position.getItemMax(items)].position;
37
- },
38
- };
39
-
40
- const MAP_TRANSFORM = {
41
- ArrowLeft: 'left',
42
- ArrowRight: 'right',
43
- };
44
-
45
- class CarouselRoot extends Component {
46
- static displayName = 'Carousel';
47
- static defaultProps = {
48
- defaultIndex: 0,
49
- duration: 350,
50
- step: 100,
51
- bounded: false,
52
- i18n: localizedMessages,
53
- locale: 'en',
54
- };
55
-
56
- static style = style;
57
- static enhance = [uniqueIDEnhancement(), i18nEnhance(localizedMessages)];
58
-
59
- refContainer = React.createRef();
60
- transform = 0;
61
- positionLeftItem = 0;
62
- indexIndicator = 0;
63
-
64
- constructor(props) {
65
- super(props);
66
- this.isControlled = props.index !== undefined;
67
- this.state = {
68
- items: [],
69
- };
70
- }
71
-
72
- uncontrolledProps() {
73
- return {
74
- index: null,
75
- };
76
- }
77
-
78
- componentDidUpdate(prevProps) {
79
- const { index } = this.asProps;
80
- if (prevProps.index !== index && this.isControlled) {
81
- this.slideToValue(prevProps.index, index);
82
- }
83
- }
84
-
85
- handlerKeyDown = (e) => {
86
- switch (e.key) {
87
- case 'ArrowLeft':
88
- case 'ArrowRight': {
89
- e.preventDefault();
90
- const { activeItemIndex } = this.controlTransformItem(MAP_TRANSFORM[e.key]);
91
- this.handlers.index(activeItemIndex);
92
- }
93
- }
94
- };
95
-
96
- toggleItem = (item, removeItem = false) => {
97
- const { index } = this.asProps;
98
- const { items } = this.state;
99
- if (removeItem) {
100
- this.updateItems(items.filter((element) => element.node !== item.node));
101
- } else {
102
- this.setState(
103
- (state) => {
104
- return {
105
- items: [...state.items, item].map((element, position) => ({
106
- ...element,
107
- position,
108
- transform: 0,
109
- })),
110
- };
111
- },
112
- () => {
113
- const { items } = this.state;
114
- if (items.length > index && index >= 0) {
115
- this.slideToValue(this.indexIndicator, index);
116
- }
117
- },
118
- );
119
- }
120
- };
121
-
122
- updateItems = (items) => {
123
- this.setState(() => ({ items }));
124
- };
125
-
126
- transformContainer = (transform) => {
127
- if (this.refContainer.current) {
128
- this.refContainer.current.style.transform = `translateX(${transform}%)`;
129
- }
130
- };
131
-
132
- getDirection = (currentIndex, nextIndex, bounded) => {
133
- if (bounded) {
134
- return currentIndex < nextIndex ? 'right' : 'left';
135
- }
136
- const { items } = this.state;
137
- const listIndex = items.map((_, ind) => ind);
138
- const tmpArr = [...listIndex];
139
- const minTmpArr = tmpArr[0];
140
- const maxTmpArr = tmpArr[tmpArr.length - 1];
141
-
142
- if (tmpArr.length === 2) {
143
- return currentIndex < nextIndex ? 'right' : 'left';
144
- }
145
- if (currentIndex === minTmpArr) {
146
- tmpArr.unshift(maxTmpArr);
147
- tmpArr.pop();
148
- }
149
- if (currentIndex === maxTmpArr) {
150
- tmpArr.shift();
151
- tmpArr.push(minTmpArr);
152
- }
153
-
154
- const tmpCurrentIndex = tmpArr.indexOf(currentIndex);
155
- const left = tmpArr.indexOf(nextIndex);
156
-
157
- return left - tmpCurrentIndex < 0 ? 'left' : 'right';
158
- };
159
-
160
- slideToValue = (currentIndex, nextIndexItem, bounded) => {
161
- if (currentIndex === nextIndexItem) return false;
162
- const direction = this.getDirection(
163
- currentIndex,
164
- nextIndexItem,
165
- bounded || this.asProps.bounded,
166
- );
167
- let i = currentIndex;
168
- while (nextIndexItem !== i) {
169
- const { activeItemIndex } = this.transformItem(direction);
170
- i = activeItemIndex;
171
- }
172
- };
173
-
174
- controlTransformItem = (direction) => {
175
- const { bounded, index } = this.asProps;
176
- const { items } = this.state;
177
- const maxIndexIndicator = items.length - 1;
178
-
179
- if (this.isControlled) {
180
- if (direction === 'right') {
181
- if (bounded && index === maxIndexIndicator) {
182
- return { activeItemIndex: maxIndexIndicator };
183
- }
184
- return { activeItemIndex: index === maxIndexIndicator ? 0 : index + 1 };
185
- }
186
- if (direction === 'left') {
187
- if (bounded && index === 0) {
188
- return { activeItemIndex: 0 };
189
- }
190
- return { activeItemIndex: index === 0 ? maxIndexIndicator : index - 1 };
191
- }
192
- }
193
- return this.transformItem(direction);
194
- };
195
-
196
- transformItem = (direction) => {
197
- const { bounded, step } = this.asProps;
198
- const { items } = this.state;
199
- const maxIndexIndicator = items.length - 1;
200
- let nextItemPosition = undefined;
201
-
202
- if (direction === 'right') {
203
- if (bounded && this.positionLeftItem === maxIndexIndicator) {
204
- return { activeItemIndex: maxIndexIndicator };
205
- }
206
- this.positionLeftItem += 1;
207
- const positionItemMax = position.getMax(items);
208
-
209
- if (this.positionLeftItem > positionItemMax) {
210
- nextItemPosition = position.getItemMin(items);
211
- items[nextItemPosition].position = positionItemMax + 1;
212
- items[nextItemPosition].transform += items.length * step;
213
- this.updateItems([...items]);
214
- }
215
-
216
- this.indexIndicator += 1;
217
- if (this.indexIndicator > maxIndexIndicator) {
218
- this.indexIndicator = 0;
219
- }
220
- this.transform -= step;
221
- }
222
- if (direction === 'left') {
223
- if (bounded && this.positionLeftItem === 0) {
224
- return { activeItemIndex: 0 };
225
- }
226
- this.positionLeftItem -= 1;
227
- const positionItemMin = position.getMin(items);
228
-
229
- if (this.positionLeftItem < positionItemMin) {
230
- nextItemPosition = position.getItemMax(items);
231
- items[nextItemPosition].position = positionItemMin - 1;
232
- items[nextItemPosition].transform -= items.length * step;
233
- this.updateItems([...items]);
234
- }
235
-
236
- this.indexIndicator -= 1;
237
- if (this.indexIndicator < 0) {
238
- this.indexIndicator = maxIndexIndicator;
239
- }
240
- this.transform += step;
241
- }
242
-
243
- const activeItemIndex = items.findIndex((item) => item.position === this.positionLeftItem);
244
- if (items[activeItemIndex]) {
245
- items[
246
- activeItemIndex
247
- ].node.style.transform = `translateX(${items[activeItemIndex].transform}%)`;
248
- }
249
- this.transformContainer(this.transform);
250
- return { activeItemIndex };
251
- };
252
-
253
- bindHandlerClick = (direction) => {
254
- return () => {
255
- const { activeItemIndex } = this.controlTransformItem(direction);
256
- this.handlers.index(activeItemIndex);
257
- };
258
- };
259
-
260
- bindHandlerClickIndicator = (value) => {
261
- return () => {
262
- !this.isControlled && this.slideToValue(this.indexIndicator, value, true);
263
- this.handlers.index(value);
264
- };
265
- };
266
-
267
- handlerTouchStart = (e) => {
268
- this._touchStartCoord = e.changedTouches[0].clientX;
269
- };
270
-
271
- handlerTouchEnd = (e) => {
272
- const touchEndCoord = e.changedTouches[0].clientX;
273
- const delta = touchEndCoord - this._touchStartCoord;
274
- if (delta > 50) {
275
- const { activeItemIndex } = this.controlTransformItem('left');
276
- this.handlers.index(activeItemIndex);
277
- } else if (delta < -50) {
278
- const { activeItemIndex } = this.controlTransformItem('right');
279
- this.handlers.index(activeItemIndex);
280
- }
281
- };
282
-
283
- getContainerProps() {
284
- const { duration } = this.asProps;
285
-
286
- return {
287
- ref: this.refContainer,
288
- duration,
289
- };
290
- }
291
-
292
- getItemProps(_, index) {
293
- return {
294
- toggleItem: this.toggleItem,
295
- uid: this.asProps.uid,
296
- index,
297
- current: index === this.asProps.index,
298
- };
299
- }
300
-
301
- bindHandlerKeydownControl = (direction) => (e) => {
302
- const { key } = e;
303
- if (key === 'Enter') {
304
- e.preventDefault();
305
- this.bindHandlerClick(direction)();
306
- }
307
- };
308
-
309
- getPrevProps() {
310
- const { index, bounded, getI18nText } = this.asProps;
311
- const { items } = this.state;
312
- let disabled = false;
313
- if (items.length && bounded) {
314
- disabled = index === 0;
315
- }
316
- return {
317
- onClick: this.bindHandlerClick('left'),
318
- onKeyDown: this.bindHandlerKeydownControl('left'),
319
- disabled,
320
- label: getI18nText('prev'),
321
- };
322
- }
323
-
324
- getNextProps() {
325
- const { index, bounded, getI18nText } = this.asProps;
326
- const { items } = this.state;
327
- let disabled = false;
328
- if (items.length && bounded) {
329
- disabled = index === items.length - 1;
330
- }
331
- return {
332
- onClick: this.bindHandlerClick('right'),
333
- onKeyDown: this.bindHandlerKeydownControl('right'),
334
- disabled,
335
- label: getI18nText('next'),
336
- };
337
- }
338
-
339
- getIndicatorsProps() {
340
- const { items } = this.state;
341
- const { index } = this.asProps;
342
-
343
- return {
344
- items: items.map((item, key) => ({
345
- active: key === index,
346
- onClick: this.bindHandlerClickIndicator(key),
347
- key,
348
- })),
349
- };
350
- }
351
-
352
- render() {
353
- const SCarousel = Root;
354
- const { styles, Children } = this.asProps;
355
-
356
- return sstyled(styles)(
357
- <SCarousel
358
- render={Box}
359
- role='group'
360
- onKeyDown={this.handlerKeyDown}
361
- tabIndex={0}
362
- onTouchStart={this.handlerTouchStart}
363
- onTouchEnd={this.handlerTouchEnd}
364
- >
365
- <Children />
366
- </SCarousel>,
367
- );
368
- }
369
- }
370
-
371
- const Container = (props) => {
372
- const SContainer = Root;
373
- const { styles, duration } = props;
374
-
375
- return sstyled(styles)(<SContainer render={Box} role='list' use:duration={`${duration}ms`} />);
376
- };
377
-
378
- const Item = (props) => {
379
- const { styles, toggleItem, index, uid, current } = props;
380
- const SItem = Root;
381
- const refItem = React.createRef();
382
- React.useEffect(() => {
383
- // add item
384
- toggleItem({ node: refItem.current });
385
- return () => {
386
- // remove item
387
- toggleItem({ node: refItem.current }, true);
388
- };
389
- }, []);
390
-
391
- return sstyled(styles)(
392
- <SItem
393
- render={Box}
394
- ref={refItem}
395
- role='listitem'
396
- id={`igc-${uid}-carousel-item-${index}`}
397
- aria-current={current}
398
- />,
399
- );
400
- };
401
-
402
- const Prev = (props) => {
403
- const { styles, children, Children, label, top = 0 } = props;
404
- const SPrev = Root;
405
- return sstyled(styles)(
406
- <SPrev render={Box} top={top}>
407
- {children ? <Children /> : <ChevronLeft interactive aria-label={label} />}
408
- </SPrev>,
409
- );
410
- };
411
-
412
- const Next = (props) => {
413
- const { styles, children, Children, label, top = 0 } = props;
414
- const SNext = Root;
415
- return sstyled(styles)(
416
- <SNext render={Box} top={top}>
417
- {children ? <Children /> : <ChevronRight interactive aria-label={label} />}
418
- </SNext>,
419
- );
420
- };
421
-
422
- const Indicators = ({ items, styles, Children }) => {
423
- const SIndicators = Root;
424
- if (Children.origin) {
425
- return sstyled(styles)(
426
- <SIndicators render={Box} aria-hidden='true'>
427
- <Children />
428
- </SIndicators>,
429
- );
430
- }
431
- return sstyled(styles)(
432
- <SIndicators render={Box} aria-hidden='true'>
433
- {items.map((item, index) => (
434
- <Carousel.Indicator key={index} {...item} />
435
- ))}
436
- </SIndicators>,
437
- );
438
- };
439
-
440
- const Indicator = ({ styles, Children }) => {
441
- const SIndicator = Root;
442
- return sstyled(styles)(
443
- <SIndicator render={Box}>
444
- <Children />
445
- </SIndicator>,
446
- );
447
- };
448
-
449
- const Carousel = createComponent(CarouselRoot, {
450
- Container,
451
- Indicators,
452
- Indicator,
453
- Item,
454
- Prev,
455
- Next,
456
- });
457
-
458
- export default Carousel;
package/src/index.d.ts DELETED
@@ -1,76 +0,0 @@
1
- import React from 'react';
2
- import { PropGetterFn, UnknownProperties, Intergalactic } from '@semcore/core';
3
- import { BoxProps } from '@semcore/flex-box';
4
-
5
- type ChildRenderFn<Props> = Props & {
6
- children?: ({
7
- items,
8
- }: {
9
- items: { active: boolean; onClick: () => void }[];
10
- }) => React.ReactElement | React.ReactElement[];
11
- };
12
-
13
- /** @deprecated */
14
- export interface ICarouselProps extends CarouselProps, UnknownProperties {}
15
- export type CarouselProps = BoxProps & {
16
- /** Index active item */
17
- index?: number;
18
- /**
19
- * Index of the active item selected by default
20
- * @default 0
21
- */
22
- defaultIndex?: number;
23
- /** Called when the selection is changed */
24
- onIndexChange?: (index: number) => void;
25
- /** Animation duration
26
- * @default 300 */
27
- duration?: number;
28
- /** Disables infinite items change in the carousel
29
- * @default false */
30
- bounded?: boolean;
31
- /** @ignore */
32
- step?: number;
33
- locale?: string;
34
- };
35
-
36
- /** @deprecated */
37
- export interface ICarouselContext extends CarouselContext, UnknownProperties {}
38
- export type CarouselContext = {
39
- getContainerProps: PropGetterFn;
40
- getItemProps: PropGetterFn;
41
- getPrevProps: PropGetterFn;
42
- getNextProps: PropGetterFn;
43
- getIndicatorsProps: PropGetterFn;
44
- };
45
-
46
- /** @deprecated */
47
- export interface ICarouselState extends CarouselState, UnknownProperties {}
48
- export type CarouselState = {
49
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
50
- items: { transform: number; position: number; node: HTMLDivElement }[];
51
- };
52
-
53
- declare const Carousel: Intergalactic.Component<
54
- 'div',
55
- CarouselProps,
56
- CarouselContext & CarouselState
57
- > & {
58
- Container: Intergalactic.Component<'div', BoxProps>;
59
- Indicators: Intergalactic.Component<'div', BoxProps, CarouselState>;
60
- Indicator: Intergalactic.Component<
61
- 'div',
62
- Omit<BoxProps, 'position'> & {
63
- active?: boolean;
64
- onClick?: () => void;
65
- transform?: number;
66
- position?: number;
67
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
68
- node?: HTMLDivElement;
69
- }
70
- >;
71
- Item: Intergalactic.Component<'div', BoxProps>;
72
- Prev: Intergalactic.Component<'div', BoxProps>;
73
- Next: Intergalactic.Component<'div', BoxProps>;
74
- };
75
-
76
- export default Carousel;
File without changes