1 | import { Component, Prop, Vue } from 'vue-property-decorator'
|
2 | import { Value, Styles, Position, TooltipProp, TooltipFormatter } from './typings'
|
3 |
|
4 | import './styles/dot.scss'
|
5 |
|
6 | @Component({ name: 'VueSliderDot' })
|
7 | export default class VueSliderDot extends Vue {
|
8 | $refs!: {
|
9 | dot: HTMLDivElement
|
10 | }
|
11 |
|
12 | @Prop({ default: 0 })
|
13 | value!: Value
|
14 |
|
15 | @Prop() tooltip!: TooltipProp
|
16 |
|
17 | @Prop() dotStyle?: Styles
|
18 |
|
19 | @Prop() tooltipStyle?: Styles
|
20 |
|
21 | @Prop({
|
22 | type: String,
|
23 | validator: (val: string) => ['top', 'right', 'bottom', 'left'].indexOf(val) > -1,
|
24 | required: true,
|
25 | })
|
26 | tooltipPlacement!: Position
|
27 |
|
28 | @Prop({ type: [String, Function] })
|
29 | tooltipFormatter?: TooltipFormatter
|
30 |
|
31 | @Prop({ type: Boolean, default: false })
|
32 | focus!: boolean
|
33 |
|
34 | @Prop({ default: false })
|
35 | disabled!: boolean
|
36 |
|
37 | get dotClasses() {
|
38 | return [
|
39 | 'vue-slider-dot',
|
40 | {
|
41 | 'vue-slider-dot-hover': this.tooltip === 'hover' || this.tooltip === 'active',
|
42 | 'vue-slider-dot-disabled': this.disabled,
|
43 | 'vue-slider-dot-focus': this.focus,
|
44 | },
|
45 | ]
|
46 | }
|
47 |
|
48 | get handleClasses() {
|
49 | return [
|
50 | 'vue-slider-dot-handle',
|
51 | {
|
52 | 'vue-slider-dot-handle-disabled': this.disabled,
|
53 | 'vue-slider-dot-handle-focus': this.focus,
|
54 | },
|
55 | ]
|
56 | }
|
57 |
|
58 | get tooltipClasses() {
|
59 | return [
|
60 | 'vue-slider-dot-tooltip',
|
61 | [`vue-slider-dot-tooltip-${this.tooltipPlacement}`],
|
62 | {
|
63 | 'vue-slider-dot-tooltip-show': this.showTooltip,
|
64 | },
|
65 | ]
|
66 | }
|
67 |
|
68 | get tooltipInnerClasses() {
|
69 | return [
|
70 | 'vue-slider-dot-tooltip-inner',
|
71 | [`vue-slider-dot-tooltip-inner-${this.tooltipPlacement}`],
|
72 | {
|
73 | 'vue-slider-dot-tooltip-inner-disabled': this.disabled,
|
74 | 'vue-slider-dot-tooltip-inner-focus': this.focus,
|
75 | },
|
76 | ]
|
77 | }
|
78 |
|
79 | get showTooltip(): boolean {
|
80 | switch (this.tooltip) {
|
81 | case 'always':
|
82 | return true
|
83 | case 'none':
|
84 | return false
|
85 | case 'focus':
|
86 | case 'active':
|
87 | return !!this.focus
|
88 | default:
|
89 | return false
|
90 | }
|
91 | }
|
92 |
|
93 | get tooltipValue(): Value {
|
94 | if (this.tooltipFormatter) {
|
95 | return typeof this.tooltipFormatter === 'string'
|
96 | ? this.tooltipFormatter.replace(/\{value\}/, String(this.value))
|
97 | : this.tooltipFormatter(this.value)
|
98 | } else {
|
99 | return this.value
|
100 | }
|
101 | }
|
102 |
|
103 | dragStart(e: MouseEvent | TouchEvent) {
|
104 | if (this.disabled) {
|
105 | return false
|
106 | }
|
107 |
|
108 | this.$emit('drag-start')
|
109 | }
|
110 |
|
111 | render() {
|
112 | return (
|
113 | <div
|
114 | ref="dot"
|
115 | class={this.dotClasses}
|
116 | aria-valuetext={
|
117 | typeof this.tooltipValue === 'number' ? this.tooltipValue.toString() : this.tooltipValue
|
118 | }
|
119 | onMousedown={this.dragStart}
|
120 | onTouchstart={this.dragStart}
|
121 | >
|
122 | {this.$slots.dot || <div class={this.handleClasses} style={this.dotStyle} />}
|
123 | {this.tooltip !== 'none' ? (
|
124 | <div class={this.tooltipClasses}>
|
125 | {this.$slots.tooltip || (
|
126 | <div class={this.tooltipInnerClasses} style={this.tooltipStyle}>
|
127 | <span class={'vue-slider-dot-tooltip-text'}>{this.tooltipValue}</span>
|
128 | </div>
|
129 | )}
|
130 | </div>
|
131 | ) : null}
|
132 | </div>
|
133 | )
|
134 | }
|
135 | }
|