Calendar/CalendarPopup/CalendarView 日历

注:

Import

import {
  TaCalendar,
  TaCalendarPopup,
  TaCalendarView
} from 'tantalum-ui-mobile-react'

具体的引入方式可以参考引入组件

Import Type

组件导出的类型定义:

import type {
  CalendarValueFormatter,
  CalendarValueParser,
  CalendarOnSelect,
  CalendarOnConfirm,
  CalendarDayHandler,
  CalendarMode,
  CalendarDetail,
  SelectorOnChange,
  SelectorModelValue,
  VisibleState,
  PopupOnVisibleStateChange,
  PopupOnCancel
} from 'tantalum-ui-mobile-react'

公共 Props

属性类型默认值必填说明
valueSelectorModelValue[]选中值
minDateDate当前日期可选最小值
maxDateDate当前日期的六个月后可选最大值
initialModeCalendarMode'single'模式
allowSameDaybooleanfalserange 模式生效,设置开始结束时间是否可以同一天
maxRangenumber | stringInfinityrange 模式生效,选择区间的最长天数
dayHandlerCalendarDayHandler日历每个日期处理函数
formatterCalendarValueFormatterparser 成对设置,对于 value 的值进行转化
parserCalendarValueParserformatter 成对设置,对于 value 的值进行反转化

Calendar 日历选择器

注:

  • 支持表单,具体可参考 Form
import {
  showToast,
  showCalendar,
  SelectorModelValue,
  TaGroup,
  TaCell,
  TaCalendar,
  SelectorDetail
} from '@/index'
import { formatter, parser } from './utils'
import dayjs from 'dayjs'

const minDate = dayjs().startOf('day').subtract(1, 'month').toDate()
const maxDate = dayjs().startOf('day').add(1, 'month').toDate()

const formatValue = (
  formatter(
    [dayjs().startOf('day').add(1, 'month').toDate()],
    'single'
  ) as SelectorDetail
).value
const disableValue = dayjs().startOf('day').add(1, 'month').toDate()

export default function ExpCalendar() {
  function onCallApi() {
    showCalendar({
      mode: 'range',
      showClose: true,
      success: res => {
        console.log('success', res)
        if (res.cancel) {
          showToast('取消了')
        } else {
          showToast(`选择了 ${res.detail.label}`)
        }
      }
    })
  }

  function onChange(res: SelectorModelValue) {
    console.log('change', res)

    showToast('change: ' + (res as any)[0])
  }

  return (
    <>
      <TaGroup title="initialMode=simple">
        <TaCell label="默认">
          <TaCalendar />
        </TaCell>
        <TaCell label="showConfirm=true">
          <TaCalendar showConfirm />
        </TaCell>
        <TaCell label="showClose=true">
          <TaCalendar showClose />
        </TaCell>
        <TaCell label="firstDayOfWeek=1">
          <TaCalendar firstDayOfWeek="1" />
        </TaCell>
        <TaCell label="minDate/maxDate +-1month">
          <TaCalendar minDate={minDate} maxDate={maxDate} />
        </TaCell>
        <TaCell label="formatter/parser">
          <TaCalendar
            formatter={formatter}
            parser={parser}
            value={formatValue}
          />
        </TaCell>
        <TaCell label="禁用">
          <TaCalendar disabled value={disableValue} />
        </TaCell>
      </TaGroup>
      <TaGroup title="initialMode=range">
        <TaCell label="默认">
          <TaCalendar initialMode="range" />
        </TaCell>
        <TaCell label="allowSameDay">
          <TaCalendar initialMode="range" allowSameDay />
        </TaCell>
        <TaCell label="maxRange=5">
          <TaCalendar initialMode="range" maxRange="5" />
        </TaCell>
      </TaGroup>
      <TaGroup title="事件监听">
        <TaCell label="change">
          <TaCalendar onChange={onChange} />
        </TaCell>
      </TaGroup>
      <TaGroup title="API">
        <TaCell label="showCalendar" isLink onClick={() => onCallApi()} />
      </TaGroup>
    </>
  )
}

