feat: initial commit - Phase 1 & 2 core features

This commit is contained in:
hiderfong
2026-04-22 17:07:33 +08:00
commit 1773bda06b
25005 changed files with 6252106 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
import { SFCWithInstall } from "../../utils/vue/typescript.js";
import "../../utils/index.js";
import { RateEmits, RateInstance, RateProps, RatePropsPublic, rateEmits, rateProps } from "./src/rate.js";
import { _default } from "./src/rate.vue.js";
//#region ../../packages/components/rate/index.d.ts
declare const ElRate: SFCWithInstall<typeof _default>;
//#endregion
export { ElRate, ElRate as default, RateEmits, RateInstance, RateProps, RatePropsPublic, rateEmits, rateProps };
+14
View File
@@ -0,0 +1,14 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_install = require('../../utils/vue/install.js');
const require_rate = require('./src/rate.js');
const require_rate$1 = require('./src/rate2.js');
//#region ../../packages/components/rate/index.ts
const ElRate = require_install.withInstall(require_rate$1.default);
//#endregion
exports.ElRate = ElRate;
exports.default = ElRate;
exports.rateEmits = require_rate.rateEmits;
exports.rateProps = require_rate.rateProps;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["withInstall","Rate"],"sources":["../../../../../packages/components/rate/index.ts"],"sourcesContent":["import { withInstall } from '@element-plus/utils'\nimport Rate from './src/rate.vue'\n\nimport type { SFCWithInstall } from '@element-plus/utils'\n\nexport const ElRate: SFCWithInstall<typeof Rate> = withInstall(Rate)\nexport default ElRate\n\nexport * from './src/rate'\n"],"mappings":";;;;;;AAKA,MAAa,SAAsCA,4BAAYC,uBAAK"}
+138
View File
@@ -0,0 +1,138 @@
import { IconPropType } from "../../../utils/vue/icon.js";
import { EpPropFinalized, EpPropMergeType } from "../../../utils/vue/props/types.js";
import { ComponentSize } from "../../../constants/size.js";
import "../../../utils/index.js";
import { _default } from "./rate.vue.js";
import * as vue from "vue";
import { Component, ExtractPublicPropTypes } from "vue";
//#region ../../packages/components/rate/src/rate.d.ts
interface RateProps {
/**
* @description binding value
*/
modelValue?: number;
/**
* @description native `id` attribute
*/
id?: string;
/**
* @description threshold value between low and medium level. The value itself will be included in low level
*/
lowThreshold?: number;
/**
* @description threshold value between medium and high level. The value itself will be included in high level
*/
highThreshold?: number;
/**
* @description max rating score
*/
max?: number;
/**
* @description colors for icons. If array, it should have 3 elements, each of which corresponds with a score level, else if object, the key should be threshold value between two levels, and the value should be corresponding color
*/
colors?: string[] | Record<number, string>;
/**
* @description color of unselected icons
*/
voidColor?: string;
/**
* @description color of unselected read-only icons
*/
disabledVoidColor?: string;
/**
* @description icon components. If array, it should have 3 elements, each of which corresponds with a score level, else if object, the key should be threshold value between two levels, and the value should be corresponding icon component
*/
icons?: Array<IconPropType> | Record<number, IconPropType>;
/**
* @description component of unselected icons
*/
voidIcon?: IconPropType;
/**
* @description component of unselected read-only icons
*/
disabledVoidIcon?: IconPropType;
/**
* @description whether Rate is read-only
*/
disabled?: boolean;
/**
* @description whether picking half start is allowed
*/
allowHalf?: boolean;
/**
* @description whether to display texts
*/
showText?: boolean;
/**
* @description whether to display current score. show-score and show-text cannot be true at the same time
*/
showScore?: boolean;
/**
* @description color of texts
*/
textColor?: string;
/**
* @description text array
*/
texts?: string[];
/**
* @description score template
*/
scoreTemplate?: string;
/**
* @description size of Rate
*/
size?: ComponentSize;
/**
* @description whether value can be reset to `0`
*/
clearable?: boolean;
/**
* @description native `aria-label` attribute
*/
ariaLabel?: string;
}
/**
* @deprecated Removed after 3.0.0, Use `RateProps` instead.
*/
declare const rateProps: {
readonly ariaLabel: StringConstructor;
readonly modelValue: EpPropFinalized<NumberConstructor, unknown, unknown, 0, boolean>;
readonly id: EpPropFinalized<StringConstructor, unknown, unknown, undefined, boolean>;
readonly lowThreshold: EpPropFinalized<NumberConstructor, unknown, unknown, 2, boolean>;
readonly highThreshold: EpPropFinalized<NumberConstructor, unknown, unknown, 4, boolean>;
readonly max: EpPropFinalized<NumberConstructor, unknown, unknown, 5, boolean>;
readonly colors: EpPropFinalized<(new (...args: any[]) => string[] | Record<number, string>) | (() => string[] | Record<number, string>) | (((new (...args: any[]) => string[] | Record<number, string>) | (() => string[] | Record<number, string>)) | null)[], unknown, unknown, () => ["", "", ""], boolean>;
readonly voidColor: EpPropFinalized<StringConstructor, unknown, unknown, "", boolean>;
readonly disabledVoidColor: EpPropFinalized<StringConstructor, unknown, unknown, "", boolean>;
readonly icons: EpPropFinalized<(new (...args: any[]) => (string | Component)[] | Record<number, string | Component>) | (() => (string | Component)[] | Record<number, string | Component>) | (((new (...args: any[]) => (string | Component)[] | Record<number, string | Component>) | (() => (string | Component)[] | Record<number, string | Component>)) | null)[], unknown, unknown, () => [Component, Component, Component], boolean>;
readonly voidIcon: EpPropFinalized<(new (...args: any[]) => (string | Component) & {}) | (() => string | Component) | (((new (...args: any[]) => (string | Component) & {}) | (() => string | Component)) | null)[], unknown, unknown, () => Component, boolean>;
readonly disabledVoidIcon: EpPropFinalized<(new (...args: any[]) => (string | Component) & {}) | (() => string | Component) | (((new (...args: any[]) => (string | Component) & {}) | (() => string | Component)) | null)[], unknown, unknown, () => Component, boolean>;
readonly disabled: EpPropFinalized<BooleanConstructor, unknown, unknown, undefined, boolean>;
readonly allowHalf: BooleanConstructor;
readonly showText: BooleanConstructor;
readonly showScore: BooleanConstructor;
readonly textColor: EpPropFinalized<StringConstructor, unknown, unknown, "", boolean>;
readonly texts: EpPropFinalized<(new (...args: any[]) => string[]) | (() => string[]) | (((new (...args: any[]) => string[]) | (() => string[])) | null)[], unknown, unknown, () => ["Extremely bad", "Disappointed", "Fair", "Satisfied", "Surprise"], boolean>;
readonly scoreTemplate: EpPropFinalized<StringConstructor, unknown, unknown, "{value}", boolean>;
readonly size: {
readonly type: vue.PropType<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", never>>;
readonly required: false;
readonly validator: ((val: unknown) => boolean) | undefined;
__epPropKey: true;
};
readonly clearable: BooleanConstructor;
};
/**
* @deprecated Removed after 3.0.0, Use `RateProps` instead.
*/
type RatePropsPublic = ExtractPublicPropTypes<typeof rateProps>;
declare const rateEmits: {
change: (value: number) => boolean;
"update:modelValue": (value: number) => boolean;
};
type RateEmits = typeof rateEmits;
type RateInstance = InstanceType<typeof _default> & unknown;
//#endregion
export { RateEmits, RateInstance, RateProps, RatePropsPublic, rateEmits, rateProps };
+106
View File
@@ -0,0 +1,106 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_event = require('../../../constants/event.js');
const require_types = require('../../../utils/types.js');
const require_runtime$1 = require('../../../utils/vue/props/runtime.js');
const require_icon = require('../../../utils/vue/icon.js');
const require_typescript = require('../../../utils/typescript.js');
const require_index = require('../../../hooks/use-size/index.js');
const require_index$1 = require('../../../hooks/use-aria/index.js');
let _element_plus_icons_vue = require("@element-plus/icons-vue");
//#region ../../packages/components/rate/src/rate.ts
/**
* @deprecated Removed after 3.0.0, Use `RateProps` instead.
*/
const rateProps = require_runtime$1.buildProps({
modelValue: {
type: Number,
default: 0
},
id: {
type: String,
default: void 0
},
lowThreshold: {
type: Number,
default: 2
},
highThreshold: {
type: Number,
default: 4
},
max: {
type: Number,
default: 5
},
colors: {
type: require_runtime$1.definePropType([Array, Object]),
default: () => require_typescript.mutable([
"",
"",
""
])
},
voidColor: {
type: String,
default: ""
},
disabledVoidColor: {
type: String,
default: ""
},
icons: {
type: require_runtime$1.definePropType([Array, Object]),
default: () => [
_element_plus_icons_vue.StarFilled,
_element_plus_icons_vue.StarFilled,
_element_plus_icons_vue.StarFilled
]
},
voidIcon: {
type: require_icon.iconPropType,
default: () => _element_plus_icons_vue.Star
},
disabledVoidIcon: {
type: require_icon.iconPropType,
default: () => _element_plus_icons_vue.StarFilled
},
disabled: {
type: Boolean,
default: void 0
},
allowHalf: Boolean,
showText: Boolean,
showScore: Boolean,
textColor: {
type: String,
default: ""
},
texts: {
type: require_runtime$1.definePropType(Array),
default: () => require_typescript.mutable([
"Extremely bad",
"Disappointed",
"Fair",
"Satisfied",
"Surprise"
])
},
scoreTemplate: {
type: String,
default: "{value}"
},
size: require_index.useSizeProp,
clearable: Boolean,
...require_index$1.useAriaProps(["ariaLabel"])
});
const rateEmits = {
[require_event.CHANGE_EVENT]: (value) => require_types.isNumber(value),
[require_event.UPDATE_MODEL_EVENT]: (value) => require_types.isNumber(value)
};
//#endregion
exports.rateEmits = rateEmits;
exports.rateProps = rateProps;
//# sourceMappingURL=rate.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
import { IconPropType } from "../../../utils/vue/icon.js";
import "../../../utils/index.js";
import { RateProps } from "./rate.js";
import * as vue from "vue";
//#region ../../packages/components/rate/src/rate.vue.d.ts
declare function setCurrentValue(value: number, event?: MouseEvent): void;
declare function resetCurrentValue(): void;
declare const __VLS_export: vue.DefineComponent<RateProps, {
/** @description set current value */setCurrentValue: typeof setCurrentValue; /** @description reset current value */
resetCurrentValue: typeof resetCurrentValue;
}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
change: (value: number) => void;
"update:modelValue": (value: number) => void;
}, string, vue.PublicProps, Readonly<RateProps> & Readonly<{
onChange?: ((value: number) => any) | undefined;
"onUpdate:modelValue"?: ((value: number) => any) | undefined;
}>, {
id: string;
disabled: boolean;
modelValue: number;
max: number;
textColor: string;
lowThreshold: number;
highThreshold: number;
colors: string[] | Record<number, string>;
voidColor: string;
disabledVoidColor: string;
icons: Array<IconPropType> | Record<number, IconPropType>;
voidIcon: IconPropType;
disabledVoidIcon: IconPropType;
texts: string[];
scoreTemplate: string;
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
declare const _default: typeof __VLS_export;
//#endregion
export { _default };
@@ -0,0 +1,223 @@
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_aria = require('../../../constants/aria.js');
const require_event = require('../../../constants/event.js');
const require_event$1 = require('../../../utils/dom/event.js');
const require_index = require('../../../hooks/use-namespace/index.js');
const require_index$1 = require('../../icon/index.js');
const require_constants = require('../../form/src/constants.js');
const require_use_form_common_props = require('../../form/src/hooks/use-form-common-props.js');
const require_use_form_item = require('../../form/src/hooks/use-form-item.js');
const require_rate = require('./rate.js');
let lodash_unified = require("lodash-unified");
let vue = require("vue");
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/rate/src/rate.vue?vue&type=script&setup=true&lang.ts
const _hoisted_1 = [
"id",
"aria-label",
"aria-labelledby",
"aria-valuenow",
"aria-valuetext",
"aria-valuemax",
"tabindex",
"aria-disabled"
];
const _hoisted_2 = ["onMousemove", "onClick"];
var rate_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
name: "ElRate",
__name: "rate",
props: require_rate.rateProps,
emits: require_rate.rateEmits,
setup(__props, { expose: __expose, emit: __emit }) {
function getValueFromMap(value, map) {
const isExcludedObject = (val) => (0, _vue_shared.isObject)(val);
const matchedValue = map[Object.keys(map).map((key) => +key).filter((key) => {
const val = map[key];
return (isExcludedObject(val) ? val.excluded : false) ? value < key : value <= key;
}).sort((a, b) => a - b)[0]];
return isExcludedObject(matchedValue) && matchedValue.value || matchedValue;
}
const props = __props;
const emit = __emit;
const formItemContext = (0, vue.inject)(require_constants.formItemContextKey, void 0);
const rateSize = require_use_form_common_props.useFormSize();
const ns = require_index.useNamespace("rate");
const { inputId, isLabeledByFormItem } = require_use_form_item.useFormItemInputId(props, { formItemContext });
const currentValue = (0, vue.ref)((0, lodash_unified.clamp)(props.modelValue, 0, props.max));
const hoverIndex = (0, vue.ref)(-1);
const pointerAtLeftHalf = (0, vue.ref)(true);
const iconRefs = (0, vue.ref)([]);
const iconClientWidths = (0, vue.computed)(() => iconRefs.value.map((icon) => icon.$el.clientWidth));
const rateClasses = (0, vue.computed)(() => [ns.b(), ns.m(rateSize.value)]);
const rateDisabled = require_use_form_common_props.useFormDisabled();
const rateStyles = (0, vue.computed)(() => {
return ns.cssVarBlock({
"void-color": props.voidColor,
"disabled-void-color": props.disabledVoidColor,
"fill-color": activeColor.value
});
});
const text = (0, vue.computed)(() => {
let result = "";
if (props.showScore) result = props.scoreTemplate.replace(/\{\s*value\s*\}/, rateDisabled.value ? `${props.modelValue}` : `${currentValue.value}`);
else if (props.showText) result = props.texts[Math.ceil(currentValue.value) - 1];
return result;
});
const valueDecimal = (0, vue.computed)(() => props.modelValue * 100 - Math.floor(props.modelValue) * 100);
const colorMap = (0, vue.computed)(() => (0, _vue_shared.isArray)(props.colors) ? {
[props.lowThreshold]: props.colors[0],
[props.highThreshold]: {
value: props.colors[1],
excluded: true
},
[props.max]: props.colors[2]
} : props.colors);
const activeColor = (0, vue.computed)(() => {
const color = getValueFromMap(currentValue.value, colorMap.value);
return (0, _vue_shared.isObject)(color) ? "" : color;
});
const decimalStyle = (0, vue.computed)(() => {
let width = "";
if (rateDisabled.value) width = `${valueDecimal.value}%`;
else if (props.allowHalf) width = "50%";
return {
color: activeColor.value,
width
};
});
const componentMap = (0, vue.computed)(() => {
let icons = (0, _vue_shared.isArray)(props.icons) ? [...props.icons] : { ...props.icons };
icons = (0, vue.markRaw)(icons);
return (0, _vue_shared.isArray)(icons) ? {
[props.lowThreshold]: icons[0],
[props.highThreshold]: {
value: icons[1],
excluded: true
},
[props.max]: icons[2]
} : icons;
});
const decimalIconComponent = (0, vue.computed)(() => getValueFromMap(props.modelValue, componentMap.value));
const voidComponent = (0, vue.computed)(() => rateDisabled.value ? (0, _vue_shared.isString)(props.disabledVoidIcon) ? props.disabledVoidIcon : (0, vue.markRaw)(props.disabledVoidIcon) : (0, _vue_shared.isString)(props.voidIcon) ? props.voidIcon : (0, vue.markRaw)(props.voidIcon));
const activeComponent = (0, vue.computed)(() => getValueFromMap(currentValue.value, componentMap.value));
function showDecimalIcon(item) {
const showWhenDisabled = rateDisabled.value && valueDecimal.value > 0 && item - 1 < props.modelValue && item > props.modelValue;
const showWhenAllowHalf = props.allowHalf && pointerAtLeftHalf.value && item - .5 <= currentValue.value && item > currentValue.value;
return showWhenDisabled || showWhenAllowHalf;
}
function emitValue(value) {
if (props.clearable && value === props.modelValue) value = 0;
emit(require_event.UPDATE_MODEL_EVENT, value);
if (props.modelValue !== value) emit(require_event.CHANGE_EVENT, value);
}
function selectValue(value) {
if (rateDisabled.value) return;
if (props.allowHalf && pointerAtLeftHalf.value) emitValue(currentValue.value);
else emitValue(value);
}
function handleKey(e) {
if (rateDisabled.value) return;
const code = require_event$1.getEventCode(e);
const step = props.allowHalf ? .5 : 1;
let _currentValue = currentValue.value;
switch (code) {
case require_aria.EVENT_CODE.up:
case require_aria.EVENT_CODE.right:
_currentValue += step;
break;
case require_aria.EVENT_CODE.left:
case require_aria.EVENT_CODE.down:
_currentValue -= step;
break;
}
_currentValue = (0, lodash_unified.clamp)(_currentValue, 0, props.max);
if (_currentValue === currentValue.value) return;
e.stopPropagation();
e.preventDefault();
emit(require_event.UPDATE_MODEL_EVENT, _currentValue);
emit(require_event.CHANGE_EVENT, _currentValue);
return _currentValue;
}
function setCurrentValue(value, event) {
if (rateDisabled.value) return;
if (props.allowHalf && event) {
pointerAtLeftHalf.value = event.offsetX * 2 <= iconClientWidths.value[value - 1];
currentValue.value = pointerAtLeftHalf.value ? value - .5 : value;
} else currentValue.value = value;
hoverIndex.value = value;
}
function resetCurrentValue() {
if (rateDisabled.value) return;
if (props.allowHalf) pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue);
currentValue.value = (0, lodash_unified.clamp)(props.modelValue, 0, props.max);
hoverIndex.value = -1;
}
(0, vue.watch)(() => props.modelValue, (val) => {
currentValue.value = (0, lodash_unified.clamp)(val, 0, props.max);
pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue);
});
if (!props.modelValue) emit(require_event.UPDATE_MODEL_EVENT, 0);
__expose({
setCurrentValue,
resetCurrentValue
});
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
id: (0, vue.unref)(inputId),
class: (0, vue.normalizeClass)([rateClasses.value, (0, vue.unref)(ns).is("disabled", (0, vue.unref)(rateDisabled))]),
role: "slider",
"aria-label": !(0, vue.unref)(isLabeledByFormItem) ? __props.ariaLabel || "rating" : void 0,
"aria-labelledby": (0, vue.unref)(isLabeledByFormItem) ? (0, vue.unref)(formItemContext)?.labelId : void 0,
"aria-valuenow": currentValue.value,
"aria-valuetext": text.value || void 0,
"aria-valuemin": "0",
"aria-valuemax": __props.max,
style: (0, vue.normalizeStyle)(rateStyles.value),
tabindex: (0, vue.unref)(rateDisabled) ? void 0 : 0,
"aria-disabled": (0, vue.unref)(rateDisabled),
onKeydown: handleKey
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.max, (item, key) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
key,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("item")),
onMousemove: ($event) => setCurrentValue(item, $event),
onMouseleave: resetCurrentValue,
onClick: ($event) => selectValue(item)
}, [(0, vue.createVNode)((0, vue.unref)(require_index$1.ElIcon), {
ref_for: true,
ref_key: "iconRefs",
ref: iconRefs,
class: (0, vue.normalizeClass)([
(0, vue.unref)(ns).e("icon"),
{ hover: hoverIndex.value === item },
(0, vue.unref)(ns).is("active", item <= currentValue.value),
(0, vue.unref)(ns).is("focus-visible", item === Math.ceil(currentValue.value || 1))
])
}, {
default: (0, vue.withCtx)(() => [
(0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(activeComponent.value), null, null, 512)), [[vue.vShow, !showDecimalIcon(item) && item <= currentValue.value]]),
(0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(voidComponent.value), null, null, 512)), [[vue.vShow, !showDecimalIcon(item) && item > currentValue.value]]),
(0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(voidComponent.value), { class: (0, vue.normalizeClass)([(0, vue.unref)(ns).em("decimal", "box")]) }, null, 8, ["class"])), [[vue.vShow, showDecimalIcon(item)]]),
(0, vue.withDirectives)((0, vue.createVNode)((0, vue.unref)(require_index$1.ElIcon), {
style: (0, vue.normalizeStyle)(decimalStyle.value),
class: (0, vue.normalizeClass)([(0, vue.unref)(ns).e("icon"), (0, vue.unref)(ns).e("decimal")])
}, {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(decimalIconComponent.value)))]),
_: 1
}, 8, ["style", "class"]), [[vue.vShow, showDecimalIcon(item)]])
]),
_: 2
}, 1032, ["class"])], 42, _hoisted_2);
}), 128)), __props.showText || __props.showScore ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
key: 0,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("text")),
style: (0, vue.normalizeStyle)({ color: __props.textColor })
}, (0, vue.toDisplayString)(text.value), 7)) : (0, vue.createCommentVNode)("v-if", true)], 46, _hoisted_1);
};
}
});
//#endregion
exports.default = rate_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=rate.vue_vue_type_script_setup_true_lang.js.map
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_rate_vue_vue_type_script_setup_true_lang = require('./rate.vue_vue_type_script_setup_true_lang.js');
//#region ../../packages/components/rate/src/rate.vue
var rate_default = require_rate_vue_vue_type_script_setup_true_lang.default;
//#endregion
exports.default = rate_default;
//# sourceMappingURL=rate2.js.map
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/css.js');
require("element-plus/theme-chalk/el-rate.css");
@@ -0,0 +1,3 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/index.js');
require("element-plus/theme-chalk/src/rate.scss");