lupine.components 1.1.13 → 1.1.15

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.
Files changed (92) hide show
  1. package/README.md +3 -3
  2. package/package.json +42 -42
  3. package/src/components/action-sheet.tsx +419 -419
  4. package/src/components/button-push-animation.tsx +147 -138
  5. package/src/components/button.tsx +55 -55
  6. package/src/components/desktop-footer.tsx +17 -17
  7. package/src/components/desktop-header.tsx +52 -52
  8. package/src/components/drag-refresh.tsx +129 -129
  9. package/src/components/editable-label.tsx +83 -83
  10. package/src/components/float-window.tsx +233 -233
  11. package/src/components/grid.tsx +18 -18
  12. package/src/components/html-load.tsx +41 -41
  13. package/src/components/html-var.tsx +81 -81
  14. package/src/components/index.ts +43 -44
  15. package/src/components/input-with-title.tsx +24 -24
  16. package/src/components/link-item.tsx +13 -13
  17. package/src/components/link-list.tsx +62 -62
  18. package/src/components/menu-bar.tsx +219 -219
  19. package/src/components/menu-item-props.tsx +13 -13
  20. package/src/components/menu-sidebar.tsx +325 -318
  21. package/src/components/message-box.tsx +44 -44
  22. package/src/components/meta-data.tsx +36 -36
  23. package/src/components/meta-description.tsx +12 -12
  24. package/src/components/mobile-components/icon-menu-item-props.ts +6 -6
  25. package/src/components/mobile-components/index.ts +8 -9
  26. package/src/components/mobile-components/mobile-footer-menu.tsx +95 -95
  27. package/src/components/mobile-components/mobile-header-component.tsx +101 -101
  28. package/src/components/mobile-components/mobile-header-title-icon.tsx +109 -101
  29. package/src/components/mobile-components/mobile-header-with-back.tsx +127 -117
  30. package/src/components/mobile-components/mobile-side-menu.tsx +154 -154
  31. package/src/components/mobile-components/mobile-top-sys-icon.tsx +18 -18
  32. package/src/components/mobile-components/mobile-top-sys-menu.tsx +62 -62
  33. package/src/components/modal.tsx +33 -33
  34. package/src/components/notice-message.tsx +118 -118
  35. package/src/components/page-title.tsx +6 -6
  36. package/src/components/paging-link.tsx +175 -175
  37. package/src/components/panel.tsx +21 -21
  38. package/src/components/popup-menu.tsx +289 -289
  39. package/src/components/progress.tsx +91 -91
  40. package/src/components/radio-label-component.tsx +36 -36
  41. package/src/components/redirect.tsx +19 -19
  42. package/src/components/resizable-splitter.tsx +128 -128
  43. package/src/components/select-angle-component.tsx +127 -127
  44. package/src/components/select-with-title.tsx +37 -37
  45. package/src/components/slide-tab-component.tsx +144 -149
  46. package/src/components/spinner.tsx +106 -100
  47. package/src/components/stars-component.tsx +66 -66
  48. package/src/components/svg.tsx +24 -24
  49. package/src/components/tabs.tsx +279 -279
  50. package/src/components/text-glow.tsx +37 -37
  51. package/src/components/text-scale.tsx +42 -42
  52. package/src/components/text-wave.tsx +55 -55
  53. package/src/components/theme-selector.tsx +28 -28
  54. package/src/components/toggle-base.tsx +285 -269
  55. package/src/components/toggle-switch.tsx +160 -160
  56. package/src/frames/index.ts +3 -3
  57. package/src/frames/responsive-frame.tsx +83 -83
  58. package/src/frames/slider-frame.tsx +111 -111
  59. package/src/frames/top-frame.tsx +30 -30
  60. package/src/index.ts +5 -5
  61. package/src/lib/back-action-helper.ts +54 -54
  62. package/src/lib/base62.ts +23 -23
  63. package/src/lib/blob-utils.ts +23 -23
  64. package/src/lib/calculate-text-width.ts +13 -13
  65. package/src/lib/date-utils.ts +317 -317
  66. package/src/lib/deep-merge.ts +37 -37
  67. package/src/lib/document-ready.ts +34 -34
  68. package/src/lib/dom-utils.ts +32 -32
  69. package/src/lib/download-file.ts +118 -118
  70. package/src/lib/download-link.ts +12 -12
  71. package/src/lib/download-stream.ts +19 -19
  72. package/src/lib/drag-util.ts +118 -118
  73. package/src/lib/dynamical-load.ts +134 -134
  74. package/src/lib/encode-html.ts +27 -27
  75. package/src/lib/find-parent-tag.ts +8 -8
  76. package/src/lib/format-bytes.ts +11 -11
  77. package/src/lib/index.ts +24 -24
  78. package/src/lib/lite-dom.ts +225 -225
  79. package/src/lib/message-hub.ts +103 -104
  80. package/src/lib/observable.ts +188 -188
  81. package/src/lib/path-utils.ts +42 -42
  82. package/src/lib/promise-timeout.ts +1 -1
  83. package/src/lib/simple-storage.ts +40 -40
  84. package/src/lib/stop-propagation.ts +7 -7
  85. package/src/lib/upload-file.ts +101 -101
  86. package/src/styles/base-themes.ts +17 -17
  87. package/src/styles/dark-themes.ts +99 -99
  88. package/src/styles/index.ts +5 -5
  89. package/src/styles/light-themes.ts +106 -106
  90. package/src/styles/media-query.ts +93 -93
  91. package/src/styles/shared-themes.ts +57 -57
  92. package/tsconfig.json +113 -113