Calendar Props

属性类型默认值必填说明
namestring标识
placeholderstring没有选中值的提示,也会用在弹窗标题上
disabledbooleanfalse是否禁用
showConfirmbooleanfalse弹窗是否展示确定按钮
showClosebooleanfalse弹窗是否展示关闭按钮

Calendar Events

事件描述回调函数参数函数 TypeScript
onChange选择后值发生改变时触发payload: SelectorModelValueSelectorOnChange

CalendarPopup 日历选择弹窗

import {
  showToast,
  SelectorModelValue,
  PopupOnVisibleStateChange,
  PopupOnCancel,
  TaCell,
  TaGroup,
  TaNoticeBar,
  TaCalendar,
  CalendarOnConfirm
} from '@/index'
import dayjs from 'dayjs'
import { formatter, parser, template } from '../Calendar/utils'
import { useRef, useState } from 'react'

interface showArgs {
  showConfirm?: boolean
  showClose?: boolean
  visibleEvent?: boolean
  changeEvent?: boolean
  clickEvent?: boolean
}

const title = 'CalendarPopup'
const defaultValue = dayjs().format(template)

export default function ExpCalendarPopup() {
  const [popupValue, setPopupValue] = useState(defaultValue)
  const [popupRangeValue, setPopupRangeValue] = useState<SelectorModelValue>([])
  const [visible, setVisible] = useState(false)
  const [rangeVisible, setRangeVisible] = useState(false)
  const [showConfirm, setShowConfirm] = useState(false)
  const [showClose, setShowClose] = useState(false)
  const clickEvent = useRef(false)
  const changeEvent = useRef(false)
  const visibleEvent = useRef(false)

  function addOneDay() {
    setPopupValue(
      dayjs(popupValue, template, true).add(1, 'day').format(template)
    )
  }

  function onShow(args: showArgs = {}) {
    setShowConfirm(!!args.showConfirm)
    setShowClose(!!args.showClose)

    visibleEvent.current = !!args.visibleEvent
    changeEvent.current = !!args.changeEvent
    clickEvent.current = !!args.clickEvent

    setVisible(true)
  }

  const onVisibleStateChange: PopupOnVisibleStateChange = res => {
    if (visibleEvent.current) {
      console.log('onVisibleStateChange', res)
      showToast(`${res.state} 事件触发`)
    }
  }

  const onConfirm: CalendarOnConfirm = res => {
    if (clickEvent.current) {
      console.log('onConfirm', res)
      showToast(`点击确定按钮`)
    }
  }

  const onCancel: PopupOnCancel = res => {
    if (clickEvent.current) {
      console.log('onCancel', res)

      if (res.source === 'cancelClick') {
        showToast('点击了取消按钮')
      } else if (res.source === 'maskClick') {
        showToast('点击了蒙层')
      }
    }
  }

  function onChange(res: SelectorModelValue) {
    console.log('onChange', res)
    if (changeEvent.current) {
      showToast(`值改为 ${res}`)
    }

    setPopupValue(res as string)
  }

  function onRangeChange(res: SelectorModelValue) {
    console.log('onChange', res)

    setPopupRangeValue(res)
  }

  return (
    <>
      <TaNoticeBar
        className="top-notice-bar"
        title="基础展示参数可以参考 Calendar"
      />
      <TaGroup title="基础用法">
        <TaCell label="默认" onClick={() => onShow({})}>
          {popupValue}
        </TaCell>
        <TaCell label="+1day" isLink onClick={() => addOneDay()}>
          click
        </TaCell>
        <TaCell
          label="showConfirm=true"
          isLink
          onClick={() => onShow({ showConfirm: true })}
        />
        <TaCell
          label="initialMode=range"
          isLink
          onClick={() => setRangeVisible(true)}
        ></TaCell>
      </TaGroup>
      <TaGroup title="事件监听">
        <TaCell
          label="onChange"
          isLink
          onClick={() => onShow({ changeEvent: true })}
        />
        <TaCell
          label="onConfirm/onCancel"
          isLink
          onClick={() => onShow({ clickEvent: true })}
        />
        <TaCell
          label="onVisibleStateChange"
          isLink
          onClick={() => onShow({ visibleEvent: true })}
        />
      </TaGroup>
      <TaCalendar.Popup
        title={title}
        showConfirm={showConfirm}
        showClose={showClose}
        formatter={formatter}
        parser={parser}
        visible={visible}
        onUpdateVisible={v => setVisible(v)}
        value={popupValue}
        onChange={onChange}
        onConfirm={onConfirm}
        onCancel={onCancel}
        onVisibleStateChange={onVisibleStateChange}
      />
      <TaCalendar.Popup
        title={title}
        initialMode="range"
        visible={rangeVisible}
        onUpdateVisible={v => setRangeVisible(v)}
        value={popupRangeValue}
        onChange={onRangeChange}
      />
    </>
  )
}

