32b63044037b272563774f5997e9fbfe93a28e2d62225403fb735b078dff010a4224473787f67c10369e4bb19f093569619c48749bd28178f331be26cfa216 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. import { defineComponent, ref, computed, watch, provide, openBlock, createBlock, unref, withCtx, withDirectives, mergeProps, withKeys, createElementVNode, createVNode, normalizeClass, createTextVNode, toDisplayString, normalizeStyle, vShow, nextTick } from 'vue';
  2. import { pick, debounce } from 'lodash-unified';
  3. import { ElIcon } from '../../icon/index.mjs';
  4. import { reactiveComputed } from '@vueuse/core';
  5. import { ElTooltip } from '../../tooltip/index.mjs';
  6. import { ElButton } from '../../button/index.mjs';
  7. import { ArrowDown, Close } from '@element-plus/icons-vue';
  8. import { colorPickerProps, colorPickerEmits } from './color-picker.mjs';
  9. import { ElColorPickerPanel } from '../../color-picker-panel/index.mjs';
  10. import Color from '../../color-picker-panel/src/utils/color.mjs';
  11. import { useCommonColor } from '../../color-picker-panel/src/composables/use-common-color.mjs';
  12. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  13. import { colorPickerPanelProps, ROOT_COMMON_COLOR_INJECTION_KEY } from '../../color-picker-panel/src/color-picker-panel.mjs';
  14. import ClickOutside from '../../../directives/click-outside/index.mjs';
  15. import { useLocale } from '../../../hooks/use-locale/index.mjs';
  16. import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
  17. import { useFormItem, useFormItemInputId } from '../../form/src/hooks/use-form-item.mjs';
  18. import { useFormSize, useFormDisabled } from '../../form/src/hooks/use-form-common-props.mjs';
  19. import { useEmptyValues } from '../../../hooks/use-empty-values/index.mjs';
  20. import { useFocusController } from '../../../hooks/use-focus-controller/index.mjs';
  21. import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '../../../constants/event.mjs';
  22. import { debugWarn } from '../../../utils/error.mjs';
  23. import { EVENT_CODE } from '../../../constants/aria.mjs';
  24. const __default__ = defineComponent({
  25. name: "ElColorPicker"
  26. });
  27. const _sfc_main = /* @__PURE__ */ defineComponent({
  28. ...__default__,
  29. props: colorPickerProps,
  30. emits: colorPickerEmits,
  31. setup(__props, { expose, emit }) {
  32. const props = __props;
  33. const { t } = useLocale();
  34. const ns = useNamespace("color");
  35. const { formItem } = useFormItem();
  36. const colorSize = useFormSize();
  37. const colorDisabled = useFormDisabled();
  38. const { valueOnClear, isEmptyValue } = useEmptyValues(props, null);
  39. const commonColor = useCommonColor(props, emit);
  40. const { inputId: buttonId, isLabeledByFormItem } = useFormItemInputId(props, {
  41. formItemContext: formItem
  42. });
  43. const popper = ref();
  44. const triggerRef = ref();
  45. const pickerPanelRef = ref();
  46. const showPicker = ref(false);
  47. const showPanelColor = ref(false);
  48. let shouldActiveChange = true;
  49. const { isFocused, handleFocus, handleBlur } = useFocusController(triggerRef, {
  50. disabled: colorDisabled,
  51. beforeBlur(event) {
  52. var _a;
  53. return (_a = popper.value) == null ? void 0 : _a.isFocusInsideContent(event);
  54. },
  55. afterBlur() {
  56. setShowPicker(false);
  57. resetColor();
  58. }
  59. });
  60. const color = reactiveComputed(() => {
  61. var _a, _b;
  62. return (_b = (_a = pickerPanelRef.value) == null ? void 0 : _a.color) != null ? _b : commonColor.color;
  63. });
  64. const panelProps = computed(() => pick(props, Object.keys(colorPickerPanelProps)));
  65. const displayedColor = computed(() => {
  66. if (!props.modelValue && !showPanelColor.value) {
  67. return "transparent";
  68. }
  69. return displayedRgb(color, props.showAlpha);
  70. });
  71. const currentColor = computed(() => {
  72. return !props.modelValue && !showPanelColor.value ? "" : color.value;
  73. });
  74. const buttonAriaLabel = computed(() => {
  75. return !isLabeledByFormItem.value ? props.ariaLabel || t("el.colorpicker.defaultLabel") : void 0;
  76. });
  77. const buttonAriaLabelledby = computed(() => {
  78. return isLabeledByFormItem.value ? formItem == null ? void 0 : formItem.labelId : void 0;
  79. });
  80. const btnKls = computed(() => {
  81. return [
  82. ns.b("picker"),
  83. ns.is("disabled", colorDisabled.value),
  84. ns.bm("picker", colorSize.value),
  85. ns.is("focused", isFocused.value)
  86. ];
  87. });
  88. function displayedRgb(color2, showAlpha) {
  89. const { r, g, b, a } = color2.toRgb();
  90. return showAlpha ? `rgba(${r}, ${g}, ${b}, ${a})` : `rgb(${r}, ${g}, ${b})`;
  91. }
  92. function setShowPicker(value) {
  93. showPicker.value = value;
  94. }
  95. const debounceSetShowPicker = debounce(setShowPicker, 100, { leading: true });
  96. function show() {
  97. if (colorDisabled.value)
  98. return;
  99. setShowPicker(true);
  100. }
  101. function hide() {
  102. debounceSetShowPicker(false);
  103. resetColor();
  104. }
  105. function resetColor() {
  106. nextTick(() => {
  107. if (props.modelValue) {
  108. color.fromString(props.modelValue);
  109. } else {
  110. color.value = "";
  111. nextTick(() => {
  112. showPanelColor.value = false;
  113. });
  114. }
  115. });
  116. }
  117. function handleTrigger() {
  118. if (colorDisabled.value)
  119. return;
  120. if (showPicker.value) {
  121. resetColor();
  122. }
  123. debounceSetShowPicker(!showPicker.value);
  124. }
  125. function confirmValue() {
  126. const value = isEmptyValue(color.value) ? valueOnClear.value : color.value;
  127. emit(UPDATE_MODEL_EVENT, value);
  128. emit(CHANGE_EVENT, value);
  129. if (props.validateEvent) {
  130. formItem == null ? void 0 : formItem.validate("change").catch((err) => debugWarn());
  131. }
  132. debounceSetShowPicker(false);
  133. nextTick(() => {
  134. const newColor = new Color({
  135. enableAlpha: props.showAlpha,
  136. format: props.colorFormat || "",
  137. value: props.modelValue
  138. });
  139. if (!color.compare(newColor)) {
  140. resetColor();
  141. }
  142. });
  143. }
  144. function clear() {
  145. debounceSetShowPicker(false);
  146. emit(UPDATE_MODEL_EVENT, valueOnClear.value);
  147. emit(CHANGE_EVENT, valueOnClear.value);
  148. if (props.modelValue !== valueOnClear.value && props.validateEvent) {
  149. formItem == null ? void 0 : formItem.validate("change").catch((err) => debugWarn());
  150. }
  151. resetColor();
  152. }
  153. function handleClickOutside() {
  154. if (!showPicker.value)
  155. return;
  156. hide();
  157. isFocused.value && focus();
  158. }
  159. function handleEsc(event) {
  160. event.preventDefault();
  161. event.stopPropagation();
  162. setShowPicker(false);
  163. resetColor();
  164. }
  165. function handleKeyDown(event) {
  166. var _a, _b;
  167. switch (event.code) {
  168. case EVENT_CODE.enter:
  169. case EVENT_CODE.numpadEnter:
  170. case EVENT_CODE.space:
  171. event.preventDefault();
  172. event.stopPropagation();
  173. show();
  174. (_b = (_a = pickerPanelRef == null ? void 0 : pickerPanelRef.value) == null ? void 0 : _a.inputRef) == null ? void 0 : _b.focus();
  175. break;
  176. case EVENT_CODE.esc:
  177. handleEsc(event);
  178. break;
  179. }
  180. }
  181. function focus() {
  182. triggerRef.value.focus();
  183. }
  184. function blur() {
  185. triggerRef.value.blur();
  186. }
  187. watch(() => currentColor.value, (val) => {
  188. shouldActiveChange && emit("activeChange", val);
  189. shouldActiveChange = true;
  190. });
  191. watch(() => color.value, () => {
  192. if (!props.modelValue && !showPanelColor.value) {
  193. showPanelColor.value = true;
  194. }
  195. });
  196. watch(() => props.modelValue, (newVal) => {
  197. if (!newVal) {
  198. showPanelColor.value = false;
  199. } else if (newVal && newVal !== color.value) {
  200. shouldActiveChange = false;
  201. color.fromString(newVal);
  202. }
  203. });
  204. provide(ROOT_COMMON_COLOR_INJECTION_KEY, commonColor);
  205. expose({
  206. color,
  207. show,
  208. hide,
  209. focus,
  210. blur
  211. });
  212. return (_ctx, _cache) => {
  213. return openBlock(), createBlock(unref(ElTooltip), {
  214. ref_key: "popper",
  215. ref: popper,
  216. visible: showPicker.value,
  217. "show-arrow": false,
  218. "fallback-placements": ["bottom", "top", "right", "left"],
  219. offset: 0,
  220. "gpu-acceleration": false,
  221. "popper-class": [unref(ns).be("picker", "panel"), _ctx.popperClass],
  222. "stop-popper-mouse-event": false,
  223. pure: "",
  224. effect: "light",
  225. trigger: "click",
  226. teleported: _ctx.teleported,
  227. transition: `${unref(ns).namespace.value}-zoom-in-top`,
  228. persistent: _ctx.persistent,
  229. "append-to": _ctx.appendTo,
  230. onHide: ($event) => setShowPicker(false)
  231. }, {
  232. content: withCtx(() => [
  233. withDirectives((openBlock(), createBlock(unref(ElColorPickerPanel), mergeProps({
  234. ref_key: "pickerPanelRef",
  235. ref: pickerPanelRef
  236. }, unref(panelProps), {
  237. border: false,
  238. onKeydown: withKeys(handleEsc, ["esc"])
  239. }), {
  240. footer: withCtx(() => [
  241. createElementVNode("div", null, [
  242. createVNode(unref(ElButton), {
  243. class: normalizeClass(unref(ns).be("footer", "link-btn")),
  244. text: "",
  245. size: "small",
  246. onClick: clear
  247. }, {
  248. default: withCtx(() => [
  249. createTextVNode(toDisplayString(unref(t)("el.colorpicker.clear")), 1)
  250. ]),
  251. _: 1
  252. }, 8, ["class"]),
  253. createVNode(unref(ElButton), {
  254. plain: "",
  255. size: "small",
  256. class: normalizeClass(unref(ns).be("footer", "btn")),
  257. onClick: confirmValue
  258. }, {
  259. default: withCtx(() => [
  260. createTextVNode(toDisplayString(unref(t)("el.colorpicker.confirm")), 1)
  261. ]),
  262. _: 1
  263. }, 8, ["class"])
  264. ])
  265. ]),
  266. _: 1
  267. }, 16, ["onKeydown"])), [
  268. [unref(ClickOutside), handleClickOutside, triggerRef.value]
  269. ])
  270. ]),
  271. default: withCtx(() => [
  272. createElementVNode("div", mergeProps({
  273. id: unref(buttonId),
  274. ref_key: "triggerRef",
  275. ref: triggerRef
  276. }, _ctx.$attrs, {
  277. class: unref(btnKls),
  278. role: "button",
  279. "aria-label": unref(buttonAriaLabel),
  280. "aria-labelledby": unref(buttonAriaLabelledby),
  281. "aria-description": unref(t)("el.colorpicker.description", { color: _ctx.modelValue || "" }),
  282. "aria-disabled": unref(colorDisabled),
  283. tabindex: unref(colorDisabled) ? void 0 : _ctx.tabindex,
  284. onKeydown: handleKeyDown,
  285. onFocus: unref(handleFocus),
  286. onBlur: unref(handleBlur)
  287. }), [
  288. createElementVNode("div", {
  289. class: normalizeClass(unref(ns).be("picker", "trigger")),
  290. onClick: handleTrigger
  291. }, [
  292. createElementVNode("span", {
  293. class: normalizeClass([unref(ns).be("picker", "color"), unref(ns).is("alpha", _ctx.showAlpha)])
  294. }, [
  295. createElementVNode("span", {
  296. class: normalizeClass(unref(ns).be("picker", "color-inner")),
  297. style: normalizeStyle({
  298. backgroundColor: unref(displayedColor)
  299. })
  300. }, [
  301. withDirectives(createVNode(unref(ElIcon), {
  302. class: normalizeClass([unref(ns).be("picker", "icon"), unref(ns).is("icon-arrow-down")])
  303. }, {
  304. default: withCtx(() => [
  305. createVNode(unref(ArrowDown))
  306. ]),
  307. _: 1
  308. }, 8, ["class"]), [
  309. [vShow, _ctx.modelValue || showPanelColor.value]
  310. ]),
  311. withDirectives(createVNode(unref(ElIcon), {
  312. class: normalizeClass([unref(ns).be("picker", "empty"), unref(ns).is("icon-close")])
  313. }, {
  314. default: withCtx(() => [
  315. createVNode(unref(Close))
  316. ]),
  317. _: 1
  318. }, 8, ["class"]), [
  319. [vShow, !_ctx.modelValue && !showPanelColor.value]
  320. ])
  321. ], 6)
  322. ], 2)
  323. ], 2)
  324. ], 16, ["id", "aria-label", "aria-labelledby", "aria-description", "aria-disabled", "tabindex", "onFocus", "onBlur"])
  325. ]),
  326. _: 1
  327. }, 8, ["visible", "popper-class", "teleported", "transition", "persistent", "append-to", "onHide"]);
  328. };
  329. }
  330. });
  331. var ColorPicker = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "color-picker.vue"]]);
  332. export { ColorPicker as default };
  333. //# sourceMappingURL=color-picker2.mjs.map