@zkwq/business 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/dist/index.css +1 -0
  2. package/dist/index.js +21861 -0
  3. package/dist/index.umd.cjs +46 -0
  4. package/package.json +27 -0
  5. package/src/components/base/ui/alert/Alert.vue +94 -0
  6. package/src/components/base/ui/autocomplete/autocomplete-suggestions.vue +77 -0
  7. package/src/components/base/ui/autocomplete/autocomplete.vue +305 -0
  8. package/src/components/base/ui/backtop/main.vue +112 -0
  9. package/src/components/base/ui/button/Button.vue +84 -0
  10. package/src/components/base/ui/button/ButtonGroup.vue +10 -0
  11. package/src/components/base/ui/carousel/Carousel.vue +304 -0
  12. package/src/components/base/ui/carousel/CarouselItem.vue +137 -0
  13. package/src/components/base/ui/cascader/cascader.vue +650 -0
  14. package/src/components/base/ui/cascader-panel/cascader-menu.vue +138 -0
  15. package/src/components/base/ui/cascader-panel/cascader-node.vue +246 -0
  16. package/src/components/base/ui/cascader-panel/cascader-panel.vue +382 -0
  17. package/src/components/base/ui/cascader-panel/node.js +166 -0
  18. package/src/components/base/ui/cascader-panel/store.js +62 -0
  19. package/src/components/base/ui/checkbox/checkbox-button.vue +199 -0
  20. package/src/components/base/ui/checkbox/checkbox-group.vue +48 -0
  21. package/src/components/base/ui/checkbox/checkbox.vue +222 -0
  22. package/src/components/base/ui/col/col.js +71 -0
  23. package/src/components/base/ui/collapse/collapse-item.vue +180 -0
  24. package/src/components/base/ui/collapse/collapse.vue +73 -0
  25. package/src/components/base/ui/color-picker/color.js +317 -0
  26. package/src/components/base/ui/color-picker/components/alpha-slider.vue +132 -0
  27. package/src/components/base/ui/color-picker/components/hue-slider.vue +123 -0
  28. package/src/components/base/ui/color-picker/components/picker-dropdown.vue +119 -0
  29. package/src/components/base/ui/color-picker/components/predefine.vue +61 -0
  30. package/src/components/base/ui/color-picker/components/sv-panel.vue +100 -0
  31. package/src/components/base/ui/color-picker/draggable.js +36 -0
  32. package/src/components/base/ui/color-picker/index.js +2 -0
  33. package/src/components/base/ui/color-picker/main.vue +188 -0
  34. package/src/components/base/ui/date-picker/basic/date-table.vue +441 -0
  35. package/src/components/base/ui/date-picker/basic/month-table.vue +254 -0
  36. package/src/components/base/ui/date-picker/basic/time-spinner.vue +304 -0
  37. package/src/components/base/ui/date-picker/basic/year-table.vue +101 -0
  38. package/src/components/base/ui/date-picker/panel/date-range.vue +680 -0
  39. package/src/components/base/ui/date-picker/panel/date.vue +597 -0
  40. package/src/components/base/ui/date-picker/panel/month-range.vue +289 -0
  41. package/src/components/base/ui/date-picker/panel/time-range.vue +248 -0
  42. package/src/components/base/ui/date-picker/panel/time-select.vue +178 -0
  43. package/src/components/base/ui/date-picker/panel/time.vue +186 -0
  44. package/src/components/base/ui/date-picker/picker/date-picker.js +43 -0
  45. package/src/components/base/ui/date-picker/picker/time-picker.js +39 -0
  46. package/src/components/base/ui/date-picker/picker/time-select.js +21 -0
  47. package/src/components/base/ui/date-picker/picker.vue +942 -0
  48. package/src/components/base/ui/dialog/Index.vue +212 -0
  49. package/src/components/base/ui/directive/repeat-click.js +24 -0
  50. package/src/components/base/ui/directive/ripple.js +303 -0
  51. package/src/components/base/ui/divider/Divider.vue +37 -0
  52. package/src/components/base/ui/drawer/Drawer.vue +202 -0
  53. package/src/components/base/ui/dropdown/dropdown-item.vue +39 -0
  54. package/src/components/base/ui/dropdown/dropdown-menu.vue +63 -0
  55. package/src/components/base/ui/dropdown/dropdown.vue +308 -0
  56. package/src/components/base/ui/form/Form.vue +167 -0
  57. package/src/components/base/ui/form/FormItem.vue +334 -0
  58. package/src/components/base/ui/form/LabelWrap.vue +69 -0
  59. package/src/components/base/ui/icon/icon.vue +13 -0
  60. package/src/components/base/ui/image/image-viewer.vue +302 -0
  61. package/src/components/base/ui/image/main.vue +248 -0
  62. package/src/components/base/ui/index.js +189 -0
  63. package/src/components/base/ui/input/Input.vue +438 -0
  64. package/src/components/base/ui/input/calcTextareaHeight.js +104 -0
  65. package/src/components/base/ui/input-number/input-number.vue +285 -0
  66. package/src/components/base/ui/locale/format.js +32 -0
  67. package/src/components/base/ui/locale/index.js +48 -0
  68. package/src/components/base/ui/locale/lang/zh-CN.js +120 -0
  69. package/src/components/base/ui/menu/menu-item-group.vue +45 -0
  70. package/src/components/base/ui/menu/menu-item.vue +112 -0
  71. package/src/components/base/ui/menu/menu-mixin.js +44 -0
  72. package/src/components/base/ui/menu/menu.vue +312 -0
  73. package/src/components/base/ui/menu/submenu.vue +408 -0
  74. package/src/components/base/ui/message/index.js +2 -0
  75. package/src/components/base/ui/message/main.js +87 -0
  76. package/src/components/base/ui/message/main.vue +110 -0
  77. package/src/components/base/ui/message-box/main.js +216 -0
  78. package/src/components/base/ui/message-box/main.vue +323 -0
  79. package/src/components/base/ui/mixin/emitter.js +31 -0
  80. package/src/components/base/ui/mixin/focus.js +9 -0
  81. package/src/components/base/ui/mixin/locale.js +9 -0
  82. package/src/components/base/ui/mixin/migrating.js +33 -0
  83. package/src/components/base/ui/pagination/pager.vue +163 -0
  84. package/src/components/base/ui/pagination/pagination.jsx +391 -0
  85. package/src/components/base/ui/popover/directive.js +20 -0
  86. package/src/components/base/ui/popover/index.js +14 -0
  87. package/src/components/base/ui/popover/main.vue +236 -0
  88. package/src/components/base/ui/progress/Progress.vue +227 -0
  89. package/src/components/base/ui/radio/radio-button.vue +114 -0
  90. package/src/components/base/ui/radio/radio-group.vue +111 -0
  91. package/src/components/base/ui/radio/radio.vue +134 -0
  92. package/src/components/base/ui/row/row.js +47 -0
  93. package/src/components/base/ui/scrollbar/bar.jsx +91 -0
  94. package/src/components/base/ui/scrollbar/index.jsx +203 -0
  95. package/src/components/base/ui/scrollbar/util.js +32 -0
  96. package/src/components/base/ui/select/Option.vue +168 -0
  97. package/src/components/base/ui/select/OptionGroup.vue +60 -0
  98. package/src/components/base/ui/select/Select.vue +920 -0
  99. package/src/components/base/ui/select/SelectDropdown.vue +74 -0
  100. package/src/components/base/ui/select/navigation-mixin.js +54 -0
  101. package/src/components/base/ui/skeleton/index.js +8 -0
  102. package/src/components/base/ui/skeleton/src/img-placeholder.vue +16 -0
  103. package/src/components/base/ui/skeleton/src/index.vue +80 -0
  104. package/src/components/base/ui/skeleton/src/item.vue +22 -0
  105. package/src/components/base/ui/skeleton-item/index.js +8 -0
  106. package/src/components/base/ui/slider/button.vue +238 -0
  107. package/src/components/base/ui/slider/main.vue +427 -0
  108. package/src/components/base/ui/slider/marker.js +18 -0
  109. package/src/components/base/ui/style/alert.scss +147 -0
  110. package/src/components/base/ui/style/animations.scss +65 -0
  111. package/src/components/base/ui/style/autocomplete.scss +81 -0
  112. package/src/components/base/ui/style/backtop.scss +20 -0
  113. package/src/components/base/ui/style/button-group.scss +0 -0
  114. package/src/components/base/ui/style/button.scss +380 -0
  115. package/src/components/base/ui/style/carousel-item.scss +50 -0
  116. package/src/components/base/ui/style/carousel.scss +161 -0
  117. package/src/components/base/ui/style/cascader-panel.scss +120 -0
  118. package/src/components/base/ui/style/cascader.scss +185 -0
  119. package/src/components/base/ui/style/checkbox-button.scss +0 -0
  120. package/src/components/base/ui/style/checkbox-group.scss +0 -0
  121. package/src/components/base/ui/style/checkbox.scss +360 -0
  122. package/src/components/base/ui/style/col.scss +156 -0
  123. package/src/components/base/ui/style/collapse-item.scss +0 -0
  124. package/src/components/base/ui/style/collapse.scss +114 -0
  125. package/src/components/base/ui/style/color-picker.scss +387 -0
  126. package/src/components/base/ui/style/config.scss +4 -0
  127. package/src/components/base/ui/style/date-picker/date-picker.scss +97 -0
  128. package/src/components/base/ui/style/date-picker/date-range-picker.scss +101 -0
  129. package/src/components/base/ui/style/date-picker/date-table.scss +151 -0
  130. package/src/components/base/ui/style/date-picker/month-table.scss +82 -0
  131. package/src/components/base/ui/style/date-picker/picker-panel.scss +117 -0
  132. package/src/components/base/ui/style/date-picker/picker.scss +197 -0
  133. package/src/components/base/ui/style/date-picker/time-picker.scss +85 -0
  134. package/src/components/base/ui/style/date-picker/time-range-picker.scss +31 -0
  135. package/src/components/base/ui/style/date-picker/time-spinner.scss +110 -0
  136. package/src/components/base/ui/style/date-picker/year-table.scss +51 -0
  137. package/src/components/base/ui/style/date-picker.scss +12 -0
  138. package/src/components/base/ui/style/dialog.scss +123 -0
  139. package/src/components/base/ui/style/divider.scss +47 -0
  140. package/src/components/base/ui/style/drawer.scss +218 -0
  141. package/src/components/base/ui/style/dropdown-item.scss +0 -0
  142. package/src/components/base/ui/style/dropdown-menu.scss +0 -0
  143. package/src/components/base/ui/style/dropdown.scss +185 -0
  144. package/src/components/base/ui/style/form-item.scss +0 -0
  145. package/src/components/base/ui/style/form.scss +203 -0
  146. package/src/components/base/ui/style/function.scss +43 -0
  147. package/src/components/base/ui/style/icon.scss +1167 -0
  148. package/src/components/base/ui/style/image.scss +184 -0
  149. package/src/components/base/ui/style/index.scss +57 -0
  150. package/src/components/base/ui/style/input-number.scss +187 -0
  151. package/src/components/base/ui/style/input.scss +477 -0
  152. package/src/components/base/ui/style/menu-item-group.scss +0 -0
  153. package/src/components/base/ui/style/menu-item.scss +0 -0
  154. package/src/components/base/ui/style/menu.scss +294 -0
  155. package/src/components/base/ui/style/message-box.scss +231 -0
  156. package/src/components/base/ui/style/message.scss +120 -0
  157. package/src/components/base/ui/style/mixins.scss +196 -0
  158. package/src/components/base/ui/style/option-group.scss +42 -0
  159. package/src/components/base/ui/style/option.scss +36 -0
  160. package/src/components/base/ui/style/pagination.scss +295 -0
  161. package/src/components/base/ui/style/popover.scss +40 -0
  162. package/src/components/base/ui/style/popper.scss +102 -0
  163. package/src/components/base/ui/style/popup.scss +42 -0
  164. package/src/components/base/ui/style/progress.scss +141 -0
  165. package/src/components/base/ui/style/radio-button.scss +113 -0
  166. package/src/components/base/ui/style/radio-group.scss +9 -0
  167. package/src/components/base/ui/style/radio.scss +203 -0
  168. package/src/components/base/ui/style/ripple.scss +35 -0
  169. package/src/components/base/ui/style/row.scss +39 -0
  170. package/src/components/base/ui/style/scrollbar.scss +75 -0
  171. package/src/components/base/ui/style/select-dropdown.scss +59 -0
  172. package/src/components/base/ui/style/select.scss +154 -0
  173. package/src/components/base/ui/style/skeleton-item.scss +84 -0
  174. package/src/components/base/ui/style/skeleton.scss +40 -0
  175. package/src/components/base/ui/style/slider.scss +250 -0
  176. package/src/components/base/ui/style/switch.scss +116 -0
  177. package/src/components/base/ui/style/tabs.scss +602 -0
  178. package/src/components/base/ui/style/tag.scss +174 -0
  179. package/src/components/base/ui/style/tooltip.scss +146 -0
  180. package/src/components/base/ui/style/transition.scss +138 -0
  181. package/src/components/base/ui/style/upload.scss +603 -0
  182. package/src/components/base/ui/style/utils.scss +39 -0
  183. package/src/components/base/ui/style/var.scss +1007 -0
  184. package/src/components/base/ui/switch/index.vue +174 -0
  185. package/src/components/base/ui/tabs/tab-bar.vue +57 -0
  186. package/src/components/base/ui/tabs/tab-nav.vue +294 -0
  187. package/src/components/base/ui/tabs/tab-pane.vue +56 -0
  188. package/src/components/base/ui/tabs/tabs.vue +191 -0
  189. package/src/components/base/ui/tag/Tag.vue +60 -0
  190. package/src/components/base/ui/tooltip/tooltip.jsx +234 -0
  191. package/src/components/base/ui/upload/Index.vue +340 -0
  192. package/src/components/base/ui/upload/Upload.vue +216 -0
  193. package/src/components/base/ui/upload/UploadDragger.vue +70 -0
  194. package/src/components/base/ui/upload/UploadList.vue +100 -0
  195. package/src/components/base/ui/upload/ajax.js +85 -0
  196. package/src/components/base/ui/util/aria-dialog.js +90 -0
  197. package/src/components/base/ui/util/aria-utils.js +122 -0
  198. package/src/components/base/ui/util/clickoutside.js +76 -0
  199. package/src/components/base/ui/util/date-util.js +292 -0
  200. package/src/components/base/ui/util/date.js +370 -0
  201. package/src/components/base/ui/util/debounce.js +21 -0
  202. package/src/components/base/ui/util/deepmerge.js +100 -0
  203. package/src/components/base/ui/util/dom.js +215 -0
  204. package/src/components/base/ui/util/index.js +262 -0
  205. package/src/components/base/ui/util/menu/aria-menubar.js +14 -0
  206. package/src/components/base/ui/util/menu/aria-menuitem.js +49 -0
  207. package/src/components/base/ui/util/menu/aria-submenu.js +59 -0
  208. package/src/components/base/ui/util/merge.js +14 -0
  209. package/src/components/base/ui/util/popper.js +1235 -0
  210. package/src/components/base/ui/util/popup/index.js +218 -0
  211. package/src/components/base/ui/util/popup/popup-manager.js +194 -0
  212. package/src/components/base/ui/util/resize-events.js +32 -0
  213. package/src/components/base/ui/util/scroll-into-view.js +27 -0
  214. package/src/components/base/ui/util/scrollbar-width.js +29 -0
  215. package/src/components/base/ui/util/shared.js +7 -0
  216. package/src/components/base/ui/util/throttle.js +91 -0
  217. package/src/components/base/ui/util/types.js +24 -0
  218. package/src/components/base/ui/util/vdom.js +5 -0
  219. package/src/components/base/ui/util/vue-popper.js +188 -0
  220. package/src/components/normal/AggsItemH.vue +139 -0
  221. package/src/index.js +10 -0
  222. package/src/static/base-icons.ttf +0 -0
  223. package/src/static/base-icons.woff +0 -0
  224. package/src/static/label_bg.png +0 -0
  225. package/src/static/term-label-bg.png +0 -0
  226. package/src/style/app-article.scss +698 -0
  227. package/src/style/app-comment.scss +259 -0
  228. package/src/style/app-recommend.scss +48 -0
  229. package/src/style/app-richtext.scss +176 -0
  230. package/src/style/index.scss +523 -0
  231. package/vite.config.js +38 -0
