UNPKG

15.2 kBJavaScriptView Raw
1import { h, r as registerInstance, c as createEvent, H as Host, g as getElement } from './index-8809c729.js';
2import Taro from '@tarojs/taro';
3import { c as classnames } from './index-1d8e8acd.js';
4
5const splitUrl = _url => {
6 let url = _url || '';
7 let pos;
8 const res = {
9 path: null,
10 query: null,
11 fragment: null
12 };
13 pos = url.indexOf('#');
14 if (pos > -1) {
15 res.fragment = url.substring(pos + 1);
16 url = url.substring(0, pos);
17 }
18 pos = url.indexOf('?');
19 if (pos > -1) {
20 res.query = url.substring(pos + 1);
21 url = url.substring(0, pos);
22 }
23 res.path = url;
24 return res;
25};
26
27// export const removeLeadingSlash = (str = '') => str.replace(/^\.?\//, '')
28// export const removeTrailingSearch = (str = '') => str.replace(/\?[\s\S]*$/, '')
29const addLeadingSlash = (url = '') => (url.charAt(0) === '/' ? url : '/' + url);
30const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path) || path === prefix;
31const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substring(prefix.length) : path;
32const stripSuffix = (path = '', suffix = '') => path.includes(suffix) ? path.substring(0, path.length - suffix.length) : path;
33
34function isAbsolute(pathname) {
35 return pathname.charAt(0) === '/';
36}
37
38// About 1.5x faster than the two-arg version of Array#splice()
39function spliceOne(list, index) {
40 for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) {
41 list[i] = list[k];
42 }
43
44 list.pop();
45}
46
47// This implementation is based heavily on node's url.parse
48function resolvePathname(to, from) {
49 if (from === undefined) from = '';
50
51 var toParts = (to && to.split('/')) || [];
52 var fromParts = (from && from.split('/')) || [];
53
54 var isToAbs = to && isAbsolute(to);
55 var isFromAbs = from && isAbsolute(from);
56 var mustEndAbs = isToAbs || isFromAbs;
57
58 if (to && isAbsolute(to)) {
59 // to is absolute
60 fromParts = toParts;
61 } else if (toParts.length) {
62 // to is relative, drop the filename
63 fromParts.pop();
64 fromParts = fromParts.concat(toParts);
65 }
66
67 if (!fromParts.length) return '/';
68
69 var hasTrailingSlash;
70 if (fromParts.length) {
71 var last = fromParts[fromParts.length - 1];
72 hasTrailingSlash = last === '.' || last === '..' || last === '';
73 } else {
74 hasTrailingSlash = false;
75 }
76
77 var up = 0;
78 for (var i = fromParts.length; i >= 0; i--) {
79 var part = fromParts[i];
80
81 if (part === '.') {
82 spliceOne(fromParts, i);
83 } else if (part === '..') {
84 spliceOne(fromParts, i);
85 up++;
86 } else if (up) {
87 spliceOne(fromParts, i);
88 up--;
89 }
90 }
91
92 if (!mustEndAbs) for (; up--; up) fromParts.unshift('..');
93
94 if (
95 mustEndAbs &&
96 fromParts[0] !== '' &&
97 (!fromParts[0] || !isAbsolute(fromParts[0]))
98 )
99 fromParts.unshift('');
100
101 var result = fromParts.join('/');
102
103 if (hasTrailingSlash && result.substr(-1) !== '/') result += '/';
104
105 return result;
106}
107
108const TabbarItem = ({ index, isSelected = false, textColor, iconPath, badgeText, showRedDot = false, text, onSelect }) => {
109 const className = classnames('weui-tabbar__item', {
110 'weui-bar__item_on': isSelected
111 });
112 const badgeStyle = {
113 position: 'absolute',
114 top: '-2px',
115 right: '-13px'
116 };
117 const dotStyle = {
118 position: 'absolute',
119 top: '0',
120 right: '-6px'
121 };
122 function onClick() {
123 onSelect(index);
124 }
125 return (h("a", { key: index, href: 'javascript:;', class: className, onClick: onClick },
126 h("span", { style: { display: 'inline-block', position: 'relative' } },
127 h("img", { src: iconPath, alt: '', class: 'weui-tabbar__icon' }),
128 !!badgeText && (h("span", { class: 'weui-badge taro-tabbar-badge', style: badgeStyle }, badgeText)),
129 showRedDot && (h("span", { class: 'weui-badge weui-badge_dot', style: dotStyle }))),
130 h("p", { class: 'weui-tabbar__label', style: { color: textColor } }, text)));
131};
132
133const indexCss = "html,body{height:100%}#app{height:100%}.taro-tabbar__border-white::before{border-top-color:#fff !important}.taro-tabbar__container{display:-ms-flexbox;display:flex;overflow:hidden;-ms-flex-direction:column;flex-direction:column;height:100%}.taro-tabbar__panel{overflow:auto;position:relative;-ms-flex:1;flex:1;-webkit-overflow-scrolling:auto}.taro-tabbar__tabbar{position:relative;width:100%;height:50px;-webkit-transition:bottom 0.2s, top 0.2s;transition:bottom 0.2s, top 0.2s}.taro-tabbar__tabbar-top{top:0}.taro-tabbar__tabbar-bottom{bottom:0;margin-bottom:constant(safe-area-inset-bottom);margin-bottom:env(safe-area-inset-bottom)}.taro-tabbar__tabbar-hide{display:none}.taro-tabbar__tabbar-slideout{top:-52px;-ms-flex:0 0;flex:0 0}.taro-tabbar__panel+.taro-tabbar__tabbar-slideout{top:auto;bottom:-52px}";
134
135const STATUS_SHOW = 0;
136const STATUS_HIDE = 1;
137const STATUS_SLIDEOUT = 2;
138const basicTabBarClassName = 'taro-tabbar__tabbar';
139const hideTabBarClassName = 'taro-tabbar__tabbar-hide';
140const hideTabBarWithAnimationClassName = 'taro-tabbar__tabbar-slideout';
141let Tabbar = class {
142 constructor(hostRef) {
143 registerInstance(this, hostRef);
144 this.onLongPress = createEvent(this, "longpress", 7);
145 this.homePage = '';
146 this.customRoutes = [];
147 this.tabbarPos = 'bottom';
148 this.selectedIndex = -1;
149 this.status = STATUS_SHOW;
150 this.getOriginUrl = (url) => {
151 const customRoute = this.customRoutes.filter(([, customUrl]) => {
152 const pathA = splitUrl(customUrl).path;
153 const pathB = splitUrl(url).path;
154 return pathA === pathB;
155 });
156 return stripSuffix(customRoute.length ? customRoute[0][0] : url, '.html');
157 };
158 this.getSelectedIndex = (url) => {
159 let foundIndex = -1;
160 this.list.forEach(({ pagePath }, idx) => {
161 const pathA = splitUrl(url).path;
162 const pathB = splitUrl(pagePath).path;
163 if (pathA === pathB) {
164 foundIndex = idx;
165 }
166 });
167 return foundIndex;
168 };
169 this.switchTab = (index) => {
170 this.selectedIndex = index;
171 Taro.switchTab({
172 url: this.list[index].pagePath
173 });
174 };
175 this.switchTabHandler = ({ url, successHandler, errorHandler }) => {
176 const currentUrl = this.getOriginUrl(this.getCurrentUrl() || this.homePage);
177 const nextTab = resolvePathname(url, currentUrl);
178 const foundIndex = this.getSelectedIndex(nextTab);
179 if (foundIndex > -1) {
180 this.switchTab(foundIndex);
181 successHandler({
182 errMsg: 'switchTab:ok'
183 });
184 }
185 else {
186 errorHandler({
187 errMsg: `switchTab:fail page "${nextTab}" is not found`
188 });
189 }
190 };
191 this.routerChangeHandler = (options) => {
192 var _a;
193 const to = (_a = options === null || options === void 0 ? void 0 : options.toLocation) === null || _a === void 0 ? void 0 : _a.path;
194 let currentPage;
195 if (typeof to === 'string') {
196 const routerBasename = this.conf.basename || '/';
197 currentPage = stripBasename(addLeadingSlash(to || this.homePage), routerBasename) || '/';
198 }
199 else {
200 currentPage = this.getCurrentUrl();
201 }
202 this.selectedIndex = this.getSelectedIndex(this.getOriginUrl(currentPage));
203 };
204 this.setTabBarBadgeHandler = ({ index, text, successHandler, errorHandler }) => {
205 const list = [...this.list];
206 if (index in list) {
207 list[index].showRedDot = false;
208 list[index].badgeText = text;
209 successHandler({
210 errMsg: 'setTabBarBadge:ok'
211 });
212 }
213 else {
214 errorHandler({
215 errMsg: 'setTabBarBadge:fail tabbar item not found'
216 });
217 }
218 this.list = list;
219 };
220 this.removeTabBarBadgeHandler = ({ index, successHandler, errorHandler }) => {
221 const list = [...this.list];
222 if (index in list) {
223 list[index].badgeText = null;
224 list[index].badgeText = null;
225 successHandler({
226 errMsg: 'removeTabBarBadge:ok'
227 });
228 }
229 else {
230 errorHandler({
231 errMsg: 'removeTabBarBadge:fail tabbar item not found'
232 });
233 }
234 this.list = list;
235 };
236 this.showTabBarRedDotHandler = ({ index, successHandler, errorHandler }) => {
237 const list = [...this.list];
238 if (index in list) {
239 list[index].badgeText = null;
240 list[index].showRedDot = true;
241 successHandler({
242 errMsg: 'showTabBarRedDot:ok'
243 });
244 }
245 else {
246 errorHandler({
247 errMsg: 'showTabBarRedDot:fail tabbar item not found'
248 });
249 }
250 this.list = list;
251 };
252 this.hideTabBarRedDotHandler = ({ index, successHandler, errorHandler }) => {
253 const list = [...this.list];
254 if (index in list) {
255 list[index].showRedDot = false;
256 successHandler({
257 errMsg: 'hideTabBarRedDot:ok'
258 });
259 }
260 else {
261 errorHandler({
262 errMsg: 'hideTabBarRedDot:fail tabbar item not found'
263 });
264 }
265 this.list = list;
266 };
267 this.showTabBarHandler = ({ successHandler }) => {
268 this.status = STATUS_SHOW;
269 successHandler({
270 errMsg: 'showTabBar:ok'
271 });
272 };
273 this.hideTabBarHandler = ({ animation, successHandler }) => {
274 this.status = animation ? STATUS_SLIDEOUT : STATUS_HIDE;
275 successHandler({
276 errMsg: 'hideTabBar:ok'
277 });
278 };
279 this.setTabBarStyleHandler = ({ color, selectedColor, backgroundColor, borderStyle, successHandler }) => {
280 if (backgroundColor)
281 this.backgroundColor = backgroundColor;
282 if (borderStyle)
283 this.borderStyle = borderStyle;
284 if (color)
285 this.color = color;
286 if (selectedColor)
287 this.selectedColor = selectedColor;
288 successHandler({
289 errMsg: 'setTabBarStyle:ok'
290 });
291 };
292 this.setTabBarItemHandler = ({ index, iconPath, selectedIconPath, text, successHandler, errorHandler }) => {
293 const list = [...this.list];
294 if (index in list) {
295 if (iconPath)
296 list[index].iconPath = iconPath;
297 if (selectedIconPath)
298 list[index].selectedIconPath = selectedIconPath;
299 if (text)
300 list[index].text = text;
301 successHandler({
302 errMsg: 'setTabBarItem:ok'
303 });
304 }
305 else {
306 errorHandler({
307 errMsg: 'setTabBarItem:fail tabbar item not found'
308 });
309 }
310 this.list = list;
311 };
312 const list = this.conf.list;
313 const customRoutes = this.conf.customRoutes;
314 if (Object.prototype.toString.call(list) !== '[object Array]' ||
315 list.length < 2 ||
316 list.length > 5) {
317 throw new Error('tabBar 配置错误');
318 }
319 this.homePage = addLeadingSlash(this.conf.homePage);
320 for (let key in customRoutes) {
321 const path = customRoutes[key];
322 key = addLeadingSlash(key);
323 if (typeof path === 'string') {
324 this.customRoutes.push([key, addLeadingSlash(path)]);
325 }
326 else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
327 this.customRoutes.push(...path.map(p => [key, addLeadingSlash(p)]));
328 }
329 }
330 list.forEach(item => {
331 if (item.pagePath.indexOf('/') !== 0) {
332 item.pagePath = '/' + item.pagePath;
333 }
334 });
335 this.list = list;
336 this.borderStyle = this.conf.borderStyle;
337 this.backgroundColor = this.conf.backgroundColor;
338 this.color = this.conf.color;
339 this.selectedColor = this.conf.selectedColor;
340 }
341 getCurrentUrl() {
342 const routerMode = this.conf.mode;
343 const routerBasename = this.conf.basename || '/';
344 let url;
345 if (routerMode === 'hash') {
346 const href = window.location.href;
347 const hashIndex = href.indexOf('#');
348 url = hashIndex === -1
349 ? ''
350 : href.substring(hashIndex + 1);
351 }
352 else {
353 url = location.pathname;
354 }
355 const processedUrl = addLeadingSlash(stripBasename(url, routerBasename));
356 return decodeURI(processedUrl === '/' ? this.homePage : processedUrl);
357 }
358 bindEvent() {
359 Taro.eventCenter.on('__taroRouterChange', this.routerChangeHandler);
360 Taro.eventCenter.on('__taroSwitchTab', this.switchTabHandler);
361 Taro.eventCenter.on('__taroSetTabBarBadge', this.setTabBarBadgeHandler);
362 Taro.eventCenter.on('__taroRemoveTabBarBadge', this.removeTabBarBadgeHandler);
363 Taro.eventCenter.on('__taroShowTabBarRedDotHandler', this.showTabBarRedDotHandler);
364 Taro.eventCenter.on('__taroHideTabBarRedDotHandler', this.hideTabBarRedDotHandler);
365 Taro.eventCenter.on('__taroShowTabBar', this.showTabBarHandler);
366 Taro.eventCenter.on('__taroHideTabBar', this.hideTabBarHandler);
367 Taro.eventCenter.on('__taroSetTabBarStyle', this.setTabBarStyleHandler);
368 Taro.eventCenter.on('__taroSetTabBarItem', this.setTabBarItemHandler);
369 }
370 removeEvent() {
371 Taro.eventCenter.off('__taroRouterChange', this.routerChangeHandler);
372 Taro.eventCenter.off('__taroSwitchTab', this.switchTabHandler);
373 Taro.eventCenter.off('__taroSetTabBarBadge', this.setTabBarBadgeHandler);
374 Taro.eventCenter.off('__taroRemoveTabBarBadge', this.removeTabBarBadgeHandler);
375 Taro.eventCenter.off('__taroShowTabBarRedDotHandler', this.showTabBarRedDotHandler);
376 Taro.eventCenter.off('__taroHideTabBarRedDotHandler', this.hideTabBarRedDotHandler);
377 Taro.eventCenter.off('__taroShowTabBar', this.showTabBarHandler);
378 Taro.eventCenter.off('__taroHideTabBar', this.hideTabBarHandler);
379 Taro.eventCenter.off('__taroSetTabBarStyle', this.setTabBarStyleHandler);
380 Taro.eventCenter.off('__taroSetTabBarItem', this.setTabBarItemHandler);
381 }
382 componentDidLoad() {
383 this.tabbarPos = this.tabbar.nextElementSibling ? 'top' : 'bottom';
384 this.bindEvent();
385 this.routerChangeHandler();
386 }
387 disconnectedCallback() {
388 this.removeEvent();
389 }
390 render() {
391 const { tabbarPos = 'bottom' } = this;
392 const status = this.status;
393 const containerCls = classnames('weui-tabbar', {
394 [`taro-tabbar__border-${this.borderStyle || 'black'}`]: true
395 });
396 const shouldHideTabBar = this.selectedIndex === -1 || status === STATUS_HIDE;
397 const shouldSlideout = status === STATUS_SLIDEOUT;
398 return (h(Host, { class: classnames(basicTabBarClassName, `${basicTabBarClassName}-${tabbarPos}`, {
399 [hideTabBarClassName]: shouldHideTabBar,
400 [hideTabBarWithAnimationClassName]: shouldSlideout
401 }) }, h("div", { class: containerCls, style: {
402 backgroundColor: this.backgroundColor || '',
403 height: 'inherit'
404 } }, this.list.map((item, index) => {
405 const isSelected = this.selectedIndex === index;
406 let textColor;
407 let iconPath;
408 if (isSelected) {
409 textColor = this.selectedColor || '';
410 iconPath = item.selectedIconPath;
411 }
412 else {
413 textColor = this.color || '';
414 iconPath = item.iconPath;
415 }
416 return (h(TabbarItem, { index: index, onSelect: this.switchTab.bind(this), isSelected: isSelected, textColor: textColor, iconPath: iconPath, text: item.text, badgeText: item.badgeText, showRedDot: item.showRedDot }));
417 }))));
418 }
419 get tabbar() { return getElement(this); }
420};
421Tabbar.style = indexCss;
422
423export { Tabbar as taro_tabbar };