CalendarPopup Props

属性类型默认值必填说明
visiblebooleanfalse是否显示
titlestring弹窗标题
showConfirmbooleanfalse选择时是否展示确定按钮
showClosebooleanfalse是否展示关闭按钮

CalendarPopup Events

事件描述回调函数参数函数 TypeScript
onConfirm选择完毕后触发 / showConfirm 点击确定按钮后触发payload: CalendarDetailCalendarOnConfirm
onCancel点击蒙层关闭后触发PopupOnCancel
onChange选择后值发生改变时触发payload: SelectorModelValueSelectorOnChange
onVisibleStateChange展示隐藏时触发payload: { state: VisibleState }PopupOnVisibleStateChange
onUpdateVisible展示隐藏时触发visible: boolean 是否显示

VisibleState 值说明

说明备注
show展示时触发
shown展示且动画结束后触发
hide隐藏时触发可能携带其他参数 cancel, maskClick, closeClick 等
hidden隐藏且动画结束后触发可能携带其他参数 cancel, maskClick, closeClick 等

CalendarView 日历选择面板

import {
  TaCalendar,
  TaNoticeBar,
  TaCell,
  TaGroup,
  CalendarOnSelect,
  showToast
} from '@/index'
import { useState } from 'react'
import { formatter, parser } from '../Calendar/utils'

export default function ExpCalendarView() {
  const [viewValue, setViewValue] = useState('')
  const [viewRangeValue, setViewRangeValue] = useState('')

  const onSelect: CalendarOnSelect = res => {
    console.log('select', res)

    showToast(`选择:${res.label}`)
  }

  return (
    <>
      <TaNoticeBar
        className="top-notice-bar"
        title="基础展示参数可以参考 Calendar"
      />
      <TaGroup title="initialMode=single">
        <TaCell label="value:"> {viewValue} </TaCell>
        <TaCalendar.View
          value={viewValue}
          onChange={v => setViewValue(v as string)}
          formatter={formatter}
          parser={parser}
        />
      </TaGroup>
      <TaGroup title="initialMode=range">
        <TaCell label="value:"> {viewRangeValue} </TaCell>
        <TaCalendar.View
          initialMode="range"
          value={viewRangeValue}
          onChange={v => setViewRangeValue(v as string)}
          formatter={formatter}
          parser={parser}
        />
      </TaGroup>
      <TaGroup title="select 事件">
        <TaCalendar.View onSelect={onSelect} />
      </TaGroup>
    </>
  )
}

CalendarView Events

事件描述回调函数参数函数 TypeScript
onSelect选择后触发payload: CalendarDetailCalendarOnSelect
onChange选择后值发生改变时触发payload: SelectorModelValueSelectorOnChange

showCalendar(object) 显示日历选择弹窗