@@ -0,0 +1,180 @@
1
+ <template>
2
+ <div class="base-collapse-item"
3
+ :class="{'is-active': isActive, 'is-disabled': disabled }">
4
+ <div
5
+ role="tab"
6
+ :aria-expanded="isActive"
7
+ :aria-controls="`base-collapse-content-${id}`"
8
+ :aria-describedby ="`base-collapse-content-${id}`"
9
+ >
10
+ <div
11
+ class="base-collapse-item__header"
12
+ @click="handleHeaderClick"
13
+ role="button"
14
+ :id="`base-collapse-head-${id}`"
15
+ :tabindex="disabled ? undefined : 0"
16
+ @keyup.space.enter.stop="handleEnterClick"
17
+ :class="{
18
+ 'focusing': focusing,
19
+ 'is-active': isActive
20
+ }"
21
+ @focus="handleFocus"
22
+ @blur="focusing = false"
23
+ >
24
+ <slot name="title">{{title}}</slot>
25
+ <i
26
+ class="base-collapse-item__arrow base-icon-caret-right"
27
+ :class="{'is-active': isActive}">
28
+ </i>
29
+ </div>
30
+ </div>
31
+ <transition
32
+ v-on:before-enter="beforeEnter"
33
+ v-on:enter="enter"
34
+ v-on:after-enter="afterEnter"
35
+ v-on:before-leave="beforeLeave"
36
+ v-on:leave="leave"
37
+ v-on:after-leave="afterLeave"
38
+ >
39
+ <div
40
+ class="base-collapse-item__wrap"
41
+ v-show="isActive"
42
+ role="tabpanel"
43
+ :aria-hidden="!isActive"
44
+ :aria-labelledby="`base-collapse-head-${id}`"
45
+ :id="`base-collapse-content-${id}`"
46
+ >
47
+ <div class="base-collapse-item__content">
48
+ <slot></slot>
49
+ </div>
50
+ </div>
51
+ </transition>
52
+ </div>
53
+ </template>
54
+ <script>
55
+ import Emitter from '../mixin/emitter'
56
+ import { generateId } from '../util/index'
57
+ import { addClass, removeClass } from '../util/dom'
58
+
59
+ export default {
60
+ name: 'BaseCollapseItem',
61
+
62
+ componentName: 'BaseCollapseItem',
63
+
64
+ mixins: [Emitter],
65
+
66
+ data() {
67
+ return {
68
+ contentWrapStyle: {
69
+ height: 'auto',
70
+ display: 'block'
71
+ },
72
+ contentHeight: 0,
73
+ focusing: false,
74
+ isClick: false,
75
+ id: generateId()
76
+ };
77
+ },
78
+
79
+ inject: ['collapse'],
80
+
81
+ props: {
82
+ title: String,
83
+ name: {
84
+ type: [String, Number],
85
+ default() {
86
+ return this._uid;
87
+ }
88
+ },
89
+ disabled: Boolean
90
+ },
91
+
92
+ computed: {
93
+ isActive() {
94
+ return this.collapse.activeNames.indexOf(this.name) > -1;
95
+ }
96
+ },
97
+
98
+ methods: {
99
+ handleFocus() {
100
+ setTimeout(() => {
101
+ if (!this.isClick) {
102
+ this.focusing = true;
103
+ } else {
104
+ this.isClick = false;
105
+ }
106
+ }, 50);
107
+ },
108
+ handleHeaderClick() {
109
+ if (this.disabled) return;
110
+ this.dispatch('BaseCollapse', 'item-click', this);
111
+ this.focusing = false;
112
+ this.isClick = true;
113
+ },
114
+ handleEnterClick() {
115
+ this.dispatch('BaseCollapse', 'item-click', this);
116
+ },
117
+ beforeEnter(el) {
118
+ addClass(el, 'collapse-transition');
119
+ if (!el.dataset) el.dataset = {};
120
+
121
+ el.dataset.oldPaddingTop = el.style.paddingTop;
122
+ el.dataset.oldPaddingBottom = el.style.paddingBottom;
123
+
124
+ el.style.height = '0';
125
+ el.style.paddingTop = 0;
126
+ el.style.paddingBottom = 0;
127
+ },
128
+
129
+ enter(el) {
130
+ el.dataset.oldOverflow = el.style.overflow;
131
+ if (el.scrollHeight !== 0) {
132
+ el.style.height = el.scrollHeight + 'px';
133
+ el.style.paddingTop = el.dataset.oldPaddingTop;
134
+ el.style.paddingBottom = el.dataset.oldPaddingBottom;
135
+ } else {
136
+ el.style.height = '';
137
+ el.style.paddingTop = el.dataset.oldPaddingTop;
138
+ el.style.paddingBottom = el.dataset.oldPaddingBottom;
139
+ }
140
+
141
+ el.style.overflow = 'hidden';
142
+ },
143
+
144
+ afterEnter(el) {
145
+ // for safari: remove class then reset height is necessary
146
+ removeClass(el, 'collapse-transition');
147
+ el.style.height = '';
148
+ el.style.overflow = el.dataset.oldOverflow;
149
+ },
150
+
151
+ beforeLeave(el) {
152
+ if (!el.dataset) el.dataset = {};
153
+ el.dataset.oldPaddingTop = el.style.paddingTop;
154
+ el.dataset.oldPaddingBottom = el.style.paddingBottom;
155
+ el.dataset.oldOverflow = el.style.overflow;
156
+
157
+ el.style.height = el.scrollHeight + 'px';
158
+ el.style.overflow = 'hidden';
159
+ },
160
+
161
+ leave(el) {
162
+ if (el.scrollHeight !== 0) {
163
+ // for safari: add class after set height, or it will jump to zero height suddenly, weired
164
+ addClass(el, 'collapse-transition');
165
+ el.style.height = 0;
166
+ el.style.paddingTop = 0;
167
+ el.style.paddingBottom = 0;
168
+ }
169
+ },
170
+
171
+ afterLeave(el) {
172
+ removeClass(el, 'collapse-transition');
173
+ el.style.height = '';
174
+ el.style.overflow = el.dataset.oldOverflow;
175
+ el.style.paddingTop = el.dataset.oldPaddingTop;
176
+ el.style.paddingBottom = el.dataset.oldPaddingBottom;
177
+ }
178
+ }
179
+ }
180
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div class="base-collapse" role="tablist" aria-multiselectable="true">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+ <script>
7
+ export default {
8
+ name: 'BaseCollapse',
9
+
10
+ componentName: 'BaseCollapse',
11
+
12
+ props: {
13
+ accordion: Boolean,
14
+ value: {
15
+ type: [Array, String, Number],
16
+ default() {
17
+ return [];
18
+ }
19
+ }
20
+ },
21
+
22
+ data() {
23
+ return {
24
+ activeNames: [].concat(this.value)
25
+ };
26
+ },
27
+
28
+ provide() {
29
+ return {
30
+ collapse: this
31
+ };
32
+ },
33
+
34
+ watch: {
35
+ value(value) {
36
+ this.activeNames = [].concat(value);
37
+ }
38
+ },
39
+
40
+ methods: {
41
+ setActiveNames(activeNames) {
42
+ activeNames = [].concat(activeNames);
43
+ let value = this.accordion ? activeNames[0] : activeNames;
44
+ this.activeNames = activeNames;
45
+ this.$emit('input', value);
46
+ this.$emit('change', value);
47
+ },
48
+ handleItemClick(item) {
49
+ if (this.accordion) {
50
+ this.setActiveNames(
51
+ (this.activeNames[0] || this.activeNames[0] === 0) &&
52
+ this.activeNames[0] === item.name
53
+ ? '' : item.name
54
+ );
55
+ } else {
56
+ let activeNames = this.activeNames.slice(0);
57
+ let index = activeNames.indexOf(item.name);
58
+
59
+ if (index > -1) {
60
+ activeNames.splice(index, 1);
61
+ } else {
62
+ activeNames.push(item.name);
63
+ }
64
+ this.setActiveNames(activeNames);
65
+ }
66
+ }
67
+ },
68
+
69
+ created() {
70
+ this.$on('item-click', this.handleItemClick);
71
+ }
72
+ };
73
+ </script>
@@ -0,0 +1,317 @@
1
+ const hsv2hsl = function(hue, sat, val) {
2
+ return [
3
+ hue,
4
+ (sat * val / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue)) || 0,
5
+ hue / 2
6
+ ];
7
+ };
8
+
9
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
10
+ // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
11
+ const isOnePointZero = function(n) {
12
+ return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;
13
+ };
14
+
15
+ const isPercentage = function(n) {
16
+ return typeof n === 'string' && n.indexOf('%') !== -1;
17
+ };
18
+
19
+ // Take input from [0, n] and return it as [0, 1]
20
+ const bound01 = function(value, max) {
21
+ if (isOnePointZero(value)) value = '100%';
22
+
23
+ const processPercent = isPercentage(value);
24
+ value = Math.min(max, Math.max(0, parseFloat(value)));
25
+
26
+ // Automatically convert percentage into number
27
+ if (processPercent) {
28
+ value = parseInt(value * max, 10) / 100;
29
+ }
30
+
31
+ // Handle floating point rounding errors
32
+ if ((Math.abs(value - max) < 0.000001)) {
33
+ return 1;
34
+ }
35
+
36
+ // Convert into [0, 1] range if it isn't already
37
+ return (value % max) / parseFloat(max);
38
+ };
39
+
40
+ const INT_HEX_MAP = { 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F' };
41
+
42
+ const toHex = function({ r, g, b }) {
43
+ const hexOne = function(value) {
44
+ value = Math.min(Math.round(value), 255);
45
+ const high = Math.floor(value / 16);
46
+ const low = value % 16;
47
+ return '' + (INT_HEX_MAP[high] || high) + (INT_HEX_MAP[low] || low);
48
+ };
49
+
50
+ if (isNaN(r) || isNaN(g) || isNaN(b)) return '';
51
+
52
+ return '#' + hexOne(r) + hexOne(g) + hexOne(b);
53
+ };
54
+
55
+ const HEX_INT_MAP = { A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 };
56
+
57
+ const parseHexChannel = function(hex) {
58
+ if (hex.length === 2) {
59
+ return (HEX_INT_MAP[hex[0].toUpperCase()] || +hex[0]) * 16 + (HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1]);
60
+ }
61
+
62
+ return HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1];
63
+ };
64
+
65
+ const hsl2hsv = function(hue, sat, light) {
66
+ sat = sat / 100;
67
+ light = light / 100;
68
+ let smin = sat;
69
+ const lmin = Math.max(light, 0.01);
70
+ let sv;
71
+ let v;
72
+
73
+ light *= 2;
74
+ sat *= (light <= 1) ? light : 2 - light;
75
+ smin *= lmin <= 1 ? lmin : 2 - lmin;
76
+ v = (light + sat) / 2;
77
+ sv = light === 0 ? (2 * smin) / (lmin + smin) : (2 * sat) / (light + sat);
78
+
79
+ return {
80
+ h: hue,
81
+ s: sv * 100,
82
+ v: v * 100
83
+ };
84
+ };
85
+
86
+ // `rgbToHsv`
87
+ // Converts an RGB color value to HSV
88
+ // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
89
+ // *Returns:* { h, s, v } in [0,1]
90
+ const rgb2hsv = function(r, g, b) {
91
+ r = bound01(r, 255);
92
+ g = bound01(g, 255);
93
+ b = bound01(b, 255);
94
+
95
+ const max = Math.max(r, g, b);
96
+ const min = Math.min(r, g, b);
97
+ let h, s;
98
+ let v = max;
99
+
100
+ const d = max - min;
101
+ s = max === 0 ? 0 : d / max;
102
+
103
+ if (max === min) {
104
+ h = 0; // achromatic
105
+ } else {
106
+ switch (max) {
107
+ case r:
108
+ h = (g - b) / d + (g < b ? 6 : 0);
109
+ break;
110
+ case g:
111
+ h = (b - r) / d + 2;
112
+ break;
113
+ case b:
114
+ h = (r - g) / d + 4;
115
+ break;
116
+ }
117
+ h /= 6;
118
+ }
119
+
120
+ return { h: h * 360, s: s * 100, v: v * 100 };
121
+ };
122
+
123
+ // `hsvToRgb`
124
+ // Converts an HSV color value to RGB.
125
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
126
+ // *Returns:* { r, g, b } in the set [0, 255]
127
+ const hsv2rgb = function(h, s, v) {
128
+ h = bound01(h, 360) * 6;
129
+ s = bound01(s, 100);
130
+ v = bound01(v, 100);
131
+
132
+ const i = Math.floor(h);
133
+ const f = h - i;
134
+ const p = v * (1 - s);
135
+ const q = v * (1 - f * s);
136
+ const t = v * (1 - (1 - f) * s);
137
+ const mod = i % 6;
138
+ const r = [v, q, p, p, t, v][mod];
139
+ const g = [t, v, v, q, p, p][mod];
140
+ const b = [p, p, t, v, v, q][mod];
141
+
142
+ return {
143
+ r: Math.round(r * 255),
144
+ g: Math.round(g * 255),
145
+ b: Math.round(b * 255)
146
+ };
147
+ };
148
+
149
+ export default class Color {
150
+ constructor(options) {
151
+ this._hue = 0;
152
+ this._saturation = 100;
153
+ this._value = 100;
154
+ this._alpha = 100;
155
+
156
+ this.enableAlpha = false;
157
+ this.format = 'hex';
158
+ this.value = '';
159
+
160
+ options = options || {};
161
+
162
+ for (let option in options) {
163
+ if (options.hasOwnProperty(option)) {
164
+ this[option] = options[option];
165
+ }
166
+ }
167
+
168
+ this.doOnChange();
169
+ }
170
+
171
+ set(prop, value) {
172
+ if (arguments.length === 1 && typeof prop === 'object') {
173
+ for (let p in prop) {
174
+ if (prop.hasOwnProperty(p)) {
175
+ this.set(p, prop[p]);
176
+ }
177
+ }
178
+
179
+ return;
180
+ }
181
+
182
+ this['_' + prop] = value;
183
+ this.doOnChange();
184
+ }
185
+
186
+ get(prop) {
187
+ return this['_' + prop];
188
+ }
189
+
190
+ toRgb() {
191
+ return hsv2rgb(this._hue, this._saturation, this._value);
192
+ }
193
+
194
+ fromString(value) {
195
+ if (!value) {
196
+ this._hue = 0;
197
+ this._saturation = 100;
198
+ this._value = 100;
199
+
200
+ this.doOnChange();
201
+ return;
202
+ }
203
+
204
+ const fromHSV = (h, s, v) => {
205
+ this._hue = Math.max(0, Math.min(360, h));
206
+ this._saturation = Math.max(0, Math.min(100, s));
207
+ this._value = Math.max(0, Math.min(100, v));
208
+
209
+ this.doOnChange();
210
+ };
211
+
212
+ if (value.indexOf('hsl') !== -1) {
213
+ const parts = value.replace(/hsla|hsl|\(|\)/gm, '')
214
+ .split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
215
+
216
+ if (parts.length === 4) {
217
+ this._alpha = Math.floor(parseFloat(parts[3]) * 100);
218
+ } else if (parts.length === 3) {
219
+ this._alpha = 100;
220
+ }
221
+ if (parts.length >= 3) {
222
+ const { h, s, v } = hsl2hsv(parts[0], parts[1], parts[2]);
223
+ fromHSV(h, s, v);
224
+ }
225
+ } else if (value.indexOf('hsv') !== -1) {
226
+ const parts = value.replace(/hsva|hsv|\(|\)/gm, '')
227
+ .split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
228
+
229
+ if (parts.length === 4) {
230
+ this._alpha = Math.floor(parseFloat(parts[3]) * 100);
231
+ } else if (parts.length === 3) {
232
+ this._alpha = 100;
233
+ }
234
+ if (parts.length >= 3) {
235
+ fromHSV(parts[0], parts[1], parts[2]);
236
+ }
237
+ } else if (value.indexOf('rgb') !== -1) {
238
+ const parts = value.replace(/rgba|rgb|\(|\)/gm, '')
239
+ .split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
240
+
241
+ if (parts.length === 4) {
242
+ this._alpha = Math.floor(parseFloat(parts[3]) * 100);
243
+ } else if (parts.length === 3) {
244
+ this._alpha = 100;
245
+ }
246
+ if (parts.length >= 3) {
247
+ const { h, s, v } = rgb2hsv(parts[0], parts[1], parts[2]);
248
+ fromHSV(h, s, v);
249
+ }
250
+ } else if (value.indexOf('#') !== -1) {
251
+ const hex = value.replace('#', '').trim();
252
+ if (!/^(?:[0-9a-fA-F]{3}){1,2}$/.test(hex)) return;
253
+ let r, g, b;
254
+
255
+ if (hex.length === 3) {
256
+ r = parseHexChannel(hex[0] + hex[0]);
257
+ g = parseHexChannel(hex[1] + hex[1]);
258
+ b = parseHexChannel(hex[2] + hex[2]);
259
+ } else if (hex.length === 6 || hex.length === 8) {
260
+ r = parseHexChannel(hex.substring(0, 2));
261
+ g = parseHexChannel(hex.substring(2, 4));
262
+ b = parseHexChannel(hex.substring(4, 6));
263
+ }
264
+
265
+ if (hex.length === 8) {
266
+ this._alpha = Math.floor(parseHexChannel(hex.substring(6)) / 255 * 100);
267
+ } else if (hex.length === 3 || hex.length === 6) {
268
+ this._alpha = 100;
269
+ }
270
+
271
+ const { h, s, v } = rgb2hsv(r, g, b);
272
+ fromHSV(h, s, v);
273
+ }
274
+ }
275
+
276
+ compare(color) {
277
+ return Math.abs(color._hue - this._hue) < 2 &&
278
+ Math.abs(color._saturation - this._saturation) < 1 &&
279
+ Math.abs(color._value - this._value) < 1 &&
280
+ Math.abs(color._alpha - this._alpha) < 1;
281
+ }
282
+
283
+ doOnChange() {
284
+ const { _hue, _saturation, _value, _alpha, format } = this;
285
+
286
+ if (this.enableAlpha) {
287
+ switch (format) {
288
+ case 'hsl':
289
+ const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
290
+ this.value = `hsla(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%, ${ _alpha / 100})`;
291
+ break;
292
+ case 'hsv':
293
+ this.value = `hsva(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%, ${ _alpha / 100})`;
294
+ break;
295
+ default:
296
+ const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
297
+ this.value = `rgba(${r}, ${g}, ${b}, ${ _alpha / 100 })`;
298
+ }
299
+ } else {
300
+ switch (format) {
301
+ case 'hsl':
302
+ const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
303
+ this.value = `hsl(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%)`;
304
+ break;
305
+ case 'hsv':
306
+ this.value = `hsv(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%)`;
307
+ break;
308
+ case 'rgb':
309
+ const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
310
+ this.value = `rgb(${r}, ${g}, ${b})`;
311
+ break;
312
+ default:
313
+ this.value = toHex(hsv2rgb(_hue, _saturation, _value));
314
+ }
315
+ }
316
+ }
317
+ };
@@ -0,0 +1,132 @@
1
+ <template>
2
+ <div class="base-color-alpha-slider" :class="{ 'is-vertical': vertical }">
3
+ <div class="base-color-alpha-slider__bar"
4
+ @click="handleClick"
5
+ ref="bar"
6
+ :style="{
7
+ background: background
8
+ }">
9
+ </div>
10
+ <div class="base-color-alpha-slider__thumb"
11
+ ref="thumb"
12
+ :style="{
13
+ left: thumbLeft + 'px',
14
+ top: thumbTop + 'px'
15
+ }">
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import draggable from '../draggable';
22
+
23
+ export default {
24
+ name: 'base-color-alpha-slider',
25
+
26
+ props: {
27
+ color: {
28
+ required: true
29
+ },
30
+ vertical: Boolean
31
+ },
32
+
33
+ watch: {
34
+ 'color._alpha'() {
35
+ this.update();
36
+ },
37
+
38
+ 'color.value'() {
39
+ this.update();
40
+ }
41
+ },
42
+
43
+ methods: {
44
+ handleClick(event) {
45
+ const thumb = this.$refs.thumb;
46
+ const target = event.target;
47
+
48
+ if (target !== thumb) {
49
+ this.handleDrag(event);
50
+ }
51
+ },
52
+
53
+ handleDrag(event) {
54
+ const rect = this.$el.getBoundingClientRect();
55
+ const { thumb } = this.$refs;
56
+
57
+ if (!this.vertical) {
58
+ let left = event.clientX - rect.left;
59
+ left = Math.max(thumb.offsetWidth / 2, left);
60
+ left = Math.min(left, rect.width - thumb.offsetWidth / 2);
61
+
62
+ this.color.set('alpha', Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 100));
63
+ } else {
64
+ let top = event.clientY - rect.top;
65
+ top = Math.max(thumb.offsetHeight / 2, top);
66
+ top = Math.min(top, rect.height - thumb.offsetHeight / 2);
67
+
68
+ this.color.set('alpha', Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 100));
69
+ }
70
+ },
71
+
72
+ getThumbLeft() {
73
+ if (this.vertical) return 0;
74
+ const el = this.$el;
75
+ const alpha = this.color._alpha;
76
+
77
+ if (!el) return 0;
78
+ const thumb = this.$refs.thumb;
79
+ return Math.round(alpha * (el.offsetWidth - thumb.offsetWidth / 2) / 100);
80
+ },
81
+
82
+ getThumbTop() {
83
+ if (!this.vertical) return 0;
84
+ const el = this.$el;
85
+ const alpha = this.color._alpha;
86
+
87
+ if (!el) return 0;
88
+ const thumb = this.$refs.thumb;
89
+ return Math.round(alpha * (el.offsetHeight - thumb.offsetHeight / 2) / 100);
90
+ },
91
+
92
+ getBackground() {
93
+ if (this.color && this.color.value) {
94
+ const { r, g, b } = this.color.toRgb();
95
+ return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`;
96
+ }
97
+ return null;
98
+ },
99
+
100
+ update() {
101
+ this.thumbLeft = this.getThumbLeft();
102
+ this.thumbTop = this.getThumbTop();
103
+ this.background = this.getBackground();
104
+ }
105
+ },
106
+
107
+ data() {
108
+ return {
109
+ thumbLeft: 0,
110
+ thumbTop: 0,
111
+ background: null
112
+ };
113
+ },
114
+
115
+ mounted() {
116
+ const { bar, thumb } = this.$refs;
117
+
118
+ const dragConfig = {
119
+ drag: (event) => {
120
+ this.handleDrag(event);
121
+ },
122
+ end: (event) => {
123
+ this.handleDrag(event);
124
+ }
125
+ };
126
+
127
+ draggable(bar, dragConfig);
128
+ draggable(thumb, dragConfig);
129
+ this.update();
130
+ }
131
+ };
132
+ </script>