@@ -1,127 +1,127 @@
1
- import { CssProps, RefProps } from 'lupine.components';
2
-
3
- export type SelectAngleComponentHookProps = {
4
- setAngle?: (angle: number) => void;
5
- };
6
- export type SelectAngleComponentProps = {
7
- size?: string;
8
- angle: number;
9
- onChange: (angle: number) => void;
10
- hook?: SelectAngleComponentHookProps;
11
- };
12
- export const SelectAngleComponent = (props: SelectAngleComponentProps) => {
13
- const css: CssProps = {
14
- width: props.size || '80px',
15
- height: props.size || '80px',
16
- '&circle': {
17
- width: '100%',
18
- height: '100%',
19
- borderRadius: '50%',
20
- border: '2px solid #aaa',
21
- position: 'relative',
22
- backgroundColor: 'var(--primary-bg-color)',
23
- cursor: 'pointer',
24
- },
25
- '&needle': {
26
- width: '2px',
27
- height: '50%',
28
- backgroundColor: 'red',
29
- position: 'absolute',
30
- top: '0',
31
- left: '50%',
32
- transformOrigin: 'bottom center',
33
- transform: 'rotate(90deg)',
34
- },
35
- '&tips': {
36
- position: 'absolute',
37
- top: '50%',
38
- left: '50%',
39
- transform: 'translate(-50%, -50%)',
40
- fontSize: '12px',
41
- color: 'var(--primary-color)',
42
- fontWeight: '600',
43
- zIndex: '10',
44
- },
45
- '&a0, &a90, &a180, &a270': {
46
- width: '6px',
47
- height: '6px',
48
- borderRadius: '50%',
49
- backgroundColor: '#333',
50
- position: 'absolute',
51
- top: '0',
52
- left: '50%',
53
- transform: 'translate(-50%, -50%)',
54
- fontSize: '12px',
55
- color: '#333',
56
- },
57
- '&a90': {
58
- top: '50%',
59
- left: '100%',
60
- },
61
- '&a180': {
62
- top: '100%',
63
- left: '50%',
64
- },
65
- '&a270': {
66
- top: '50%',
67
- left: '0',
68
- },
69
- };
70
-
71
- let cx: number = 0;
72
- let cy: number = 0;
73
- let mv = false;
74
- if (props.hook) {
75
- props.hook.setAngle = (angle) => {
76
- updateAngleSub(angle);
77
- };
78
- }
79
- const updateAngle = (ev: MouseEvent) => {
80
- const dx = ev.clientX - cx;
81
- const dy = ev.clientY - cy;
82
- // atan2 返回弧度,顺时针0°为右侧
83
- let deg = Math.atan2(dy, dx) * (180 / Math.PI);
84
- deg = (deg + 450) % 360; // 让上方为0°
85
- updateAngleSub(deg);
86
- };
87
- const updateAngleSub = (deg: number) => {
88
- const needle = ref.$('&needle');
89
- const text = ref.$('&tips');
90
- needle.style.transform = `rotate(${deg}deg)`;
91
- text.textContent = `${deg.toFixed(0)}°`;
92
- props.onChange(deg);
93
- };
94
-
95
- const pointerdown = (ev: MouseEvent) => {
96
- const picker = ref.$('&circle');
97
- const rect = picker.getBoundingClientRect();
98
- cx = rect.left + rect.width / 2;
99
- cy = rect.top + rect.height / 2;
100
-
101
- updateAngle(ev);
102
- mv = true;
103
- };
104
- const pointermove = (ev: MouseEvent) => {
105
- if (!mv) {
106
- return;
107
- }
108
- updateAngle(ev);
109
- };
110
- const pointerup = () => {
111
- mv = false;
112
- };
113
- const ref: RefProps = {};
114
- return (
115
- <div ref={ref} css={css}>
116
- <div class='&circle' onPointerDown={pointerdown} onPointerMove={pointermove} onPointerUp={pointerup}>
117
- <div class='&needle'></div>
118
- <div class='&tips'>90°</div>
119
-
120
- <div class='&a0' onClick={() => updateAngleSub(0)}></div>
121
- <div class='&a90' onClick={() => updateAngleSub(90)}></div>
122
- <div class='&a180' onClick={() => updateAngleSub(180)}></div>
123
- <div class='&a270' onClick={() => updateAngleSub(270)}></div>
124
- </div>
125
- </div>
126
- );
127
- };
1
+ import { CssProps, RefProps } from 'lupine.components';
2
+
3
+ export type SelectAngleComponentHookProps = {
4
+ setAngle?: (angle: number) => void;
5
+ };
6
+ export type SelectAngleComponentProps = {
7
+ size?: string;
8
+ angle: number;
9
+ onChange: (angle: number) => void;
10
+ hook?: SelectAngleComponentHookProps;
11
+ };
12
+ export const SelectAngleComponent = (props: SelectAngleComponentProps) => {
13
+ const css: CssProps = {
14
+ width: props.size || '80px',
15
+ height: props.size || '80px',
16
+ '&circle': {
17
+ width: '100%',
18
+ height: '100%',
19
+ borderRadius: '50%',
20
+ border: '2px solid #aaa',
21
+ position: 'relative',
22
+ backgroundColor: 'var(--primary-bg-color)',
23
+ cursor: 'pointer',
24
+ },
25
+ '&needle': {
26
+ width: '2px',
27
+ height: '50%',
28
+ backgroundColor: 'red',
29
+ position: 'absolute',
30
+ top: '0',
31
+ left: '50%',
32
+ transformOrigin: 'bottom center',
33
+ transform: 'rotate(90deg)',
34
+ },
35
+ '&tips': {
36
+ position: 'absolute',
37
+ top: '50%',
38
+ left: '50%',
39
+ transform: 'translate(-50%, -50%)',
40
+ fontSize: '12px',
41
+ color: 'var(--primary-color)',
42
+ fontWeight: '600',
43
+ zIndex: '10',
44
+ },
45
+ '&a0, &a90, &a180, &a270': {
46
+ width: '6px',
47
+ height: '6px',
48
+ borderRadius: '50%',
49
+ backgroundColor: '#333',
50
+ position: 'absolute',
51
+ top: '0',
52
+ left: '50%',
53
+ transform: 'translate(-50%, -50%)',
54
+ fontSize: '12px',
55
+ color: '#333',
56
+ },
57
+ '&a90': {
58
+ top: '50%',
59
+ left: '100%',
60
+ },
61
+ '&a180': {
62
+ top: '100%',
63
+ left: '50%',
64
+ },
65
+ '&a270': {
66
+ top: '50%',
67
+ left: '0',
68
+ },
69
+ };
70
+
71
+ let cx: number = 0;
72
+ let cy: number = 0;
73
+ let mv = false;
74
+ if (props.hook) {
75
+ props.hook.setAngle = (angle) => {
76
+ updateAngleSub(angle);
77
+ };
78
+ }
79
+ const updateAngle = (ev: MouseEvent) => {
80
+ const dx = ev.clientX - cx;
81
+ const dy = ev.clientY - cy;
82
+ // atan2 返回弧度,顺时针0°为右侧
83
+ let deg = Math.atan2(dy, dx) * (180 / Math.PI);
84
+ deg = (deg + 450) % 360; // 让上方为0°
85
+ updateAngleSub(deg);
86
+ };
87
+ const updateAngleSub = (deg: number) => {
88
+ const needle = ref.$('&needle');
89
+ const text = ref.$('&tips');
90
+ needle.style.transform = `rotate(${deg}deg)`;
91
+ text.textContent = `${deg.toFixed(0)}°`;
92
+ props.onChange(deg);
93
+ };
94
+
95
+ const pointerdown = (ev: MouseEvent) => {
96
+ const picker = ref.$('&circle');
97
+ const rect = picker.getBoundingClientRect();
98
+ cx = rect.left + rect.width / 2;
99
+ cy = rect.top + rect.height / 2;
100
+
101
+ updateAngle(ev);
102
+ mv = true;
103
+ };
104
+ const pointermove = (ev: MouseEvent) => {
105
+ if (!mv) {
106
+ return;
107
+ }
108
+ updateAngle(ev);
109
+ };
110
+ const pointerup = () => {
111
+ mv = false;
112
+ };
113
+ const ref: RefProps = {};
114
+ return (
115
+ <div ref={ref} css={css}>
116
+ <div class='&circle' onPointerDown={pointerdown} onPointerMove={pointermove} onPointerUp={pointerup}>
117
+ <div class='&needle'></div>
118
+ <div class='&tips'>90°</div>
119
+
120
+ <div class='&a0' onClick={() => updateAngleSub(0)}></div>
121
+ <div class='&a90' onClick={() => updateAngleSub(90)}></div>
122
+ <div class='&a180' onClick={() => updateAngleSub(180)}></div>
123
+ <div class='&a270' onClick={() => updateAngleSub(270)}></div>
124
+ </div>
125
+ </div>
126
+ );
127
+ };
@@ -1,37 +1,37 @@
1
- import { CssProps } from 'lupine.web';
2
-
3
- export type SelectOptionProps = {
4
- option: string;
5
- value: string;
6
- selected?: boolean;
7
- };
8
- export const SelectWithTitle = (
9
- title: string,
10
- options: SelectOptionProps[],
11
- onOptionChanged: (option: string) => void,
12
- size?: number,
13
- className = 'input-base',
14
- width = '100%',
15
- ) => {
16
- const css: CssProps = {
17
- select: {
18
- height: 'auto',
19
- overflowY: 'auto',
20
- width,
21
- },
22
- };
23
- return (
24
- <div css={css}>
25
- <div>{title}</div>
26
- <div>
27
- <select class={className} onChange={(e: any) => onOptionChanged(e?.target?.value)} size={size}>
28
- {options.map((option) => (
29
- <option value={option.value} selected={option.selected}>
30
- {option.option}
31
- </option>
32
- ))}
33
- </select>
34
- </div>
35
- </div>
36
- );
37
- };
1
+ import { CssProps } from 'lupine.web';
2
+
3
+ export type SelectOptionProps = {
4
+ option: string;
5
+ value: string;
6
+ selected?: boolean;
7
+ };
8
+ export const SelectWithTitle = (
9
+ title: string,
10
+ options: SelectOptionProps[],
11
+ onOptionChanged: (option: string) => void,
12
+ size?: number,
13
+ className = 'input-base',
14
+ width = '100%'
15
+ ) => {
16
+ const css: CssProps = {
17
+ select: {
18
+ height: 'auto',
19
+ overflowY: 'auto',
20
+ width,
21
+ },
22
+ };
23
+ return (
24
+ <div css={css}>
25
+ <div>{title}</div>
26
+ <div>
27
+ <select class={className} onChange={(e: any) => onOptionChanged(e?.target?.value)} size={size}>
28
+ {options.map((option) => (
29
+ <option value={option.value} selected={option.selected}>
30
+ {option.option}
31
+ </option>
32
+ ))}
33
+ </select>
34
+ </div>
35
+ </div>
36
+ );
37
+ };
@@ -1,149 +1,144 @@
1
- import { CssProps, RefProps, VNode, bindGlobalStyle } from 'lupine.components';
2
-
3
- export interface SlideTabProps {
4
- pages: { title: string; content: VNode<any> }[];
5
- };
6
- export const SlideTabComponent = (props: SlideTabProps) => {
7
- const css: CssProps = {
8
- display: 'flex',
9
- flexDirection: 'column',
10
- flex: 1,
11
- fontSize: '12px',
12
- borderRadius: '6px',
13
- padding: '0px 8px 4px 8px',
14
- // marginBottom: '8px',
15
- height: '100%',
16
- '.slide-tab-c-list': {
17
- flex: 1,
18
- borderRadius: '6px',
19
- display: 'flex',
20
- overflowX: 'auto',
21
- width: '100%',
22
- scrollSnapType: 'x mandatory',
23
- gap: '8px',
24
- paddingBottom: '10px',
25
- scrollBehavior: 'smooth',
26
- WebkitOverflowScrolling: 'touch',
27
- },
28
- '.slide-tab-c-slide': {
29
- width: '100%',
30
- overflow: 'hidden',
31
- position: 'relative',
32
- minWidth: '100%',
33
- flexShrink: 0,
34
- scrollSnapAlign: 'start',
35
- height: '100%',
36
- overflowY: 'auto',
37
- },
38
-
39
- '.slide-tab-c-nav': {
40
- display: 'flex',
41
- flexDirection: 'row',
42
- justifyContent: 'center',
43
- backgroundColor: 'var(--primary-bg-color)',
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',
65
- },
66
- };
67
- bindGlobalStyle('slide-tab-c-box', css);
68
-
69
- const ref: RefProps = {};
70
- let slideIndex = 0;
71
- let manualScroll = false;
72
- let scrollEndTimer: NodeJS.Timeout | null = null;
73
- const drawerScroll = () => {
74
- if (manualScroll) {
75
- return;
76
- }
77
- if (scrollEndTimer) {
78
- clearTimeout(scrollEndTimer);
79
- }
80
- scrollEndTimer = setTimeout(() => {
81
- drawerScrollStop();
82
- }, 100);
83
- };
84
- const resetSlides = (index: number) => {
85
- const dots = ref.$all('.slide-tab-c-nav-item');
86
- for (let i = 0; i < dots.length; i++) {
87
- dots[i].classList.toggle('active', i === index);
88
- }
89
- };
90
- const drawerScrollStop = () => {
91
- const drawer = ref.$('.slide-tab-c-list');
92
- const width = drawer.clientWidth;
93
- const currentScrollIndex = Math.round(drawer.scrollLeft / width);
94
- slideIndex = currentScrollIndex;
95
- resetSlides(slideIndex);
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;
106
- }
107
- const offsetLeft = target.offsetLeft;
108
- manualScroll = true;
109
- drawer.scrollTo({
110
- left: offsetLeft,
111
- behavior: 'smooth',
112
- });
113
-
114
- resetSlides(slideIndex);
115
- setTimeout(() => {
116
- manualScroll = false;
117
- }, 300);
118
- };
119
-
120
- return (
121
- <section class='slide-tab-c-box' ref={ref}>
122
- <div class='slide-tab-c-nav'>
123
- <div class='slide-tab-c-nav-wrap'>
124
- {props.pages.map((page, index) => (
125
- <div
126
- class={`slide-tab-c-nav-item ${index === 0 ? 'active' : ''}`}
127
- onClick={(event) => {
128
- event.preventDefault();
129
- moveSlide(index);
130
- }}
131
- >
132
- {page.title}
133
- </div>
134
- ))}
135
-
136
- </div>
137
- </div>
138
- <div class='slide-tab-c-list no-scrollbar-container' onScroll={drawerScroll}>
139
-
140
- {props.pages.map((page) => (
141
- <div class='slide-tab-c-slide no-scrollbar-container'>
142
- {page.content}
143
- </div>
144
- ))}
145
-
146
- </div>
147
- </section>
148
- );
149
- };
1
+ import { CssProps, RefProps, VNode, bindGlobalStyle } from 'lupine.components';
2
+
3
+ export interface SlideTabProps {
4
+ pages: { title: string; content: VNode<any> }[];
5
+ }
6
+ export const SlideTabComponent = (props: SlideTabProps) => {
7
+ const css: CssProps = {
8
+ display: 'flex',
9
+ flexDirection: 'column',
10
+ flex: 1,
11
+ fontSize: '12px',
12
+ borderRadius: '6px',
13
+ padding: '0px 8px 4px 8px',
14
+ // marginBottom: '8px',
15
+ height: '100%',
16
+ '.slide-tab-c-list': {
17
+ flex: 1,
18
+ borderRadius: '6px',
19
+ display: 'flex',
20
+ overflowX: 'auto',
21
+ width: '100%',
22
+ scrollSnapType: 'x mandatory',
23
+ gap: '8px',
24
+ paddingBottom: '10px',
25
+ scrollBehavior: 'smooth',
26
+ WebkitOverflowScrolling: 'touch',
27
+ },
28
+ '.slide-tab-c-slide': {
29
+ width: '100%',
30
+ overflow: 'hidden',
31
+ position: 'relative',
32
+ minWidth: '100%',
33
+ flexShrink: 0,
34
+ scrollSnapAlign: 'start',
35
+ height: '100%',
36
+ overflowY: 'auto',
37
+ },
38
+
39
+ '.slide-tab-c-nav': {
40
+ display: 'flex',
41
+ flexDirection: 'row',
42
+ justifyContent: 'center',
43
+ backgroundColor: 'var(--primary-bg-color)',
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',
65
+ },
66
+ };
67
+ bindGlobalStyle('slide-tab-c-box', css);
68
+
69
+ const ref: RefProps = {};
70
+ let slideIndex = 0;
71
+ let manualScroll = false;
72
+ let scrollEndTimer: NodeJS.Timeout | null = null;
73
+ const drawerScroll = () => {
74
+ if (manualScroll) {
75
+ return;
76
+ }
77
+ if (scrollEndTimer) {
78
+ clearTimeout(scrollEndTimer);
79
+ }
80
+ scrollEndTimer = setTimeout(() => {
81
+ drawerScrollStop();
82
+ }, 100);
83
+ };
84
+ const resetSlides = (index: number) => {
85
+ const dots = ref.$all('.slide-tab-c-nav-item');
86
+ for (let i = 0; i < dots.length; i++) {
87
+ dots[i].classList.toggle('active', i === index);
88
+ }
89
+ };
90
+ const drawerScrollStop = () => {
91
+ const drawer = ref.$('.slide-tab-c-list');
92
+ const width = drawer.clientWidth;
93
+ const currentScrollIndex = Math.round(drawer.scrollLeft / width);
94
+ slideIndex = currentScrollIndex;
95
+ resetSlides(slideIndex);
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;
106
+ }
107
+ const offsetLeft = target.offsetLeft;
108
+ manualScroll = true;
109
+ drawer.scrollTo({
110
+ left: offsetLeft,
111
+ behavior: 'smooth',
112
+ });
113
+
114
+ resetSlides(slideIndex);
115
+ setTimeout(() => {
116
+ manualScroll = false;
117
+ }, 300);
118
+ };
119
+
120
+ return (
121
+ <section class='slide-tab-c-box' ref={ref}>
122
+ <div class='slide-tab-c-nav'>
123
+ <div class='slide-tab-c-nav-wrap'>
124
+ {props.pages.map((page, index) => (
125
+ <div
126
+ class={`slide-tab-c-nav-item ${index === 0 ? 'active' : ''}`}
127
+ onClick={(event) => {
128
+ event.preventDefault();
129
+ moveSlide(index);
130
+ }}
131
+ >
132
+ {page.title}
133
+ </div>
134
+ ))}
135
+ </div>
136
+ </div>
137
+ <div class='slide-tab-c-list no-scrollbar-container' onScroll={drawerScroll}>
138
+ {props.pages.map((page) => (
139
+ <div class='slide-tab-c-slide no-scrollbar-container'>{page.content}</div>
140
+ ))}
141
+ </div>
142
+ </section>
143
+ );
144
+ };