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
+48
View File
@@ -0,0 +1,48 @@
import { ComponentSize } from "../../constants/size.js";
import { Option } from "./src/types.js";
import { Props, SegmentedEmits, SegmentedInstance, SegmentedProps, SegmentedPropsPublic, defaultProps, segmentedEmits, segmentedProps } from "./src/segmented.js";
import "../../index.js";
import * as vue from "vue";
//#region ../../packages/components/segmented/index.d.ts
declare const ElSegmented: (<T extends Option = Option>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
attrs: any;
emit: ((event: "change", val: any) => void) & ((event: "update:modelValue", val: any) => void);
slots: {
default?: (props: {
item: T;
}) => any;
};
}, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
props: vue.PublicProps & {
direction?: ("vertical" | "horizontal") | undefined;
options?: T[] | undefined;
modelValue?: (string | number | boolean) | undefined;
props?: Props | undefined;
block?: boolean | undefined;
size?: ComponentSize | undefined;
disabled?: boolean | undefined;
validateEvent?: boolean | undefined;
id?: string | undefined;
name?: string | undefined;
ariaLabel?: string | undefined;
onChange?: ((val: any) => any) | undefined;
"onUpdate:modelValue"?: ((val: any) => any) | undefined;
} & (typeof globalThis extends {
__VLS_PROPS_FALLBACK: infer P;
} ? P : {});
expose: (exposed: {}) => void;
attrs: any;
slots: {
default?: (props: {
item: T;
}) => any;
};
emit: ((event: "change", val: any) => void) & ((event: "update:modelValue", val: any) => void);
}>) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}> & {
__ctx?: Awaited<typeof __VLS_setup>;
}) & vue.ObjectPlugin & Record<string, any>;
//#endregion
export { ElSegmented, ElSegmented as default, Props, SegmentedEmits, SegmentedInstance, SegmentedProps, SegmentedPropsPublic, defaultProps, segmentedEmits, segmentedProps };
+15
View File
@@ -0,0 +1,15 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_install = require('../../utils/vue/install.js');
const require_segmented = require('./src/segmented.js');
const require_segmented$1 = require('./src/segmented2.js');
//#region ../../packages/components/segmented/index.ts
const ElSegmented = require_install.withInstall(require_segmented$1.default);
//#endregion
exports.ElSegmented = ElSegmented;
exports.default = ElSegmented;
exports.defaultProps = require_segmented.defaultProps;
exports.segmentedEmits = require_segmented.segmentedEmits;
exports.segmentedProps = require_segmented.segmentedProps;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["withInstall","Segmented"],"sources":["../../../../../packages/components/segmented/index.ts"],"sourcesContent":["import { withInstall } from '@element-plus/utils'\nimport Segmented from './src/segmented.vue'\n\nexport const ElSegmented = withInstall(Segmented)\nexport default ElSegmented\n\nexport * from './src/segmented'\n"],"mappings":";;;;;;AAGA,MAAa,cAAcA,4BAAYC,4BAAU"}
@@ -0,0 +1,92 @@
import { EpPropFinalized, EpPropMergeType } from "../../../utils/vue/props/types.js";
import { ComponentSize } from "../../../constants/size.js";
import "../../../utils/index.js";
import { Option } from "./types.js";
import { _default } from "./segmented.vue.js";
import * as vue from "vue";
import { ComponentInstance, ExtractPublicPropTypes } from "vue";
import { ComponentExposed } from "vue-component-type-helpers";
//#region ../../packages/components/segmented/src/segmented.d.ts
interface Props {
label?: string;
value?: string;
disabled?: string;
}
declare const defaultProps: Required<Props>;
interface SegmentedProps<T extends Option = Option> {
direction?: 'vertical' | 'horizontal';
/**
* @description options of segmented
*/
options?: T[];
/**
* @description binding value
*/
modelValue?: string | number | boolean;
/**
* @description configuration options, see the following table
*/
props?: Props;
/**
* @description fit width of parent content
*/
block?: boolean;
/**
* @description size of component
*/
size?: ComponentSize;
/**
* @description whether segmented is disabled
*/
disabled?: boolean;
/**
* @description whether to trigger form validation
*/
validateEvent?: boolean;
/**
* @description native input id
*/
id?: string;
/**
* @description native `name` attribute
*/
name?: string;
/**
* @description native `aria-label` attribute
*/
ariaLabel?: string;
}
/**
* @deprecated Removed after 3.0.0, Use `SegmentedProps` instead.
*/
declare const segmentedProps: {
ariaLabel: StringConstructor;
direction: EpPropFinalized<(new (...args: any[]) => "horizontal" | "vertical") | (() => "horizontal" | "vertical") | (((new (...args: any[]) => "horizontal" | "vertical") | (() => "horizontal" | "vertical")) | null)[], unknown, unknown, string, boolean>;
options: EpPropFinalized<(new (...args: any[]) => Option[]) | (() => Option[]) | (((new (...args: any[]) => Option[]) | (() => Option[])) | null)[], unknown, unknown, () => never[], boolean>;
modelValue: EpPropFinalized<(BooleanConstructor | NumberConstructor | StringConstructor)[], unknown, unknown, undefined, boolean>;
props: EpPropFinalized<(new (...args: any[]) => Props) | (() => Props) | (((new (...args: any[]) => Props) | (() => Props)) | null)[], unknown, unknown, () => Required<Props>, boolean>;
block: BooleanConstructor;
size: {
readonly type: vue.PropType<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", never>>;
readonly required: false;
readonly validator: ((val: unknown) => boolean) | undefined;
__epPropKey: true;
};
disabled: EpPropFinalized<BooleanConstructor, unknown, unknown, undefined, boolean>;
validateEvent: EpPropFinalized<BooleanConstructor, unknown, unknown, boolean, boolean>;
id: StringConstructor;
name: StringConstructor;
};
/**
* @deprecated Removed after 3.0.0, Use `SegmentedProps` instead.
*/
type SegmentedPropsPublic = ExtractPublicPropTypes<typeof segmentedProps>;
declare const segmentedEmits: {
"update:modelValue": (val: any) => val is string | number | boolean;
change: (val: any) => val is string | number | boolean;
};
type SegmentedEmits = typeof segmentedEmits;
type SegmentedInstance = ComponentInstance<typeof _default> & ComponentExposed<typeof _default>;
//#endregion
export { Props, SegmentedEmits, SegmentedInstance, SegmentedProps, SegmentedPropsPublic, defaultProps, segmentedEmits, segmentedProps };
@@ -0,0 +1,63 @@
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_index = require('../../../hooks/use-size/index.js');
const require_index$1 = require('../../../hooks/use-aria/index.js');
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/segmented/src/segmented.ts
const defaultProps = {
label: "label",
value: "value",
disabled: "disabled"
};
/**
* @deprecated Removed after 3.0.0, Use `SegmentedProps` instead.
*/
const segmentedProps = require_runtime$1.buildProps({
direction: {
type: require_runtime$1.definePropType(String),
default: "horizontal"
},
options: {
type: require_runtime$1.definePropType(Array),
default: () => []
},
modelValue: {
type: [
String,
Number,
Boolean
],
default: void 0
},
props: {
type: require_runtime$1.definePropType(Object),
default: () => defaultProps
},
block: Boolean,
size: require_index.useSizeProp,
disabled: {
type: Boolean,
default: void 0
},
validateEvent: {
type: Boolean,
default: true
},
id: String,
name: String,
...require_index$1.useAriaProps(["ariaLabel"])
});
const segmentedEmits = {
[require_event.UPDATE_MODEL_EVENT]: (val) => (0, _vue_shared.isString)(val) || require_types.isNumber(val) || require_types.isBoolean(val),
[require_event.CHANGE_EVENT]: (val) => (0, _vue_shared.isString)(val) || require_types.isNumber(val) || require_types.isBoolean(val)
};
//#endregion
exports.defaultProps = defaultProps;
exports.segmentedEmits = segmentedEmits;
exports.segmentedProps = segmentedProps;
//# sourceMappingURL=segmented.js.map
@@ -0,0 +1 @@
{"version":3,"file":"segmented.js","names":["buildProps","definePropType","useSizeProp","useAriaProps","UPDATE_MODEL_EVENT","isNumber","isBoolean","CHANGE_EVENT"],"sources":["../../../../../../packages/components/segmented/src/segmented.ts"],"sourcesContent":["import {\n buildProps,\n definePropType,\n isBoolean,\n isNumber,\n isString,\n} from '@element-plus/utils'\nimport { useAriaProps, useSizeProp } from '@element-plus/hooks'\nimport { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants'\n\nimport type { Option } from './types'\nimport type { ComponentInstance, ExtractPublicPropTypes } from 'vue'\nimport type { ComponentExposed } from 'vue-component-type-helpers'\nimport type { ComponentSize } from '@element-plus/constants'\nimport type Segmented from './segmented.vue'\n\nexport interface Props {\n label?: string\n value?: string\n disabled?: string\n}\n\nexport const defaultProps: Required<Props> = {\n label: 'label',\n value: 'value',\n disabled: 'disabled',\n}\n\nexport interface SegmentedProps<T extends Option = Option> {\n direction?: 'vertical' | 'horizontal'\n /**\n * @description options of segmented\n */\n options?: T[]\n /**\n * @description binding value\n */\n modelValue?: string | number | boolean\n /**\n * @description configuration options, see the following table\n */\n props?: Props\n /**\n * @description fit width of parent content\n */\n block?: boolean\n /**\n * @description size of component\n */\n size?: ComponentSize\n /**\n * @description whether segmented is disabled\n */\n disabled?: boolean\n /**\n * @description whether to trigger form validation\n */\n validateEvent?: boolean\n /**\n * @description native input id\n */\n id?: string\n /**\n * @description native `name` attribute\n */\n name?: string\n /**\n * @description native `aria-label` attribute\n */\n ariaLabel?: string\n}\n\n/**\n * @deprecated Removed after 3.0.0, Use `SegmentedProps` instead.\n */\nexport const segmentedProps = buildProps({\n direction: {\n type: definePropType<'vertical' | 'horizontal'>(String),\n default: 'horizontal',\n },\n /**\n * @description options of segmented\n */\n options: {\n type: definePropType<Option[]>(Array),\n default: () => [],\n },\n /**\n * @description binding value\n */\n modelValue: {\n type: [String, Number, Boolean],\n default: undefined,\n },\n /**\n * @description configuration options, see the following table\n */\n props: {\n type: definePropType<Props>(Object),\n default: () => defaultProps,\n },\n /**\n * @description fit width of parent content\n */\n block: Boolean,\n /**\n * @description size of component\n */\n size: useSizeProp,\n /**\n * @description whether segmented is disabled\n */\n disabled: {\n type: Boolean,\n default: undefined,\n },\n /**\n * @description whether to trigger form validation\n */\n validateEvent: {\n type: Boolean,\n default: true,\n },\n /**\n * @description native input id\n */\n id: String,\n /**\n * @description native `name` attribute\n */\n name: String,\n ...useAriaProps(['ariaLabel']),\n})\n\n/**\n * @deprecated Removed after 3.0.0, Use `SegmentedProps` instead.\n */\nexport type SegmentedPropsPublic = ExtractPublicPropTypes<typeof segmentedProps>\n\nexport const segmentedEmits = {\n [UPDATE_MODEL_EVENT]: (val: any) =>\n isString(val) || isNumber(val) || isBoolean(val),\n [CHANGE_EVENT]: (val: any) =>\n isString(val) || isNumber(val) || isBoolean(val),\n}\nexport type SegmentedEmits = typeof segmentedEmits\n\nexport type SegmentedInstance = ComponentInstance<typeof Segmented> &\n ComponentExposed<typeof Segmented>\n"],"mappings":";;;;;;;;;;AAsBA,MAAa,eAAgC;CAC3C,OAAO;CACP,OAAO;CACP,UAAU;CACX;;;;AAiDD,MAAa,iBAAiBA,6BAAW;CACvC,WAAW;EACT,MAAMC,iCAA0C,OAAO;EACvD,SAAS;EACV;CAID,SAAS;EACP,MAAMA,iCAAyB,MAAM;EACrC,eAAe,EAAE;EAClB;CAID,YAAY;EACV,MAAM;GAAC;GAAQ;GAAQ;GAAQ;EAC/B,SAAS;EACV;CAID,OAAO;EACL,MAAMA,iCAAsB,OAAO;EACnC,eAAe;EAChB;CAID,OAAO;CAIP,MAAMC;CAIN,UAAU;EACR,MAAM;EACN,SAAS;EACV;CAID,eAAe;EACb,MAAM;EACN,SAAS;EACV;CAID,IAAI;CAIJ,MAAM;CACN,GAAGC,6BAAa,CAAC,YAAY,CAAC;CAC/B,CAAC;AAOF,MAAa,iBAAiB;EAC3BC,oCAAsB,kCACZ,IAAI,IAAIC,uBAAS,IAAI,IAAIC,wBAAU,IAAI;EACjDC,8BAAgB,kCACN,IAAI,IAAIF,uBAAS,IAAI,IAAIC,wBAAU,IAAI;CACnD"}
@@ -0,0 +1,29 @@
import { Option } from "./types.js";
import { SegmentedProps } from "./segmented.js";
import * as vue from "vue";
//#region ../../packages/components/segmented/src/segmented.vue.d.ts
declare const __VLS_export: <T extends Option = Option>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
props: vue.PublicProps & __VLS_PrettifyLocal<SegmentedProps<T> & {
onChange?: ((val: any) => any) | undefined;
"onUpdate:modelValue"?: ((val: any) => any) | undefined;
}> & (typeof globalThis extends {
__VLS_PROPS_FALLBACK: infer P;
} ? P : {});
expose: (exposed: {}) => void;
attrs: any;
slots: {
default?: (props: {
item: T;
}) => any;
};
emit: ((event: "change", val: any) => void) & ((event: "update:modelValue", val: any) => void);
}>) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}> & {
__ctx?: Awaited<typeof __VLS_setup>;
};
declare const _default: typeof __VLS_export;
type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
//#endregion
export { _default };
@@ -0,0 +1,162 @@
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_event = require('../../../constants/event.js');
const require_error = require('../../../utils/error.js');
const require_index = require('../../../hooks/use-namespace/index.js');
const require_index$1 = require('../../../hooks/use-id/index.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_segmented = require('./segmented.js');
let _vueuse_core = require("@vueuse/core");
let vue = require("vue");
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/segmented/src/segmented.vue?vue&type=script&setup=true&lang.ts
const _hoisted_1 = [
"id",
"aria-label",
"aria-labelledby"
];
const _hoisted_2 = [
"name",
"disabled",
"checked",
"onChange"
];
var segmented_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
name: "ElSegmented",
__name: "segmented",
props: require_segmented.segmentedProps,
emits: require_segmented.segmentedEmits,
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const ns = require_index.useNamespace("segmented");
const segmentedId = require_index$1.useId();
const segmentedSize = require_use_form_common_props.useFormSize();
const _disabled = require_use_form_common_props.useFormDisabled();
const { formItem } = require_use_form_item.useFormItem();
const { inputId, isLabeledByFormItem } = require_use_form_item.useFormItemInputId(props, { formItemContext: formItem });
const segmentedRef = (0, vue.ref)(null);
const activeElement = (0, _vueuse_core.useActiveElement)();
const state = (0, vue.reactive)({
isInit: false,
width: 0,
height: 0,
translateX: 0,
translateY: 0,
focusVisible: false
});
const handleChange = (evt, item) => {
const value = getValue(item);
emit(require_event.UPDATE_MODEL_EVENT, value);
emit(require_event.CHANGE_EVENT, value);
evt.target.checked = value === props.modelValue;
};
const aliasProps = (0, vue.computed)(() => ({
...require_segmented.defaultProps,
...props.props
}));
const getValue = (item) => {
return (0, _vue_shared.isObject)(item) ? item[aliasProps.value.value] : item;
};
const getLabel = (item) => {
return (0, _vue_shared.isObject)(item) ? item[aliasProps.value.label] : item;
};
const getDisabled = (item) => {
return !!(_disabled.value || ((0, _vue_shared.isObject)(item) ? item[aliasProps.value.disabled] : false));
};
const getSelected = (item) => {
return props.modelValue === getValue(item);
};
const getOption = (value) => {
return props.options.find((item) => getValue(item) === value);
};
const getItemCls = (item) => {
return [
ns.e("item"),
ns.is("selected", getSelected(item)),
ns.is("disabled", getDisabled(item))
];
};
const updateSelect = () => {
if (!segmentedRef.value) return;
const selectedItem = segmentedRef.value.querySelector(".is-selected");
const selectedItemInput = segmentedRef.value.querySelector(".is-selected input");
if (!selectedItem || !selectedItemInput) {
state.width = 0;
state.height = 0;
state.translateX = 0;
state.translateY = 0;
state.focusVisible = false;
return;
}
state.isInit = true;
if (props.direction === "vertical") {
state.height = selectedItem.offsetHeight;
state.translateY = selectedItem.offsetTop;
} else {
state.width = selectedItem.offsetWidth;
state.translateX = selectedItem.offsetLeft;
}
try {
state.focusVisible = selectedItemInput.matches(":focus-visible");
} catch {}
};
const segmentedCls = (0, vue.computed)(() => [
ns.b(),
ns.m(segmentedSize.value),
ns.is("block", props.block)
]);
const selectedStyle = (0, vue.computed)(() => ({
width: props.direction === "vertical" ? "100%" : `${state.width}px`,
height: props.direction === "vertical" ? `${state.height}px` : "100%",
transform: props.direction === "vertical" ? `translateY(${state.translateY}px)` : `translateX(${state.translateX}px)`,
display: state.isInit ? "block" : "none"
}));
const selectedCls = (0, vue.computed)(() => [
ns.e("item-selected"),
ns.is("disabled", getDisabled(getOption(props.modelValue))),
ns.is("focus-visible", state.focusVisible)
]);
const name = (0, vue.computed)(() => {
return props.name || segmentedId.value;
});
(0, _vueuse_core.useResizeObserver)(segmentedRef, updateSelect);
(0, vue.watch)(activeElement, updateSelect);
(0, vue.watch)(() => props.modelValue, () => {
updateSelect();
if (props.validateEvent) formItem?.validate?.("change").catch((err) => require_error.debugWarn(err));
}, { flush: "post" });
return (_ctx, _cache) => {
return __props.options.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 0,
id: (0, vue.unref)(inputId),
ref_key: "segmentedRef",
ref: segmentedRef,
class: (0, vue.normalizeClass)(segmentedCls.value),
role: "radiogroup",
"aria-label": !(0, vue.unref)(isLabeledByFormItem) ? __props.ariaLabel || "segmented" : void 0,
"aria-labelledby": (0, vue.unref)(isLabeledByFormItem) ? (0, vue.unref)(formItem).labelId : void 0
}, [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)([(0, vue.unref)(ns).e("group"), (0, vue.unref)(ns).m(__props.direction)]) }, [(0, vue.createElementVNode)("div", {
style: (0, vue.normalizeStyle)(selectedStyle.value),
class: (0, vue.normalizeClass)(selectedCls.value)
}, null, 6), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.options, (item, index) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("label", {
key: index,
class: (0, vue.normalizeClass)(getItemCls(item))
}, [(0, vue.createElementVNode)("input", {
class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("item-input")),
type: "radio",
name: name.value,
disabled: getDisabled(item),
checked: getSelected(item),
onChange: ($event) => handleChange($event, item)
}, null, 42, _hoisted_2), (0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("item-label")) }, [(0, vue.renderSlot)(_ctx.$slots, "default", { item }, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(getLabel(item)), 1)])], 2)], 2);
}), 128))], 2)], 10, _hoisted_1)) : (0, vue.createCommentVNode)("v-if", true);
};
}
});
//#endregion
exports.default = segmented_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=segmented.vue_vue_type_script_setup_true_lang.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_segmented_vue_vue_type_script_setup_true_lang = require('./segmented.vue_vue_type_script_setup_true_lang.js');
//#region ../../packages/components/segmented/src/segmented.vue
var segmented_default = require_segmented_vue_vue_type_script_setup_true_lang.default;
//#endregion
exports.default = segmented_default;
//# sourceMappingURL=segmented2.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
//#region ../../packages/components/segmented/src/types.d.ts
type Option = Record<string, any> | string | number | boolean;
//#endregion
export { Option };
@@ -0,0 +1 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -0,0 +1,3 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/css.js');
require("element-plus/theme-chalk/el-segmented.css");
@@ -0,0 +1,3 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('../../base/style/index.js');
require("element-plus/theme-chalk/src/segmented.scss");