lupine.components 1.1.56 → 1.1.58
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/package.json +1 -1
- package/src/component-pool/range/range.tsx +36 -13
- package/src/components/action-sheet-color.tsx +3 -1
- package/src/components/mobile-components/mobile-top-sys-icon.tsx +8 -3
- package/src/components/notice-message.tsx +3 -0
- package/src/components/slide-tab-component.tsx +158 -79
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { bindGlobalStyle, getGlobalStylesId, CssProps, RefProps } from 'lupine.w
|
|
|
3
3
|
export type RangeHookProps = {
|
|
4
4
|
setValue: (val: number | [number, number]) => void;
|
|
5
5
|
getValue: () => number | [number, number];
|
|
6
|
+
setDisabled?: (disabled: boolean) => void;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export type RangeProps = {
|
|
@@ -24,6 +25,7 @@ export type RangeProps = {
|
|
|
24
25
|
trackColor?: string;
|
|
25
26
|
fillColor?: string;
|
|
26
27
|
showButtons?: boolean;
|
|
28
|
+
thumbSize?: number | string;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
// 1. Define Static CSS completely decoupled from Reactivity (isVertical)
|
|
@@ -63,11 +65,11 @@ const rangeCss: CssProps = {
|
|
|
63
65
|
},
|
|
64
66
|
'&.horizontal .&-wrapper': {
|
|
65
67
|
width: '100%',
|
|
66
|
-
height: '20px',
|
|
68
|
+
height: 'var(--range-thumb-size, 20px)',
|
|
67
69
|
flex: 1,
|
|
68
70
|
},
|
|
69
71
|
'&.vertical .&-wrapper': {
|
|
70
|
-
width: '20px',
|
|
72
|
+
width: 'var(--range-thumb-size, 20px)',
|
|
71
73
|
height: '100%',
|
|
72
74
|
flex: 1,
|
|
73
75
|
},
|
|
@@ -123,7 +125,7 @@ const rangeCss: CssProps = {
|
|
|
123
125
|
transform: 'none',
|
|
124
126
|
},
|
|
125
127
|
'&.vertical .&-input': {
|
|
126
|
-
height: '20px',
|
|
128
|
+
height: 'var(--range-thumb-size, 20px)',
|
|
127
129
|
top: '100%',
|
|
128
130
|
left: 0,
|
|
129
131
|
transformOrigin: '0 0',
|
|
@@ -134,8 +136,8 @@ const rangeCss: CssProps = {
|
|
|
134
136
|
appearance: 'none',
|
|
135
137
|
WebkitAppearance: 'none',
|
|
136
138
|
pointerEvents: 'auto',
|
|
137
|
-
width: '20px',
|
|
138
|
-
height: '20px',
|
|
139
|
+
width: 'var(--range-thumb-size, 20px)',
|
|
140
|
+
height: 'var(--range-thumb-size, 20px)',
|
|
139
141
|
backgroundColor: '#fff',
|
|
140
142
|
border: '2px solid var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
|
|
141
143
|
borderRadius: '50%',
|
|
@@ -151,8 +153,8 @@ const rangeCss: CssProps = {
|
|
|
151
153
|
},
|
|
152
154
|
'.&-input::-moz-range-thumb': {
|
|
153
155
|
pointerEvents: 'auto',
|
|
154
|
-
width: '20px',
|
|
155
|
-
height: '20px',
|
|
156
|
+
width: 'var(--range-thumb-size, 20px)',
|
|
157
|
+
height: 'var(--range-thumb-size, 20px)',
|
|
156
158
|
backgroundColor: '#fff',
|
|
157
159
|
border: '2px solid var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
|
|
158
160
|
borderRadius: '50%',
|
|
@@ -280,6 +282,9 @@ export const Range = (props: RangeProps) => {
|
|
|
280
282
|
const customStyle: any = { ...props.style };
|
|
281
283
|
if (props.trackColor) customStyle['--range-track-color'] = props.trackColor;
|
|
282
284
|
if (props.fillColor) customStyle['--range-fill-color'] = props.fillColor;
|
|
285
|
+
if (props.thumbSize) {
|
|
286
|
+
customStyle['--range-thumb-size'] = typeof props.thumbSize === 'number' ? `${props.thumbSize}px` : props.thumbSize;
|
|
287
|
+
}
|
|
283
288
|
|
|
284
289
|
// Evaluate the immutable hash exact ONCE for all range implementations.
|
|
285
290
|
const globalCssId = getGlobalStylesId(rangeCss);
|
|
@@ -307,9 +312,10 @@ export const Range = (props: RangeProps) => {
|
|
|
307
312
|
|
|
308
313
|
let currentVal1 = val1;
|
|
309
314
|
let currentVal2 = val2;
|
|
315
|
+
let isDisabled = !!props.disabled;
|
|
310
316
|
|
|
311
317
|
const adjustByStep = (direction: -1 | 1) => {
|
|
312
|
-
if (
|
|
318
|
+
if (isDisabled) return;
|
|
313
319
|
if (isRangeMode) {
|
|
314
320
|
let newVal = currentVal1 + direction * step;
|
|
315
321
|
newVal = Math.max(min, Math.min(currentVal2, newVal));
|
|
@@ -417,7 +423,7 @@ export const Range = (props: RangeProps) => {
|
|
|
417
423
|
};
|
|
418
424
|
|
|
419
425
|
const handleContainerClick = (e: any) => {
|
|
420
|
-
if (
|
|
426
|
+
if (isDisabled) return;
|
|
421
427
|
if (e.target && e.target.tagName === 'INPUT') return;
|
|
422
428
|
|
|
423
429
|
const wrapper = ref.$('.&-wrapper') as HTMLElement;
|
|
@@ -461,6 +467,7 @@ export const Range = (props: RangeProps) => {
|
|
|
461
467
|
};
|
|
462
468
|
|
|
463
469
|
const handleInput = (e: Event, isThumb2: boolean) => {
|
|
470
|
+
if (isDisabled) return;
|
|
464
471
|
let val = parseFloat((e.target as HTMLInputElement).value);
|
|
465
472
|
|
|
466
473
|
// Magnetic snapping
|
|
@@ -496,6 +503,7 @@ export const Range = (props: RangeProps) => {
|
|
|
496
503
|
};
|
|
497
504
|
|
|
498
505
|
const handleChange = () => {
|
|
506
|
+
if (isDisabled) return;
|
|
499
507
|
if (props.onChange) {
|
|
500
508
|
if (isRangeMode) {
|
|
501
509
|
props.onChange([currentVal1, currentVal2]);
|
|
@@ -522,6 +530,21 @@ export const Range = (props: RangeProps) => {
|
|
|
522
530
|
updateVisuals();
|
|
523
531
|
};
|
|
524
532
|
props.hook.getValue = () => (isRangeMode ? [currentVal1, currentVal2] : currentVal1);
|
|
533
|
+
props.hook.setDisabled = (disabled: boolean) => {
|
|
534
|
+
isDisabled = disabled;
|
|
535
|
+
const container = (ref.current as HTMLElement) || (ref.$?.('.&-container') as HTMLElement);
|
|
536
|
+
if (container) {
|
|
537
|
+
if (disabled) {
|
|
538
|
+
container.classList.add('disabled');
|
|
539
|
+
} else {
|
|
540
|
+
container.classList.remove('disabled');
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const inputs = ref.$all?.('.&-input') as NodeListOf<HTMLInputElement>;
|
|
544
|
+
inputs?.forEach?.((input) => {
|
|
545
|
+
input.disabled = disabled;
|
|
546
|
+
});
|
|
547
|
+
};
|
|
525
548
|
}
|
|
526
549
|
|
|
527
550
|
const ref: RefProps & { onUnload?: (el: Element) => Promise<void> | void } = {
|
|
@@ -563,7 +586,7 @@ export const Range = (props: RangeProps) => {
|
|
|
563
586
|
|
|
564
587
|
return (
|
|
565
588
|
<div
|
|
566
|
-
class={[globalCssId, '&-container', props.class,
|
|
589
|
+
class={[globalCssId, '&-container', props.class, isDisabled ? 'disabled' : '', isVertical ? 'vertical' : 'horizontal']
|
|
567
590
|
.join(' ')
|
|
568
591
|
.trim()}
|
|
569
592
|
ref={ref}
|
|
@@ -588,7 +611,7 @@ export const Range = (props: RangeProps) => {
|
|
|
588
611
|
value={val1}
|
|
589
612
|
onInput={(e) => handleInput(e, false)}
|
|
590
613
|
onChange={handleChange}
|
|
591
|
-
disabled={
|
|
614
|
+
disabled={isDisabled}
|
|
592
615
|
/>
|
|
593
616
|
<input
|
|
594
617
|
type='range'
|
|
@@ -599,7 +622,7 @@ export const Range = (props: RangeProps) => {
|
|
|
599
622
|
value={val2}
|
|
600
623
|
onInput={(e) => handleInput(e, true)}
|
|
601
624
|
onChange={handleChange}
|
|
602
|
-
disabled={
|
|
625
|
+
disabled={isDisabled}
|
|
603
626
|
/>
|
|
604
627
|
</>
|
|
605
628
|
) : (
|
|
@@ -612,7 +635,7 @@ export const Range = (props: RangeProps) => {
|
|
|
612
635
|
value={val1}
|
|
613
636
|
onInput={(e) => handleInput(e, false)}
|
|
614
637
|
onChange={handleChange}
|
|
615
|
-
disabled={
|
|
638
|
+
disabled={isDisabled}
|
|
616
639
|
/>
|
|
617
640
|
)}
|
|
618
641
|
|
|
@@ -11,6 +11,7 @@ export type ActionSheetColorPickerProps = {
|
|
|
11
11
|
/** Show the 16 preset color swatches. Default: true */
|
|
12
12
|
showPresets?: boolean;
|
|
13
13
|
zIndex?: string;
|
|
14
|
+
colorList?: string[];
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
function hexToRgb(hex: string): [number, number, number] {
|
|
@@ -55,6 +56,7 @@ export const ActionSheetColorPicker = async ({
|
|
|
55
56
|
cancelButtonText = 'Cancel',
|
|
56
57
|
showPresets = true,
|
|
57
58
|
zIndex,
|
|
59
|
+
colorList = PRESET_COLORS,
|
|
58
60
|
}: ActionSheetColorPickerProps): Promise<string | undefined> => {
|
|
59
61
|
let [r, g, b] = hexToRgb(value);
|
|
60
62
|
|
|
@@ -238,7 +240,7 @@ export const ActionSheetColorPicker = async ({
|
|
|
238
240
|
</div>
|
|
239
241
|
{showPresets && (
|
|
240
242
|
<div class='presets'>
|
|
241
|
-
{
|
|
243
|
+
{colorList.map((hex) => (
|
|
242
244
|
<div
|
|
243
245
|
class='preset-dot'
|
|
244
246
|
style={{ backgroundColor: hex }}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
// import { NotificationColor, NotificationMessage, updateTheme, PopupMenuWithIcon, CssProps } from
|
|
1
|
+
// import { NotificationColor, NotificationMessage, updateTheme, PopupMenuWithIcon, CssProps } from "lupine.components";
|
|
2
2
|
import { CssProps } from 'lupine.components';
|
|
3
3
|
import { MobileSideMenuHelper } from './mobile-side-menu';
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export interface MobileTopSysIconProps {
|
|
6
|
+
icon?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const MobileTopSysIcon = (props: MobileTopSysIconProps = {}) => {
|
|
10
|
+
const icon = props?.icon || 'bs-list';
|
|
6
11
|
const css: CssProps = {
|
|
7
12
|
cursor: 'pointer',
|
|
8
13
|
display: 'flex',
|
|
@@ -20,7 +25,7 @@ export const MobileTopSysIcon = () => {
|
|
|
20
25
|
};
|
|
21
26
|
return (
|
|
22
27
|
<div css={css} onClick={() => MobileSideMenuHelper.show()} class='mobile-top-sys-icon'>
|
|
23
|
-
<i class=
|
|
28
|
+
<i class={`ifc-icon ${icon}`}></i>
|
|
24
29
|
</div>
|
|
25
30
|
);
|
|
26
31
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CssProps, bindGlobalStyle } from 'lupine.web';
|
|
2
|
+
import { isSafeAreaSupported } from '../lib/support-safe-area';
|
|
2
3
|
/**
|
|
3
4
|
How to use:
|
|
4
5
|
Notification.sendMessage(message);
|
|
@@ -56,6 +57,8 @@ export class NotificationMessage {
|
|
|
56
57
|
padding: '0 10px',
|
|
57
58
|
zIndex: 'var(--layer-notice)',
|
|
58
59
|
pointerEvents: 'none',
|
|
60
|
+
'padding-top ': isSafeAreaSupported() ? 'constant(safe-area-inset-top)' : '',
|
|
61
|
+
'padding-top': isSafeAreaSupported() ? 'env(safe-area-inset-top)' : '',
|
|
59
62
|
'>div': {
|
|
60
63
|
pointerEvents: 'auto',
|
|
61
64
|
color: 'var(--notice-color-with-bg)',
|
|
@@ -1,130 +1,209 @@
|
|
|
1
1
|
import { CssProps, RefProps, VNode, bindGlobalStyle } from 'lupine.components';
|
|
2
2
|
|
|
3
|
+
export interface SlideTabHookProps {
|
|
4
|
+
moveTo?: (index: number) => void;
|
|
5
|
+
getIndex?: () => number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface SlideTabPage {
|
|
9
|
+
id?: string;
|
|
10
|
+
title: string;
|
|
11
|
+
content: VNode<any> | any;
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
export interface SlideTabProps {
|
|
4
|
-
pages:
|
|
15
|
+
pages: SlideTabPage[];
|
|
16
|
+
hook?: SlideTabHookProps;
|
|
17
|
+
initialIndex?: number;
|
|
18
|
+
onChange?: (index: number, page: SlideTabPage) => void;
|
|
19
|
+
navClass?: string;
|
|
20
|
+
class?: string;
|
|
5
21
|
}
|
|
22
|
+
|
|
6
23
|
export const SlideTabComponent = (props: SlideTabProps) => {
|
|
7
24
|
const css: CssProps = {
|
|
8
25
|
display: 'flex',
|
|
9
26
|
flexDirection: 'column',
|
|
10
27
|
flex: 1,
|
|
11
|
-
|
|
12
|
-
borderRadius: '6px',
|
|
13
|
-
padding: '0px 8px 4px 8px',
|
|
14
|
-
// marginBottom: '8px',
|
|
28
|
+
width: '100%',
|
|
15
29
|
height: '100%',
|
|
30
|
+
overflow: 'hidden',
|
|
31
|
+
position: 'relative',
|
|
32
|
+
boxSizing: 'border-box',
|
|
33
|
+
|
|
34
|
+
'.slide-tab-c-nav': {
|
|
35
|
+
display: 'flex',
|
|
36
|
+
flexDirection: 'row',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
backgroundColor: 'var(--card-bg, #ffffff)',
|
|
39
|
+
borderBottom: '0.5px solid var(--card-border, rgba(60, 60, 67, 0.15))',
|
|
40
|
+
padding: '10px 16px 8px 16px',
|
|
41
|
+
overflowX: 'auto',
|
|
42
|
+
WebkitOverflowScrolling: 'touch',
|
|
43
|
+
flexShrink: 0,
|
|
44
|
+
zIndex: 10,
|
|
45
|
+
scrollbarWidth: 'none',
|
|
46
|
+
'&::-webkit-scrollbar': { display: 'none' },
|
|
47
|
+
},
|
|
48
|
+
'.slide-tab-c-nav-wrap': {
|
|
49
|
+
display: 'flex',
|
|
50
|
+
flexDirection: 'row',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
gap: '8px',
|
|
53
|
+
flexShrink: 0,
|
|
54
|
+
paddingRight: '16px',
|
|
55
|
+
},
|
|
56
|
+
'.slide-tab-c-nav-item': {
|
|
57
|
+
cursor: 'pointer',
|
|
58
|
+
padding: '7px 16px',
|
|
59
|
+
borderRadius: '20px',
|
|
60
|
+
fontSize: '13px',
|
|
61
|
+
fontWeight: 600,
|
|
62
|
+
color: 'var(--text-secondary, #8e8e93)',
|
|
63
|
+
backgroundColor: 'var(--bg-container, #f2f2f7)',
|
|
64
|
+
whiteSpace: 'nowrap',
|
|
65
|
+
transition: 'all 0.18s ease',
|
|
66
|
+
WebkitTapHighlightColor: 'transparent',
|
|
67
|
+
flexShrink: 0,
|
|
68
|
+
userSelect: 'none',
|
|
69
|
+
WebkitUserSelect: 'none',
|
|
70
|
+
'&:active': {
|
|
71
|
+
transform: 'scale(0.96)',
|
|
72
|
+
opacity: 0.85,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
'.slide-tab-c-nav-item.active': {
|
|
76
|
+
backgroundColor: 'var(--primary-accent-color, #0284c7)',
|
|
77
|
+
color: '#ffffff',
|
|
78
|
+
boxShadow: '0 2px 8px rgba(2, 132, 199, 0.35)',
|
|
79
|
+
},
|
|
80
|
+
|
|
16
81
|
'.slide-tab-c-list': {
|
|
17
82
|
flex: 1,
|
|
18
|
-
borderRadius: '6px',
|
|
19
83
|
display: 'flex',
|
|
84
|
+
flexDirection: 'row',
|
|
20
85
|
overflowX: 'auto',
|
|
86
|
+
overflowY: 'hidden',
|
|
21
87
|
width: '100%',
|
|
88
|
+
height: '100%',
|
|
22
89
|
scrollSnapType: 'x mandatory',
|
|
23
|
-
gap: '8px',
|
|
24
|
-
paddingBottom: '10px',
|
|
25
90
|
scrollBehavior: 'smooth',
|
|
26
91
|
WebkitOverflowScrolling: 'touch',
|
|
92
|
+
boxSizing: 'border-box',
|
|
93
|
+
scrollbarWidth: 'none',
|
|
94
|
+
'&::-webkit-scrollbar': { display: 'none' },
|
|
27
95
|
},
|
|
28
96
|
'.slide-tab-c-slide': {
|
|
29
97
|
width: '100%',
|
|
30
|
-
overflow: 'hidden',
|
|
31
|
-
position: 'relative',
|
|
32
98
|
minWidth: '100%',
|
|
99
|
+
maxWidth: '100%',
|
|
33
100
|
flexShrink: 0,
|
|
34
|
-
scrollSnapAlign: 'start',
|
|
35
101
|
height: '100%',
|
|
36
102
|
overflowY: 'auto',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
position: 'sticky',
|
|
45
|
-
top: 0,
|
|
46
|
-
zIndex: 1,
|
|
47
|
-
},
|
|
48
|
-
'.slide-tab-c-nav-wrap': {
|
|
49
|
-
display: 'flex',
|
|
50
|
-
flexDirection: 'row',
|
|
51
|
-
justifyContent: 'center',
|
|
52
|
-
padding: '2px 4px',
|
|
53
|
-
borderRadius: '4px',
|
|
54
|
-
backgroundColor: 'var(--secondary-bg-color)',
|
|
55
|
-
},
|
|
56
|
-
'.slide-tab-c-nav-item': {
|
|
57
|
-
cursor: 'pointer',
|
|
58
|
-
padding: '4px 8px',
|
|
59
|
-
borderRadius: '4px',
|
|
60
|
-
marginRight: '8px',
|
|
61
|
-
},
|
|
62
|
-
'.slide-tab-c-nav-item.active': {
|
|
63
|
-
backgroundColor: 'var(--primary-accent-color)',
|
|
64
|
-
color: 'white',
|
|
103
|
+
position: 'relative',
|
|
104
|
+
scrollSnapAlign: 'start',
|
|
105
|
+
scrollSnapStop: 'always',
|
|
106
|
+
WebkitOverflowScrolling: 'touch',
|
|
107
|
+
boxSizing: 'border-box',
|
|
108
|
+
scrollbarWidth: 'none',
|
|
109
|
+
'&::-webkit-scrollbar': { display: 'none' },
|
|
65
110
|
},
|
|
66
111
|
};
|
|
67
112
|
bindGlobalStyle('slide-tab-c-box', css);
|
|
68
113
|
|
|
69
114
|
const ref: RefProps = {};
|
|
70
|
-
let slideIndex = 0;
|
|
115
|
+
let slideIndex = props.initialIndex || 0;
|
|
71
116
|
let manualScroll = false;
|
|
72
|
-
let scrollEndTimer:
|
|
73
|
-
|
|
74
|
-
if (manualScroll) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (scrollEndTimer) {
|
|
78
|
-
clearTimeout(scrollEndTimer);
|
|
79
|
-
}
|
|
80
|
-
scrollEndTimer = setTimeout(() => {
|
|
81
|
-
drawerScrollStop();
|
|
82
|
-
}, 100);
|
|
83
|
-
};
|
|
117
|
+
let scrollEndTimer: any = null;
|
|
118
|
+
|
|
84
119
|
const resetSlides = (index: number) => {
|
|
85
|
-
const dots = ref.$all('.slide-tab-c-nav-item');
|
|
86
|
-
|
|
87
|
-
|
|
120
|
+
const dots = ref.$all?.('.slide-tab-c-nav-item');
|
|
121
|
+
if (dots) {
|
|
122
|
+
for (let i = 0; i < dots.length; i++) {
|
|
123
|
+
dots[i].classList.toggle('active', i === index);
|
|
124
|
+
}
|
|
125
|
+
dots[index]?.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
|
126
|
+
}
|
|
127
|
+
if (props.onChange && props.pages[index]) {
|
|
128
|
+
props.onChange(index, props.pages[index]);
|
|
88
129
|
}
|
|
89
130
|
};
|
|
131
|
+
|
|
90
132
|
const drawerScrollStop = () => {
|
|
91
|
-
const drawer = ref
|
|
133
|
+
const drawer = ref.$?.('.slide-tab-c-list') as HTMLElement | undefined;
|
|
134
|
+
if (!drawer) return;
|
|
92
135
|
const width = drawer.clientWidth;
|
|
136
|
+
if (width <= 0) return;
|
|
93
137
|
const currentScrollIndex = Math.round(drawer.scrollLeft / width);
|
|
94
|
-
slideIndex
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const moveSlide = (slideIndex: number) => {
|
|
98
|
-
const drawer = ref.$('.slide-tab-c-list');
|
|
99
|
-
const children = ref.$all('.slide-tab-c-slide');
|
|
100
|
-
if (!drawer || !children || children.length === 0) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const target = children[slideIndex];
|
|
104
|
-
if (!target) {
|
|
105
|
-
return;
|
|
138
|
+
if (currentScrollIndex !== slideIndex && currentScrollIndex >= 0 && currentScrollIndex < props.pages.length) {
|
|
139
|
+
slideIndex = currentScrollIndex;
|
|
140
|
+
resetSlides(slideIndex);
|
|
106
141
|
}
|
|
107
|
-
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const drawerScroll = () => {
|
|
145
|
+
if (manualScroll) return;
|
|
146
|
+
if (scrollEndTimer) clearTimeout(scrollEndTimer);
|
|
147
|
+
scrollEndTimer = setTimeout(() => {
|
|
148
|
+
drawerScrollStop();
|
|
149
|
+
}, 60);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const moveSlide = (targetIndex: number) => {
|
|
153
|
+
const drawer = ref.$?.('.slide-tab-c-list') as HTMLElement | undefined;
|
|
154
|
+
if (!drawer) return;
|
|
155
|
+
const width = drawer.clientWidth;
|
|
156
|
+
if (width <= 0) return;
|
|
157
|
+
|
|
108
158
|
manualScroll = true;
|
|
159
|
+
slideIndex = targetIndex;
|
|
160
|
+
resetSlides(slideIndex);
|
|
161
|
+
|
|
109
162
|
drawer.scrollTo({
|
|
110
|
-
left:
|
|
163
|
+
left: targetIndex * width,
|
|
111
164
|
behavior: 'smooth',
|
|
112
165
|
});
|
|
113
166
|
|
|
114
|
-
resetSlides(slideIndex);
|
|
115
167
|
setTimeout(() => {
|
|
116
168
|
manualScroll = false;
|
|
117
|
-
},
|
|
169
|
+
}, 350);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
if (props.hook) {
|
|
173
|
+
props.hook.moveTo = moveSlide;
|
|
174
|
+
props.hook.getIndex = () => slideIndex;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
ref.onLoad = async () => {
|
|
178
|
+
const drawer = ref.$?.('.slide-tab-c-list') as HTMLElement | undefined;
|
|
179
|
+
if (drawer) {
|
|
180
|
+
drawer.addEventListener('scrollend', drawerScrollStop);
|
|
181
|
+
}
|
|
182
|
+
if (slideIndex > 0) {
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
moveSlide(slideIndex);
|
|
185
|
+
}, 50);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
ref.onUnload = async () => {
|
|
190
|
+
const drawer = ref.$?.('.slide-tab-c-list') as HTMLElement | undefined;
|
|
191
|
+
if (drawer) {
|
|
192
|
+
drawer.removeEventListener('scrollend', drawerScrollStop);
|
|
193
|
+
}
|
|
194
|
+
if (scrollEndTimer) {
|
|
195
|
+
clearTimeout(scrollEndTimer);
|
|
196
|
+
}
|
|
118
197
|
};
|
|
119
198
|
|
|
120
199
|
return (
|
|
121
|
-
<section class=
|
|
122
|
-
<div class=
|
|
123
|
-
<div class=
|
|
200
|
+
<section class={`slide-tab-c-box ${props.class || ''}`} ref={ref}>
|
|
201
|
+
<div class={`slide-tab-c-nav no-scrollbar-container ${props.navClass || ''}`}>
|
|
202
|
+
<div class="slide-tab-c-nav-wrap">
|
|
124
203
|
{props.pages.map((page, index) => (
|
|
125
204
|
<div
|
|
126
|
-
class={`slide-tab-c-nav-item ${index ===
|
|
127
|
-
onClick={(event) => {
|
|
205
|
+
class={`slide-tab-c-nav-item ${index === slideIndex ? 'active' : ''}`}
|
|
206
|
+
onClick={(event: any) => {
|
|
128
207
|
event.preventDefault();
|
|
129
208
|
moveSlide(index);
|
|
130
209
|
}}
|
|
@@ -134,9 +213,9 @@ export const SlideTabComponent = (props: SlideTabProps) => {
|
|
|
134
213
|
))}
|
|
135
214
|
</div>
|
|
136
215
|
</div>
|
|
137
|
-
<div class=
|
|
216
|
+
<div class="slide-tab-c-list no-scrollbar-container" onScroll={drawerScroll}>
|
|
138
217
|
{props.pages.map((page) => (
|
|
139
|
-
<div class=
|
|
218
|
+
<div class="slide-tab-c-slide no-scrollbar-container">{page.content}</div>
|
|
140
219
|
))}
|
|
141
220
|
</div>
|
|
142
221
|
</section>
|