guide.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  2. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  3. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  4. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  5. return c > 3 && r && Object.defineProperty(target, key, r), r;
  6. };
  7. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  8. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  9. return new (P || (P = Promise))(function (resolve, reject) {
  10. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  11. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  12. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  13. step((generator = generator.apply(thisArg, _arguments || [])).next());
  14. });
  15. };
  16. import isFunction from 'lodash/isFunction';
  17. import { SuperComponent, wxComponent } from '../common/src/index';
  18. import props from './props';
  19. import config from '../common/config';
  20. import { systemInfo, debounce, getRect, isNumber, rpx2px, styles, unitConvert, nextTick } from '../common/utils';
  21. const { prefix } = config;
  22. const name = `${prefix}-guide`;
  23. let Guide = class Guide extends SuperComponent {
  24. constructor() {
  25. super(...arguments);
  26. this.externalClasses = [
  27. `${prefix}-class`,
  28. `${prefix}-class-reference`,
  29. `${prefix}-class-popover`,
  30. `${prefix}-class-tooltip`,
  31. `${prefix}-class-title`,
  32. `${prefix}-class-body`,
  33. `${prefix}-class-footer`,
  34. `${prefix}-class-skip`,
  35. `${prefix}-class-next`,
  36. `${prefix}-class-back`,
  37. `${prefix}-class-finish`,
  38. ];
  39. this.properties = props;
  40. this.options = {
  41. pureDataPattern: /^_/,
  42. multipleSlots: true,
  43. };
  44. this.data = {
  45. prefix,
  46. classPrefix: name,
  47. visible: false,
  48. _current: -1,
  49. _steps: [],
  50. buttonProps: {},
  51. referenceStyle: '',
  52. popoverStyle: '',
  53. title: '',
  54. body: '',
  55. nonOverlay: false,
  56. modeType: '',
  57. };
  58. this.controlledProps = [
  59. {
  60. key: 'current',
  61. event: 'change',
  62. },
  63. ];
  64. this.observers = {
  65. 'steps, current, showOverlay'() {
  66. return __awaiter(this, void 0, void 0, function* () {
  67. this._init();
  68. });
  69. },
  70. };
  71. this.lifetimes = {
  72. created() {
  73. this._init = debounce(() => this.init(), 20);
  74. this._getPlacement = this.getPlacement();
  75. },
  76. attached() {
  77. this._init();
  78. },
  79. };
  80. this.methods = {
  81. init() {
  82. var _a, _b, _c, _d, _e, _f, _g;
  83. return __awaiter(this, void 0, void 0, function* () {
  84. const { steps, current } = this.properties;
  85. const { _steps, _current } = this.data;
  86. const step = steps[current];
  87. if (!step) {
  88. return this.setData({ visible: false });
  89. }
  90. const modeType = ((_a = step.mode) !== null && _a !== void 0 ? _a : this.data.mode) === 'dialog' ? 'dialog' : 'popover';
  91. const showOverlay = (_b = step.showOverlay) !== null && _b !== void 0 ? _b : this.data.showOverlay;
  92. this.setData({ nonOverlay: !showOverlay, modeType });
  93. if (steps === _steps && current === _current)
  94. return;
  95. if (modeType === 'popover') {
  96. const rect = yield step.element();
  97. if (!rect)
  98. return;
  99. const highlightPadding = rpx2px((_c = step.highlightPadding) !== null && _c !== void 0 ? _c : this.data.highlightPadding);
  100. const referenceTop = rect.top - highlightPadding;
  101. const referenceRight = systemInfo.windowWidth - rect.right - highlightPadding;
  102. const referenceBottom = systemInfo.windowHeight - rect.bottom - highlightPadding;
  103. const referenceLeft = rect.left - highlightPadding;
  104. const style = {
  105. top: `${referenceTop}px`,
  106. right: `${referenceRight}px`,
  107. bottom: `${referenceBottom}px`,
  108. left: `${referenceLeft}px`,
  109. };
  110. this.setData({
  111. _steps: this.data.steps,
  112. _current: this.data.current,
  113. visible: true,
  114. referenceStyle: styles(style),
  115. title: (_d = step.title) !== null && _d !== void 0 ? _d : '',
  116. body: (_e = step.body) !== null && _e !== void 0 ? _e : '',
  117. buttonProps: this.buttonProps(step, 'popover'),
  118. });
  119. const popoverStyle = yield this.placementOffset(step, style);
  120. this.setData({ popoverStyle });
  121. }
  122. else {
  123. this.setData({
  124. _steps: this.data.steps,
  125. _current: this.data.current,
  126. visible: true,
  127. title: (_f = step.title) !== null && _f !== void 0 ? _f : '',
  128. body: (_g = step.body) !== null && _g !== void 0 ? _g : '',
  129. buttonProps: this.buttonProps(step, 'dialog'),
  130. });
  131. }
  132. });
  133. },
  134. placementOffset({ placement, offset }, place) {
  135. var _a, _b;
  136. return __awaiter(this, void 0, void 0, function* () {
  137. yield nextTick();
  138. const rect = yield getRect(this, `.${name}__container`);
  139. const style = (_b = (_a = this._getPlacement)[placement]) === null || _b === void 0 ? void 0 : _b.call(_a, rect, place, offset);
  140. return styles(Object.assign({ position: 'absolute' }, style));
  141. });
  142. },
  143. buttonProps(step, mode) {
  144. var _a, _b, _c, _d;
  145. let skipButton = (_a = step.skipButtonProps) !== null && _a !== void 0 ? _a : this.data.skipButtonProps;
  146. const size = mode === 'popover' ? 'extra-small' : 'medium';
  147. skipButton = Object.assign(Object.assign({ theme: 'light', content: '跳过', size }, skipButton), { tClass: `${prefix}-class-skip ${name}__button ${(skipButton === null || skipButton === void 0 ? void 0 : skipButton.class) || ''}`, type: 'skip' });
  148. let nextButton = (_b = step.nextButtonProps) !== null && _b !== void 0 ? _b : this.data.nextButtonProps;
  149. nextButton = Object.assign(Object.assign({ theme: 'primary', content: '下一步', size }, nextButton), { tClass: `${prefix}-class-next ${name}__button ${(nextButton === null || nextButton === void 0 ? void 0 : nextButton.class) || ''}`, type: 'next' });
  150. nextButton = Object.assign(Object.assign({}, nextButton), { content: this.buttonContent(nextButton) });
  151. let backButton = (_c = step.backButtonProps) !== null && _c !== void 0 ? _c : this.data.backButtonProps;
  152. backButton = Object.assign(Object.assign({ theme: 'light', content: '返回', size }, backButton), { tClass: `${prefix}-class-back ${name}__button ${(backButton === null || backButton === void 0 ? void 0 : backButton.class) || ''}`, type: 'back' });
  153. let finishButton = (_d = step.finishButtonProps) !== null && _d !== void 0 ? _d : this.data.finishButtonProps;
  154. finishButton = Object.assign(Object.assign({ theme: 'primary', content: '完成', size }, finishButton), { tClass: `${prefix}-class-finish ${name}__button ${(finishButton === null || finishButton === void 0 ? void 0 : finishButton.class) || ''}`, type: 'finish' });
  155. finishButton = Object.assign(Object.assign({}, finishButton), { content: this.buttonContent(finishButton) });
  156. return {
  157. skipButton,
  158. nextButton,
  159. backButton,
  160. finishButton,
  161. };
  162. },
  163. renderCounter() {
  164. const { steps, current, counter } = this.data;
  165. const stepsTotal = steps.length;
  166. const innerCurrent = current + 1;
  167. const popupSlotCounter = isFunction(counter) ? counter({ total: stepsTotal, current: innerCurrent }) : counter;
  168. return counter ? popupSlotCounter : `(${innerCurrent}/${stepsTotal})`;
  169. },
  170. buttonContent(button) {
  171. const { hideCounter } = this.data;
  172. return `${button.content.replace(/ \(.*?\)/, '')} ${hideCounter ? '' : this.renderCounter()}`;
  173. },
  174. onTplButtonTap(e) {
  175. const { type } = e.target.dataset;
  176. const parmas = { e, current: this.data.current, total: this.data.steps.length };
  177. switch (type) {
  178. case 'next':
  179. this.triggerEvent('next-step-click', Object.assign({ next: this.data.current + 1 }, parmas));
  180. this.setData({ current: this.data.current + 1 });
  181. break;
  182. case 'skip':
  183. this.triggerEvent('skip', parmas);
  184. this.setData({ current: -1 });
  185. break;
  186. case 'back':
  187. this.triggerEvent('back', parmas);
  188. this.setData({ current: 0 });
  189. break;
  190. case 'finish':
  191. this.triggerEvent('finish', parmas);
  192. this.setData({ current: -1 });
  193. break;
  194. default:
  195. break;
  196. }
  197. this.triggerEvent('change', { current: this.data.current });
  198. },
  199. getPlacement() {
  200. const space = rpx2px(32);
  201. const offsetLeft = (offset) => unitConvert(isNumber(offset === null || offset === void 0 ? void 0 : offset[0]) ? `${offset === null || offset === void 0 ? void 0 : offset[0]}rpx` : (offset === null || offset === void 0 ? void 0 : offset[0]) || 0);
  202. const offsetTop = (offset) => unitConvert(isNumber(offset === null || offset === void 0 ? void 0 : offset[1]) ? `${offset === null || offset === void 0 ? void 0 : offset[1]}rpx` : (offset === null || offset === void 0 ? void 0 : offset[1]) || 0);
  203. const bottom = (place) => parseFloat(place.bottom);
  204. const left = (place) => parseFloat(place.left);
  205. const right = (place) => parseFloat(place.right);
  206. const top = (place) => parseFloat(place.top);
  207. const height = (place) => systemInfo.windowHeight - bottom(place) - top(place);
  208. const width = (place) => systemInfo.windowWidth - left(place) - right(place);
  209. return {
  210. center: (rect, place, offset) => ({
  211. top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
  212. left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
  213. }),
  214. bottom: (rect, place, offset) => ({
  215. top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
  216. left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
  217. }),
  218. 'bottom-left': (rect, place, offset) => ({
  219. top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
  220. left: `${Math.max(left(place) + offsetLeft(offset), 1)}px`,
  221. }),
  222. 'bottom-right': (rect, place, offset) => ({
  223. top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
  224. right: `${Math.max(right(place) - offsetLeft(offset), 1)}px`,
  225. }),
  226. left: (rect, place, offset) => ({
  227. top: `${Math.max(height(place) / 2 + top(place) - rect.height / 2 + offsetTop(offset), 1)}px`,
  228. right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
  229. }),
  230. 'left-top': (rect, place, offset) => ({
  231. top: `${Math.max(top(place) + offsetTop(offset), 1)}px`,
  232. right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
  233. }),
  234. 'left-bottom': (rect, place, offset) => ({
  235. bottom: `${Math.max(bottom(place) - offsetTop(offset), 1)}px`,
  236. right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
  237. }),
  238. right: (rect, place, offset) => ({
  239. top: `${Math.max(height(place) / 2 + top(place) - rect.height / 2 + offsetTop(offset), 1)}px`,
  240. left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
  241. }),
  242. 'right-top': (rect, place, offset) => ({
  243. top: `${Math.max(top(place) + offsetTop(offset), 1)}px`,
  244. left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
  245. }),
  246. 'right-bottom': (rect, place, offset) => ({
  247. bottom: `${Math.max(bottom(place) - offsetTop(offset), 1)}px`,
  248. left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
  249. }),
  250. top: (rect, place, offset) => ({
  251. bottom: `${Math.max(height(place) + bottom(place) + space - offsetTop(offset), 1)}px`,
  252. left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
  253. }),
  254. 'top-left': (rect, place, offset) => ({
  255. bottom: `${Math.max(height(place) + bottom(place) + space - offsetTop(offset), 1)}px`,
  256. left: `${Math.max(left(place) + offsetLeft(offset), 1)}px`,
  257. }),
  258. 'top-right': (rect, place, offset) => ({
  259. bottom: `${Math.max(height(place) + bottom(place) + space - offsetTop(offset), 1)}px`,
  260. right: `${Math.max(right(place) - offsetLeft(offset), 1)}px`,
  261. }),
  262. };
  263. },
  264. };
  265. }
  266. };
  267. Guide = __decorate([
  268. wxComponent()
  269. ], Guide);
  270. export default Guide;