winbox-ui-next
Version:
We Design Vue 2.0: A Vue.js 3 UI Library
611 lines (610 loc) • 19.8 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
import { defineComponent, ref, provide, toRef, computed, watch, watchEffect, createVNode, withDirectives, resolveComponent, nextTick } from "vue";
import { clickoutside } from "vdirs";
import { rgba, rgb2hsv, hsla, hsl2hsv, hsva, hsl2rgb, hsv2rgb, rgb2hsl, hsv2hsl, getPreciseEventTarget, toHexString, toHexaString, toRgbaString, toRgbString, toHslaString, toHslString, toHsvaString, toHsvString } from "seemly";
import { useMergedState, useIsMounted } from "vooks";
import { VBinder, VTarget, VFollower } from "vueuc";
import "../_styles/common/dark.js";
import "../_styles/common/light.js";
import colorPickerLight from "../styles/light.js";
import useFormItem from "../_mixins/use-form-item.js";
import useTheme from "../_mixins/use-theme.js";
import useConfig from "../_mixins/use-config.js";
import "@css-render/vue3-ssr";
import { call } from "../_utils/vue/call.js";
import "../_utils/vue/wrapper.js";
import "../_utils/cssr/index.js";
import { useAdjustedTo } from "../_utils/composable/use-adjusted-to.js";
import "../_utils/composable/use-lock-html-scroll.js";
import "../_utils/composable/use-is-composing.js";
import "../_styles/global/index.cssr.js";
import { useThemeClass } from "../_mixins/use-css-vars-class.js";
import "css-render";
import HueSlider from "./HueSlider.js";
import AlphaSlider from "./AlphaSlider.js";
import Pallete from "./Pallete.js";
import ColorInput from "./ColorInput.js";
import ColorPickerTrigger from "./ColorPickerTrigger.js";
import { deriveDefaultValue, getModeFromValue } from "./utils.js";
import ColorPickerSwatches from "./ColorPickerSwatches.js";
import ColorPreview from "./ColorPreview.js";
import { colorPickerInjectionKey } from "./context.js";
import style from "./styles/index.cssr.js";
import { useI18n } from "../../locale/index.js";
import { createKey } from "../_utils/cssr/create-key.js";
const colorPickerProps = __spreadProps(__spreadValues({}, useTheme.props), {
"value": String,
"show": {
type: Boolean,
default: void 0
},
"defaultShow": Boolean,
"defaultValue": String,
"modes": {
type: Array,
default: () => ["rgb", "hex", "hsl"]
},
"placement": {
type: String,
default: "bottom-start"
},
"to": useAdjustedTo.propTo,
"showAlpha": {
type: Boolean,
default: true
},
"showPreview": Boolean,
"swatches": Array,
"disabled": {
type: Boolean,
default: void 0
},
"actions": {
type: Array,
default: null
},
"internalActions": Array,
"size": String,
"renderLabel": Function,
"onComplete": Function,
"onConfirm": Function,
"onUpdate:show": [Function, Array],
"onUpdateShow": [Function, Array],
"onUpdate:value": [Function, Array],
"onUpdateValue": [Function, Array]
});
var _ColorPicker = defineComponent({
name: "ColorPicker",
props: colorPickerProps,
setup(props, {
slots
}) {
const {
t
} = useI18n();
const selfRef = ref(null);
let upcomingValue = null;
const formItem = useFormItem(props);
const {
mergedSizeRef,
mergedDisabledRef
} = formItem;
const {
mergedClsPrefixRef,
namespaceRef,
inlineThemeDisabled
} = useConfig(props);
const themeRef = useTheme("ColorPicker", "-color-picker", style, colorPickerLight, props, mergedClsPrefixRef);
provide(colorPickerInjectionKey, {
themeRef,
renderLabelRef: toRef(props, "renderLabel"),
colorPickerSlots: slots
});
const uncontrolledShowRef = ref(props.defaultShow);
const mergedShowRef = useMergedState(toRef(props, "show"), uncontrolledShowRef);
function doUpdateShow(value) {
const {
onUpdateShow,
"onUpdate:show": _onUpdateShow
} = props;
if (onUpdateShow)
call(onUpdateShow, value);
if (_onUpdateShow)
call(_onUpdateShow, value);
uncontrolledShowRef.value = value;
}
const {
defaultValue
} = props;
const uncontrolledValueRef = ref(defaultValue === void 0 ? deriveDefaultValue(props.modes, props.showAlpha) : defaultValue);
const mergedValueRef = useMergedState(toRef(props, "value"), uncontrolledValueRef);
const undoStackRef = ref([mergedValueRef.value]);
const valueIndexRef = ref(0);
const valueModeRef = computed(() => getModeFromValue(mergedValueRef.value));
const {
modes
} = props;
const displayedModeRef = ref(getModeFromValue(mergedValueRef.value) || modes[0] || "rgb");
function handleUpdateDisplayedMode() {
const {
modes: modes2
} = props;
const {
value: displayedMode
} = displayedModeRef;
const currentModeIndex = modes2.findIndex((mode) => mode === displayedMode);
if (~currentModeIndex) {
displayedModeRef.value = modes2[(currentModeIndex + 1) % modes2.length];
} else {
displayedModeRef.value = "rgb";
}
}
let _h;
let s;
let l;
let v;
let r;
let g;
let b;
let a;
const hsvaRef = computed(() => {
const {
value: mergedValue
} = mergedValueRef;
if (!mergedValue)
return null;
switch (valueModeRef.value) {
case "hsv":
return hsva(mergedValue);
case "hsl":
[_h, s, l, a] = hsla(mergedValue);
return [...hsl2hsv(_h, s, l), a];
case "rgb":
case "hex":
[r, g, b, a] = rgba(mergedValue);
return [...rgb2hsv(r, g, b), a];
}
});
const rgbaRef = computed(() => {
const {
value: mergedValue
} = mergedValueRef;
if (!mergedValue)
return null;
switch (valueModeRef.value) {
case "rgb":
case "hex":
return rgba(mergedValue);
case "hsv":
[_h, s, v, a] = hsva(mergedValue);
return [...hsv2rgb(_h, s, v), a];
case "hsl":
[_h, s, l, a] = hsla(mergedValue);
return [...hsl2rgb(_h, s, l), a];
}
});
const hslaRef = computed(() => {
const {
value: mergedValue
} = mergedValueRef;
if (!mergedValue)
return null;
switch (valueModeRef.value) {
case "hsl":
return hsla(mergedValue);
case "hsv":
[_h, s, v, a] = hsva(mergedValue);
return [...hsv2hsl(_h, s, v), a];
case "rgb":
case "hex":
[r, g, b, a] = rgba(mergedValue);
return [...rgb2hsl(r, g, b), a];
}
});
const mergedValueArrRef = computed(() => {
switch (displayedModeRef.value) {
case "rgb":
case "hex":
return rgbaRef.value;
case "hsv":
return hsvaRef.value;
case "hsl":
return hslaRef.value;
}
});
const displayedHueRef = ref(0);
const displayedAlphaRef = ref(1);
const displayedSvRef = ref([0, 0]);
function handleUpdateSv(s2, v2) {
const {
value: hsvaArr
} = hsvaRef;
const hue = displayedHueRef.value;
const alpha = hsvaArr ? hsvaArr[3] : 1;
displayedSvRef.value = [s2, v2];
const {
showAlpha
} = props;
switch (displayedModeRef.value) {
case "hsv":
doUpdateValue((showAlpha ? toHsvaString : toHsvString)([hue, s2, v2, alpha]), "cursor");
break;
case "hsl":
doUpdateValue((showAlpha ? toHslaString : toHslString)([...hsv2hsl(hue, s2, v2), alpha]), "cursor");
break;
case "rgb":
doUpdateValue((showAlpha ? toRgbaString : toRgbString)([...hsv2rgb(hue, s2, v2), alpha]), "cursor");
break;
case "hex":
doUpdateValue((showAlpha ? toHexaString : toHexString)([...hsv2rgb(hue, s2, v2), alpha]), "cursor");
break;
}
}
function handleUpdateHue(hue) {
displayedHueRef.value = hue;
const {
value: hsvaArr
} = hsvaRef;
if (!hsvaArr) {
return;
}
const [, s2, v2, a2] = hsvaArr;
const {
showAlpha
} = props;
switch (displayedModeRef.value) {
case "hsv":
doUpdateValue((showAlpha ? toHsvaString : toHsvString)([hue, s2, v2, a2]), "cursor");
break;
case "rgb":
doUpdateValue((showAlpha ? toRgbaString : toRgbString)([...hsv2rgb(hue, s2, v2), a2]), "cursor");
break;
case "hex":
doUpdateValue((showAlpha ? toHexaString : toHexString)([...hsv2rgb(hue, s2, v2), a2]), "cursor");
break;
case "hsl":
doUpdateValue((showAlpha ? toHslaString : toHslString)([...hsv2hsl(hue, s2, v2), a2]), "cursor");
break;
}
}
function handleUpdateAlpha(alpha) {
switch (displayedModeRef.value) {
case "hsv":
[_h, s, v] = hsvaRef.value;
doUpdateValue(toHsvaString([_h, s, v, alpha]), "cursor");
break;
case "rgb":
[r, g, b] = rgbaRef.value;
doUpdateValue(toRgbaString([r, g, b, alpha]), "cursor");
break;
case "hex":
[r, g, b] = rgbaRef.value;
doUpdateValue(toHexaString([r, g, b, alpha]), "cursor");
break;
case "hsl":
[_h, s, l] = hslaRef.value;
doUpdateValue(toHslaString([_h, s, l, alpha]), "cursor");
break;
}
displayedAlphaRef.value = alpha;
}
function doUpdateValue(value, updateSource) {
if (updateSource === "cursor") {
upcomingValue = value;
} else {
upcomingValue = null;
}
const {
nTriggerFormChange,
nTriggerFormInput
} = formItem;
const {
onUpdateValue,
"onUpdate:value": _onUpdateValue
} = props;
if (onUpdateValue)
call(onUpdateValue, value);
if (_onUpdateValue)
call(_onUpdateValue, value);
nTriggerFormChange();
nTriggerFormInput();
uncontrolledValueRef.value = value;
}
function handleInputUpdateValue(value) {
doUpdateValue(value, "input");
void nextTick(handleComplete);
}
function handleComplete(pushStack = true) {
const {
value
} = mergedValueRef;
if (value) {
const {
nTriggerFormChange,
nTriggerFormInput
} = formItem;
const {
onComplete
} = props;
if (onComplete) {
onComplete(value);
}
const {
value: undoStack
} = undoStackRef;
const {
value: valueIndex
} = valueIndexRef;
if (pushStack) {
undoStack.splice(valueIndex + 1, undoStack.length, value);
valueIndexRef.value = valueIndex + 1;
}
nTriggerFormChange();
nTriggerFormInput();
}
}
function undo() {
const {
value: valueIndex
} = valueIndexRef;
if (valueIndex - 1 < 0)
return;
doUpdateValue(undoStackRef.value[valueIndex - 1], "input");
handleComplete(false);
valueIndexRef.value = valueIndex - 1;
}
function redo() {
const {
value: valueIndex
} = valueIndexRef;
if (valueIndex < 0 || valueIndex + 1 >= undoStackRef.value.length)
return;
doUpdateValue(undoStackRef.value[valueIndex + 1], "input");
handleComplete(false);
valueIndexRef.value = valueIndex + 1;
}
function handleClear() {
doUpdateValue(null, "input");
doUpdateShow(false);
}
function handleConfirm() {
const {
value
} = mergedValueRef;
const {
onConfirm
} = props;
if (onConfirm) {
onConfirm(value);
}
doUpdateShow(false);
}
const undoableRef = computed(() => valueIndexRef.value >= 1);
const redoableRef = computed(() => {
const {
value: undoStack
} = undoStackRef;
return undoStack.length > 1 && valueIndexRef.value < undoStack.length - 1;
});
watch(mergedShowRef, (value) => {
if (!value) {
undoStackRef.value = [mergedValueRef.value];
valueIndexRef.value = 0;
}
});
watchEffect(() => {
if (upcomingValue && upcomingValue === mergedValueRef.value)
;
else {
const {
value
} = hsvaRef;
if (value) {
displayedHueRef.value = value[0];
displayedAlphaRef.value = value[3];
displayedSvRef.value = [value[1], value[2]];
}
}
upcomingValue = null;
});
const cssVarsRef = computed(() => {
const {
value: mergedSize
} = mergedSizeRef;
const {
common: {
cubicBezierEaseInOut
},
self: {
[createKey("height", mergedSize)]: height
}
} = themeRef.value;
return {
"--n-height": height
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("color-picker", computed(() => {
return mergedSizeRef.value[0];
}), cssVarsRef, props) : void 0;
function renderPanel() {
var _a;
const {
value: rgba2
} = rgbaRef;
const {
value: displayedHue
} = displayedHueRef;
const {
internalActions,
modes: modes2,
actions
} = props;
const {
value: mergedClsPrefix
} = mergedClsPrefixRef;
return createVNode("div", {
"class": [`${mergedClsPrefix}-color-picker-panel`, themeClassHandle == null ? void 0 : themeClassHandle.themeClass.value],
"onDragstart": (e) => {
e.preventDefault();
},
"style": inlineThemeDisabled ? void 0 : cssVarsRef.value
}, [createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-control`
}, [createVNode(Pallete, {
"clsPrefix": mergedClsPrefix,
"rgba": rgba2,
"displayedHue": displayedHue,
"displayedSv": displayedSvRef.value,
"onUpdateSV": handleUpdateSv,
"onComplete": handleComplete
}, null), createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-preview`
}, [createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-preview__sliders`
}, [createVNode(HueSlider, {
"clsPrefix": mergedClsPrefix,
"hue": displayedHue,
"onUpdateHue": handleUpdateHue,
"onComplete": handleComplete
}, null), props.showAlpha ? createVNode(AlphaSlider, {
"clsPrefix": mergedClsPrefix,
"rgba": rgba2,
"alpha": displayedAlphaRef.value,
"onUpdateAlpha": handleUpdateAlpha,
"onComplete": handleComplete
}, null) : null]), props.showPreview ? createVNode(ColorPreview, {
"clsPrefix": mergedClsPrefix,
"mode": displayedModeRef.value,
"color": rgbaRef.value && toHexString(rgbaRef.value),
"onUpdateColor": (color) => doUpdateValue(color, "input")
}, null) : null]), createVNode(ColorInput, {
"clsPrefix": mergedClsPrefix,
"showAlpha": props.showAlpha,
"mode": displayedModeRef.value,
"modes": modes2,
"onUpdateMode": handleUpdateDisplayedMode,
"value": mergedValueRef.value,
"valueArr": mergedValueArrRef.value,
"onUpdateValue": handleInputUpdateValue
}, null), ((_a = props.swatches) == null ? void 0 : _a.length) && createVNode(ColorPickerSwatches, {
"clsPrefix": mergedClsPrefix,
"mode": displayedModeRef.value,
"swatches": props.swatches,
"onUpdateColor": (color) => doUpdateValue(color, "input")
}, null)]), (actions == null ? void 0 : actions.length) ? createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-action`
}, [actions.includes("confirm") && createVNode(resolveComponent("w-button"), {
"size": "medium",
"onClick": handleConfirm
}, {
default: () => t("colorPicker.confirm")
}), actions.includes("clear") && createVNode(resolveComponent("w-button"), {
"size": "medium",
"onClick": handleClear,
"disabled": !mergedValueRef.value
}, {
default: () => t("colorPicker.clear")
})]) : null, slots.action ? createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-action`
}, {
default: slots.action
}) : internalActions ? createVNode("div", {
"class": `${mergedClsPrefix}-color-picker-action`
}, [internalActions.includes("undo") && createVNode(resolveComponent("w-button"), {
"size": "medium",
"onClick": undo,
"disabled": !undoableRef.value
}, {
default: () => t("colorPicker.undo")
}), internalActions.includes("redo") && createVNode(resolveComponent("w-button"), {
"size": "medium",
"onClick": redo,
"disabled": !redoableRef.value
}, {
default: () => t("colorPicker.redo")
})]) : null]);
}
return {
mergedSize: mergedSizeRef,
mergedClsPrefix: mergedClsPrefixRef,
namespace: namespaceRef,
selfRef,
hsla: hslaRef,
rgba: rgbaRef,
mergedShow: mergedShowRef,
mergedDisabled: mergedDisabledRef,
isMounted: useIsMounted(),
adjustedTo: useAdjustedTo(props),
mergedValue: mergedValueRef,
handleTriggerClick() {
doUpdateShow(true);
},
handleClickOutside(e) {
var _a;
if ((_a = selfRef.value) == null ? void 0 : _a.contains(getPreciseEventTarget(e))) {
return;
}
doUpdateShow(false);
},
renderPanel,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle == null ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle == null ? void 0 : themeClassHandle.onRender
};
},
render() {
const {
$slots,
mergedClsPrefix,
onRender,
mergedSize
} = this;
onRender == null ? void 0 : onRender();
return createVNode("div", {
"class": [this.themeClass, `${mergedClsPrefix}-color-picker ${mergedClsPrefix}-color-picker-${mergedSize}`],
"ref": "selfRef",
"style": this.cssVars
}, [createVNode(VBinder, null, {
default: () => [createVNode(VTarget, null, {
default: () => createVNode(ColorPickerTrigger, {
"clsPrefix": mergedClsPrefix,
"value": this.mergedValue,
"hsla": this.hsla,
"disabled": this.mergedDisabled,
"onClick": this.handleTriggerClick
}, {
label: $slots.label
})
}), createVNode(VFollower, {
"placement": this.placement,
"show": this.mergedShow,
"containerClass": this.namespace,
"teleportDisabled": this.adjustedTo === useAdjustedTo.tdkey,
"to": this.adjustedTo
}, {
default: () => this.mergedShow ? withDirectives(this.renderPanel(), [[clickoutside, this.handleClickOutside, void 0, {
capture: true
}]]) : null
})]
})]);
}
});
export { colorPickerProps, _ColorPicker as default };