123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import { withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
- import { ref, watch, reactive, defineComponent } from "vue";
- import { isDef, createNamespace, makeNumericProp } from "../utils/index.mjs";
- import { raf, useRect, doubleRaf, useEventListener, onMountedOrActivated } from "@vant/use";
- import { useExpose } from "../composables/use-expose.mjs";
- import { onPopupReopen } from "../composables/on-popup-reopen.mjs";
- import { Icon } from "../icon/index.mjs";
- const [name, bem] = createNamespace("notice-bar");
- const noticeBarProps = {
- text: String,
- mode: String,
- color: String,
- delay: makeNumericProp(1),
- speed: makeNumericProp(60),
- leftIcon: String,
- wrapable: Boolean,
- background: String,
- scrollable: {
- type: Boolean,
- default: null
- }
- };
- var stdin_default = defineComponent({
- name,
- props: noticeBarProps,
- emits: ["close", "replay"],
- setup(props, {
- emit,
- slots
- }) {
- let wrapWidth = 0;
- let contentWidth = 0;
- let startTimer;
- const wrapRef = ref();
- const contentRef = ref();
- const state = reactive({
- show: true,
- offset: 0,
- duration: 0
- });
- const renderLeftIcon = () => {
- if (slots["left-icon"]) {
- return slots["left-icon"]();
- }
- if (props.leftIcon) {
- return _createVNode(Icon, {
- "class": bem("left-icon"),
- "name": props.leftIcon
- }, null);
- }
- };
- const getRightIconName = () => {
- if (props.mode === "closeable") {
- return "cross";
- }
- if (props.mode === "link") {
- return "arrow";
- }
- };
- const onClickRightIcon = (event) => {
- if (props.mode === "closeable") {
- state.show = false;
- emit("close", event);
- }
- };
- const renderRightIcon = () => {
- if (slots["right-icon"]) {
- return slots["right-icon"]();
- }
- const name2 = getRightIconName();
- if (name2) {
- return _createVNode(Icon, {
- "name": name2,
- "class": bem("right-icon"),
- "onClick": onClickRightIcon
- }, null);
- }
- };
- const onTransitionEnd = () => {
- state.offset = wrapWidth;
- state.duration = 0;
- raf(() => {
- doubleRaf(() => {
- state.offset = -contentWidth;
- state.duration = (contentWidth + wrapWidth) / +props.speed;
- emit("replay");
- });
- });
- };
- const renderMarquee = () => {
- const ellipsis = props.scrollable === false && !props.wrapable;
- const style = {
- transform: state.offset ? `translateX(${state.offset}px)` : "",
- transitionDuration: `${state.duration}s`
- };
- return _createVNode("div", {
- "ref": wrapRef,
- "role": "marquee",
- "class": bem("wrap")
- }, [_createVNode("div", {
- "ref": contentRef,
- "style": style,
- "class": [bem("content"), {
- "van-ellipsis": ellipsis
- }],
- "onTransitionend": onTransitionEnd
- }, [slots.default ? slots.default() : props.text])]);
- };
- const reset = () => {
- const {
- delay,
- speed,
- scrollable
- } = props;
- const ms = isDef(delay) ? +delay * 1e3 : 0;
- wrapWidth = 0;
- contentWidth = 0;
- state.offset = 0;
- state.duration = 0;
- clearTimeout(startTimer);
- startTimer = setTimeout(() => {
- if (!wrapRef.value || !contentRef.value || scrollable === false) {
- return;
- }
- const wrapRefWidth = useRect(wrapRef).width;
- const contentRefWidth = useRect(contentRef).width;
- if (scrollable || contentRefWidth > wrapRefWidth) {
- doubleRaf(() => {
- wrapWidth = wrapRefWidth;
- contentWidth = contentRefWidth;
- state.offset = -contentWidth;
- state.duration = contentWidth / +speed;
- });
- }
- }, ms);
- };
- onPopupReopen(reset);
- onMountedOrActivated(reset);
- useEventListener("pageshow", reset);
- useExpose({
- reset
- });
- watch(() => [props.text, props.scrollable], reset);
- return () => {
- const {
- color,
- wrapable,
- background
- } = props;
- return _withDirectives(_createVNode("div", {
- "role": "alert",
- "class": bem({
- wrapable
- }),
- "style": {
- color,
- background
- }
- }, [renderLeftIcon(), renderMarquee(), renderRightIcon()]), [[_vShow, state.show]]);
- };
- }
- });
- export {
- stdin_default as default
- };
|