object

属性类型默认值必填说明
modeCalendarMode'single'模式
titlestring弹窗标题
valueDate/Date[][]默认选择值,range 模式下需要提供两个
minDateDate当前日期可选最小值
maxDateDate当前日期的六个月后可选最大值
allowSameDaybooleanfalserange 模式生效,设置开始结束时间是否可以同一天
maxRangenumberInfinityrange 模式生效,选择区间的最长天数
dayHandlerCalendarDayHandler日历每个日期处理函数
success(payload: SuccessPayload) => void接口调用成功(在用户做出选择后,如取消,选择选项)的回调函数
fail(e: Error) => void接口调用失败(如传入错误的参数)的回调函数(不传入 fail 遇错误直接抛出)
complete() => void弹窗关闭或调用失败的回调函数

SuccessPayload

属性类型说明
confirm?boolean为 true 时,表示点击了确定,此时返回 detail
cancel?boolean为 true 时,表示取消
detail?CalendarDetail

Usage

具体调用方式可以参考API 调用

showCalendar({
  type: 'range',
  showClose: true,
  success: ({ confirm, cancel, detail }) => {
    ...
  }
})

类型释义

SelectorValue

type SelectorValue = string | number | Date

SelectorModelValue

type SelectorModelValue = SelectorValue | SelectorValue[]

注:在不自定义 formatter/parser 的情况下,value 只有 Date[] 这种情况。

CalendarDetail

interface CalendarDetail {
  label: string
  value: Date[]
  valueArray: number[][]
  rangeCount: number
}
字段说明
label选中值对应的描述文本,如果设置了 formatter,则返回格式后文本
value选择的值,range 模式下有开始 Date 和结束 Date 两个实例,不受 formatter 影响
valueArray如:[[2021, 5, 1]] 或 [[2021, 5, 1], [2021, 5, 30]]
rangeCount选择区间持续的天数(含首尾)

CalendarMode

type CalendarMode = 'single' | 'range'
说明
single选择一天
range选择一个日期区间

CalendarValueFormatter

interface CalendarValueFormatter {
  (valueArray: Date[], mode: CalendarMode):
    | { value: SelectorModelValue; label: string }
    | SelectorModelValue
}

将 value 的原始值转为需要的自定义值,值需要满足 SelectorModelValue 的类型约束,可以返回 { value, label } 对两个数据进行修改,或者单独返回 value。

CalendarValueParser

interface CalendarValueParser {
  (value: unknown, mode: CalendarMode): Date[]
}

CalendarValueFormatter 相反,将自定义 value 的值转为组件认识的原始数组。

CalendarDayHandler

type CalendarDayHandler = dayHandler(dayInfo: DayInfo) => DayInfo

interface DayInfo {
  topHighlight?: boolean
  topText?: string
  state: string
  bottomHighlight?: boolean
  bottomText?: string
  text: string
  dateString: string
  date?: Date
  timestamp: number
}

日历中的每个日期都对应一个 DayInfo 对象,通过 day-handler 属性可以修改 DayInfo 对象的内容后返回。

类型说明
dateDate日期对应的 Date 对象,该字段修改无效
statestring日期当前的状态,有:selected 选中,startSelected 开始(initialMode="range"下),endSelected 结束(initialMode="range"下),disabled 禁用。在空字符串的情况下,可以设置为 disabled 强制设置该日期为禁用(一般在票卖完的情况下设置)
textstring日期文本,不建议修改
topTextstring日期上方展示文本,一般可修改为“节日名称”、“今天”、“明天”、“开始”、“结束”等
topHighlightboolean日期上方展示文本是否高亮
bottomTextstring日期下方展示文本,一般可修改为“机票价格”、“酒店价格”、“特价”、“热门”等
bottomHighlightboolean日期下方展示文本是否高亮
dateStringstring日期对应的格式化时间(YYYY-MM-DD),如:2020-11-11,该字段不影响展示