@sdata/web-vue 3.27.0 → 3.29.0

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 (45) hide show
  1. package/dist/sd.css +5 -1
  2. package/dist/sd.min.css +2 -2
  3. package/es/_utils/grapheme.d.ts +5 -0
  4. package/es/_utils/grapheme.js +93 -0
  5. package/es/basic-crud-table/basic-crud-table.vue_vue_type_script_setup_true_lang.js +40 -25
  6. package/es/basic-crud-table/index.d.ts +1 -1
  7. package/es/basic-crud-table/types.d.ts +9 -1
  8. package/es/components.d.ts +1 -0
  9. package/es/index.css +5 -1
  10. package/es/index.d.ts +3 -0
  11. package/es/index.js +4 -1
  12. package/es/index.scss +1 -0
  13. package/es/input/input.js +5 -6
  14. package/es/input-mask/index.d.ts +120 -0
  15. package/es/input-mask/index.js +12 -0
  16. package/es/input-mask/input-mask.js +5 -0
  17. package/es/input-mask/input-mask.vue.d.ts +49 -0
  18. package/es/input-mask/input-mask.vue_vue_type_script_setup_true_lang.js +346 -0
  19. package/es/input-mask/mask-engine.d.ts +18 -0
  20. package/es/input-mask/mask-engine.js +176 -0
  21. package/es/input-mask/presets.d.ts +2 -0
  22. package/es/input-mask/presets.js +220 -0
  23. package/es/input-mask/style/css.js +1 -0
  24. package/es/input-mask/style/index.css +20 -0
  25. package/es/input-mask/style/index.d.ts +2 -0
  26. package/es/input-mask/style/index.js +1 -0
  27. package/es/input-mask/style/index.scss +10 -0
  28. package/es/input-mask/style/token.scss +5 -0
  29. package/es/input-mask/types.d.ts +49 -0
  30. package/es/sd-vue.js +2 -0
  31. package/es/textarea/textarea.vue_vue_type_script_setup_true_lang.js +5 -6
  32. package/es/toolbar/toolbar.vue_vue_type_script_setup_true_lang.js +8 -10
  33. package/es/toolbar/types.d.ts +3 -0
  34. package/es/upload/context.d.ts +1 -0
  35. package/es/upload/index.d.ts +15 -0
  36. package/es/upload/style/index.css +1 -1
  37. package/es/upload/style/index.scss +1 -1
  38. package/es/upload/upload-picture-item.js +15 -6
  39. package/es/upload/upload-progress.js +17 -13
  40. package/es/upload/upload.d.ts +9 -0
  41. package/es/upload/upload.js +10 -1
  42. package/json/vetur-attributes.json +10 -0
  43. package/json/vetur-tags.json +6 -0
  44. package/json/web-types.json +31 -1
  45. package/package.json +1 -1
@@ -0,0 +1,5 @@
1
+ export declare const splitGraphemes: (value: string) => string[];
2
+ export declare const countGraphemes: (value: string) => number;
3
+ export declare const sliceGraphemes: (value: string, maxLength: number) => string;
4
+ export declare const codeUnitToGraphemeIndex: (value: string, offset: number) => number;
5
+ export declare const graphemeIndexToCodeUnit: (value: string, index: number) => number;
@@ -0,0 +1,93 @@
1
+ //#region components/_utils/grapheme.ts
2
+ /**
3
+ * Grapheme-aware string utilities built on `Intl.Segmenter`.
4
+ *
5
+ * The DOM (`selectionStart`, `value.length`, `setSelectionRange`) counts in
6
+ * UTF-16 code units, while user-perceived characters are grapheme clusters.
7
+ * These helpers convert between the two so that astral characters (CJK
8
+ * Extension B, emoji) and combining sequences are counted and sliced as a
9
+ * single unit. Falls back to code-point iteration when `Intl.Segmenter` is
10
+ * unavailable (older runtimes).
11
+ */
12
+ var segmenter;
13
+ var getSegmenter = () => {
14
+ var _segmenter;
15
+ if (segmenter === null) return void 0;
16
+ if (segmenter) return segmenter;
17
+ if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
18
+ else segmenter = null;
19
+ return (_segmenter = segmenter) !== null && _segmenter !== void 0 ? _segmenter : void 0;
20
+ };
21
+ /** Split a string into its grapheme-cluster segments. */
22
+ var splitGraphemes = (value) => {
23
+ const seg = getSegmenter();
24
+ if (!seg) return Array.from(value);
25
+ const result = [];
26
+ for (const { segment } of seg.segment(value)) result.push(segment);
27
+ return result;
28
+ };
29
+ /** Count user-perceived characters (grapheme clusters). */
30
+ var countGraphemes = (value) => splitGraphemes(value).length;
31
+ /** Keep the first `maxLength` grapheme clusters. */
32
+ var sliceGraphemes = (value, maxLength) => {
33
+ if (maxLength <= 0) return "";
34
+ const seg = getSegmenter();
35
+ if (!seg) return Array.from(value).slice(0, maxLength).join("");
36
+ let count = 0;
37
+ let out = "";
38
+ for (const { segment } of seg.segment(value)) {
39
+ if (count >= maxLength) break;
40
+ out += segment;
41
+ count++;
42
+ }
43
+ return out;
44
+ };
45
+ /**
46
+ * Grapheme index that contains (or is at) the given UTF-16 code-unit offset.
47
+ * Round-trips with {@link graphemeIndexToCodeUnit}.
48
+ */
49
+ var codeUnitToGraphemeIndex = (value, offset) => {
50
+ const seg = getSegmenter();
51
+ if (!seg) {
52
+ let index = 0;
53
+ let acc = 0;
54
+ for (const grapheme of Array.from(value)) {
55
+ if (acc >= offset) break;
56
+ acc += grapheme.length;
57
+ index++;
58
+ }
59
+ return index;
60
+ }
61
+ let index = 0;
62
+ let acc = 0;
63
+ for (const { segment } of seg.segment(value)) {
64
+ if (acc >= offset) break;
65
+ acc += segment.length;
66
+ index++;
67
+ }
68
+ return index;
69
+ };
70
+ /** UTF-16 code-unit offset at the start of the given grapheme index. */
71
+ var graphemeIndexToCodeUnit = (value, index) => {
72
+ const seg = getSegmenter();
73
+ if (!seg) {
74
+ let offset = 0;
75
+ let i = 0;
76
+ for (const grapheme of Array.from(value)) {
77
+ if (i >= index) break;
78
+ offset += grapheme.length;
79
+ i++;
80
+ }
81
+ return offset;
82
+ }
83
+ let offset = 0;
84
+ let i = 0;
85
+ for (const { segment } of seg.segment(value)) {
86
+ if (i >= index) break;
87
+ offset += segment.length;
88
+ i++;
89
+ }
90
+ return offset;
91
+ };
92
+ //#endregion
93
+ export { codeUnitToGraphemeIndex, countGraphemes, graphemeIndexToCodeUnit, sliceGraphemes, splitGraphemes };
@@ -25,6 +25,11 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
25
25
  columns: {},
26
26
  tableProps: { default: () => ({}) },
27
27
  toolbarProps: { default: () => ({}) },
28
+ searchBtn: {},
29
+ resetBtn: {},
30
+ createBtn: {},
31
+ editBtn: { type: [Object, Function] },
32
+ deleteBtn: { type: [Object, Function] },
28
33
  spinProps: {},
29
34
  modalProps: { default: () => ({}) },
30
35
  modalFormProps: { default: () => ({ schemas: [] }) },
@@ -138,6 +143,7 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
138
143
  const toolbarSlotNames = computed(() => getForwardedSlotNames("toolbar__", [
139
144
  "default",
140
145
  "action_prepend",
146
+ "action_middle",
141
147
  "action_append"
142
148
  ]));
143
149
  const tableSlotNames = computed(() => getForwardedSlotNames("table__", ["action_prepend", "action_append"]));
@@ -165,6 +171,9 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
165
171
  function getForwardedSlotNames(prefix, excluded = []) {
166
172
  return Object.keys(slots).filter((name) => name.startsWith(prefix)).map((name) => name.slice(prefix.length)).filter((name) => !excluded.includes(name));
167
173
  }
174
+ function resolveRowLinkProps(value, row) {
175
+ return isFunction(value) ? value(row) : value;
176
+ }
168
177
  function resolvePaginationNumber(controlled, initial, fallback) {
169
178
  const pagination = __props.tableProps.pagination;
170
179
  if (typeof pagination === "object") {
@@ -387,13 +396,10 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
387
396
  !__props.showToolbar && __props.showCreate ? (openBlock(), createElementBlock("div", {
388
397
  key: 0,
389
398
  class: normalizeClass(`${unref(prefixCls)}-header-actions`)
390
- }, [createVNode(unref(Button), {
391
- type: "primary",
392
- onClick: handleCreate
393
- }, {
399
+ }, [createVNode(unref(Button), mergeProps({ type: "primary" }, __props.createBtn, { onClick: handleCreate }), {
394
400
  default: withCtx(() => [..._cache[5] || (_cache[5] = [createTextVNode("新建", -1)])]),
395
401
  _: 1
396
- })], 2)) : createCommentVNode("", true),
402
+ }, 16)], 2)) : createCommentVNode("", true),
397
403
  __props.showToolbar ? (openBlock(), createBlock(unref(Toolbar), mergeProps({
398
404
  key: 1,
399
405
  ref_key: "toolbarRef",
@@ -402,17 +408,22 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
402
408
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => toolbarModel.value = $event)
403
409
  }, __props.toolbarProps, {
404
410
  loading: loading.value,
411
+ "search-btn": __props.searchBtn,
412
+ "reset-btn": __props.resetBtn,
405
413
  onSearch: handleSearch,
406
414
  onReset: handleReset
407
415
  }), createSlots({
408
- "action-append": withCtx(() => [renderSlot(_ctx.$slots, "toolbar__action_append"), __props.showCreate ? (openBlock(), createBlock(unref(Button), {
409
- key: 0,
410
- type: "primary",
411
- onClick: handleCreate
412
- }, {
413
- default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode("新建", -1)])]),
414
- _: 1
415
- })) : createCommentVNode("", true)]),
416
+ "action-append": withCtx(() => [
417
+ renderSlot(_ctx.$slots, "toolbar__action_middle"),
418
+ __props.showCreate ? (openBlock(), createBlock(unref(Button), mergeProps({
419
+ key: 0,
420
+ type: "primary"
421
+ }, __props.createBtn, { onClick: handleCreate }), {
422
+ default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode(" 新建 ", -1)])]),
423
+ _: 1
424
+ }, 16)) : createCommentVNode("", true),
425
+ renderSlot(_ctx.$slots, "toolbar__action_append")
426
+ ]),
416
427
  _: 2
417
428
  }, [
418
429
  _ctx.$slots.toolbar__default ? {
@@ -431,7 +442,12 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
431
442
  fn: withCtx((data) => [renderSlot(_ctx.$slots, `toolbar__${name}`, normalizeProps(guardReactiveProps(data)))])
432
443
  };
433
444
  })
434
- ]), 1040, ["modelValue", "loading"])) : createCommentVNode("", true)
445
+ ]), 1040, [
446
+ "modelValue",
447
+ "loading",
448
+ "search-btn",
449
+ "reset-btn"
450
+ ])) : createCommentVNode("", true)
435
451
  ], 2)) : createCommentVNode("", true),
436
452
  createVNode(unref(Spin), mergeProps(resolvedSpinProps.value, {
437
453
  loading: loading.value,
@@ -449,14 +465,13 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
449
465
  "basic-crud-action": withCtx((data) => [createVNode(unref(Space), null, {
450
466
  default: withCtx(() => [
451
467
  renderSlot(_ctx.$slots, "table__action_prepend", normalizeProps(guardReactiveProps(data))),
452
- __props.showEdit ? (openBlock(), createBlock(unref(Link), {
468
+ __props.showEdit ? (openBlock(), createBlock(unref(Link), mergeProps({
453
469
  key: 0,
454
- ellipsis: false,
455
- onClick: ($event) => handleEdit(data.record, data)
456
- }, {
470
+ ellipsis: false
471
+ }, resolveRowLinkProps(__props.editBtn, data.record), { onClick: ($event) => handleEdit(data.record, data) }), {
457
472
  default: withCtx(() => [..._cache[7] || (_cache[7] = [createTextVNode(" 编辑 ", -1)])]),
458
473
  _: 1
459
- }, 8, ["onClick"])) : createCommentVNode("", true),
474
+ }, 16, ["onClick"])) : createCommentVNode("", true),
460
475
  __props.showDelete ? (openBlock(), createBlock(unref(Popconfirm), {
461
476
  key: 1,
462
477
  content: deleteConfirmContent.value,
@@ -464,15 +479,15 @@ var basic_crud_table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
464
479
  "on-before-ok": handleDeleteConfirm,
465
480
  onPopupVisibleChange: (visible) => handleDeletePopupChange(visible, data.record)
466
481
  }, {
467
- default: withCtx(() => [createVNode(unref(Link), {
482
+ default: withCtx(() => [createVNode(unref(Link), mergeProps({
468
483
  ellipsis: false,
469
484
  status: "danger"
470
- }, {
471
- default: withCtx(() => [..._cache[8] || (_cache[8] = [createTextVNode("删除", -1)])]),
485
+ }, resolveRowLinkProps(__props.deleteBtn, data.record)), {
486
+ default: withCtx(() => [..._cache[8] || (_cache[8] = [createTextVNode(" 删除 ", -1)])]),
472
487
  _: 1
473
- })]),
474
- _: 1
475
- }, 8, ["content", "onPopupVisibleChange"])) : createCommentVNode("", true),
488
+ }, 16)]),
489
+ _: 2
490
+ }, 1032, ["content", "onPopupVisibleChange"])) : createCommentVNode("", true),
476
491
  renderSlot(_ctx.$slots, "table__action_append", normalizeProps(guardReactiveProps(data)))
477
492
  ]),
478
493
  _: 2
@@ -2718,5 +2718,5 @@ declare const BasicCrudTable: {
2718
2718
  install: (app: App, options?: SDOptions) => void;
2719
2719
  };
2720
2720
  export type BasicCrudTableInstance = InstanceType<typeof _BasicCrudTable>;
2721
- export type { BasicCrudTableActionSlotProps, BasicCrudTableDataResult, BasicCrudTableModalFormProps, BasicCrudTableModalProps, BasicCrudTableModalSlotProps, BasicCrudTableModalSubmitContext, BasicCrudTableProps, BasicCrudTableTableProps, BasicCrudTableToolbarProps, InferBasicCrudTableRow, InferBasicCrudTableRowFromValue, MaybePromise, } from './types';
2721
+ export type { BasicCrudTableActionSlotProps, BasicCrudTableDataResult, BasicCrudTableModalFormProps, BasicCrudTableModalProps, BasicCrudTableModalSlotProps, BasicCrudTableModalSubmitContext, BasicCrudTableProps, BasicCrudTableRowLinkProps, BasicCrudTableTableProps, BasicCrudTableToolbarProps, InferBasicCrudTableRow, InferBasicCrudTableRowFromValue, MaybePromise, } from './types';
2722
2722
  export default BasicCrudTable;
@@ -1,5 +1,7 @@
1
1
  import type { UnknownRecord } from 'type-fest';
2
+ import type { ButtonProps } from '../button';
2
3
  import type { JsonFormProps } from '../json-form';
4
+ import type { LinkProps } from '../link';
3
5
  import type ModalComponent from '../modal/modal.vue';
4
6
  import type { SpinProps } from '../spin';
5
7
  import type { TableColumnData, TableData, TableInstance } from '../table';
@@ -12,14 +14,20 @@ export type BasicCrudTableDataResult<TData extends TableData = TableData> = TDat
12
14
  [key: string]: unknown;
13
15
  };
14
16
  export type BasicCrudTableTableProps = Omit<TableInstance['$props'], 'columns' | 'data' | 'onChange' | 'onPageChange' | 'onPageSizeChange'>;
15
- export type BasicCrudTableToolbarProps = Omit<ToolbarProps, 'loading'>;
17
+ export type BasicCrudTableToolbarProps = Omit<ToolbarProps, 'loading' | 'searchBtn' | 'resetBtn'>;
16
18
  export type BasicCrudTableModalProps = Omit<InstanceType<typeof ModalComponent>['$props'], 'visible' | 'title' | 'onBeforeOk' | 'onClose' | 'onUpdate:visible'>;
17
19
  export type BasicCrudTableModalFormProps = Omit<JsonFormProps, 'model'>;
20
+ export type BasicCrudTableRowLinkProps<TRow extends TableData = TableData> = LinkProps | ((row: TRow) => LinkProps);
18
21
  export interface BasicCrudTableProps<TRow extends TableData = TableData> {
19
22
  title?: string;
20
23
  columns: TableColumnData[];
21
24
  tableProps?: BasicCrudTableTableProps;
22
25
  toolbarProps?: BasicCrudTableToolbarProps;
26
+ searchBtn?: ButtonProps;
27
+ resetBtn?: ButtonProps;
28
+ createBtn?: ButtonProps;
29
+ editBtn?: BasicCrudTableRowLinkProps<TRow>;
30
+ deleteBtn?: BasicCrudTableRowLinkProps<TRow>;
23
31
  spinProps?: SpinProps;
24
32
  modalProps?: BasicCrudTableModalProps;
25
33
  modalFormProps?: BasicCrudTableModalFormProps;
@@ -72,6 +72,7 @@ declare module 'vue' {
72
72
  SdInputGroup: SDVue['InputGroup'];
73
73
  SdInputSearch: SDVue['InputSearch'];
74
74
  SdInputPassword: SDVue['InputPassword'];
75
+ SdInputMask: SDVue['InputMask'];
75
76
  SdInputNumber: SDVue['InputNumber'];
76
77
  SdInputTag: SDVue['InputTag'];
77
78
  SdLayout: SDVue['Layout'];
package/es/index.css CHANGED
@@ -3408,7 +3408,7 @@ body {
3408
3408
  }
3409
3409
 
3410
3410
  .sd-upload {
3411
- display: inline-block;
3411
+ display: block;
3412
3412
  max-width: 100%;
3413
3413
  cursor: pointer;
3414
3414
  }
@@ -13423,6 +13423,10 @@ body.sd-tour-active .sd-tour-popover * {
13423
13423
  cursor: pointer;
13424
13424
  }
13425
13425
 
13426
+ .sd-input-mask .sd-input {
13427
+ font-variant-numeric: tabular-nums;
13428
+ }
13429
+
13426
13430
  .sd-image-trigger {
13427
13431
  padding: 6px 4px;
13428
13432
  background: var(--sd-color-bg-5);
package/es/index.d.ts CHANGED
@@ -81,6 +81,9 @@ export { default as Image, ImagePreviewAction, ImagePreview, ImagePreviewGroup }
81
81
  export type { ImageInstance, ImagePreviewActionInstance, ImagePreviewInstance, ImagePreviewGroupInstance, } from './image';
82
82
  export { default as Input, InputGroup, InputPassword, InputSearch } from './input';
83
83
  export type { InputGroupInstance, InputInstance, InputPasswordInstance, InputSearchInstance, } from './input';
84
+ export { default as InputMask } from './input-mask';
85
+ export type { InputMaskBeforeChange, InputMaskInstance, InputMaskPattern, InputMaskPresetDefinition, InputMaskPresetName, InputMaskProps, InputMaskSelection, InputMaskState, InputMaskToken, } from './input-mask';
86
+ export { defaultInputMaskFormatChars, formatInputMask, inputMaskPresets } from './input-mask';
84
87
  export { default as InputNumber } from './input-number';
85
88
  export type { InputNumberChangeHandler, InputNumberFormatter, InputNumberInputHandler, InputNumberInstance, InputNumberParser, InputNumberValue, } from './input-number';
86
89
  export { default as InputTag } from './input-tag';
package/es/index.js CHANGED
@@ -107,6 +107,9 @@ import preview_group_default from "./image/preview-group.js";
107
107
  import Image from "./image/index.js";
108
108
  import FilePreviewer from "./file-previewer/index.js";
109
109
  import Icon from "./icon-component/index.js";
110
+ import { defaultInputMaskFormatChars, formatInputMask } from "./input-mask/mask-engine.js";
111
+ import { inputMaskPresets } from "./input-mask/presets.js";
112
+ import InputMask from "./input-mask/index.js";
110
113
  import KvList from "./kv-list/index.js";
111
114
  import content_default from "./layout/content.js";
112
115
  import footer_default from "./layout/footer.js";
@@ -169,4 +172,4 @@ import Typography from "./typography/index.js";
169
172
  import Upload from "./upload/index.js";
170
173
  import Watermark from "./watermark/index.js";
171
174
  import SDVue from "./sd-vue.js";
172
- export { $createInlineComponentNode, $isInlineComponentNode, A2UI_0_9_1, Affix, Alert, Anchor, anchor_link_default as AnchorLink, AutoComplete, Avatar, AvatarGroup, BackTop, Badge, BasicCrudTable, BorderBeam, Breadcrumb, breadcrumb_item_default as BreadcrumbItem, Button, button_group_default as ButtonGroup, Calendar, Card, card_grid_default as CardGrid, card_meta_default as CardMeta, Carousel, carousel_item_default as CarouselItem, Cascader, cascader_panel_default as CascaderPanel, Checkbox, checkbox_group_default as CheckboxGroup, grid_col_default as Col, Collapse, collapse_item_default as CollapseItem, ColorPicker, Comment, ConfigProvider, Copy, countdown_default as Countdown, Cropper, DEFAULT_LOCALE, DEFAULT_LOCALE_KEY, DatePicker, Descriptions, descriptions_item_default as DescriptionsItem, dropdown_group_default as Dgroup, Divider, dropdown_option_default as Doption, Drawer, Dropdown, dropdown_button_default as DropdownButton, dropdown_submenu_default as Dsubmenu, Ellipsis, Empty, FilePreviewer, Form, form_item_default as FormItem, Grid, grid_item_default as GridItem, Icon, Image, preview_default as ImagePreview, preview_action_default as ImagePreviewAction, preview_group_default as ImagePreviewGroup, InlineComponentNode, Input, input_group_default as InputGroup, InputNumber, input_password_default as InputPassword, input_search_default as InputSearch, InputTag, JsonForm, KvList, Layout, content_default as LayoutContent, footer_default as LayoutFooter, header_default as LayoutHeader, sider_default as LayoutSider, Link, List, list_item_default as ListItem, list_item_meta_default as ListItemMeta, MODEL_SELECTOR_PROVIDERS, Mention, Menu, item_default as MenuItem, item_group_default as MenuItemGroup, Message, Modal, ModelSelector, model_selector_content_default as ModelSelectorContent, model_selector_dialog_default as ModelSelectorDialog, model_selector_empty_default as ModelSelectorEmpty, model_selector_group_default as ModelSelectorGroup, model_selector_input_default as ModelSelectorInput, model_selector_item_default as ModelSelectorItem, model_selector_list_default as ModelSelectorList, model_selector_logo_default as ModelSelectorLogo, model_selector_logo_group_default as ModelSelectorLogoGroup, model_selector_name_default as ModelSelectorName, model_selector_separator_default as ModelSelectorSeparator, model_selector_shortcut_default as ModelSelectorShortcut, model_selector_trigger_default as ModelSelectorTrigger, month_picker_default as MonthPicker, Notification, OverflowList, PageHeader, Pagination, PerformantEllipsis, Popconfirm, Popover, Progress, QrCode, quarter_picker_default as QuarterPicker, RICH_TEXT_EDITOR_BUILT_IN_NODE_NAMES, RICH_TEXT_EDITOR_JSON_FORM_NODE_NAMES, Radio, radio_group_default as RadioGroup, range_picker_default as RangePicker, Rate, recorder_core_default as RecorderCore, ResizeBox, Result, RichTextEditor, grid_row_default as Row, Scrollbar, Secret, Select, SelectableCard, Sender, SenderHeader, SenderSwitch, Skeleton, line_default as SkeletonLine, shape_default as SkeletonShape, Slider, Space, Spin, Split, Statistic, step_default as Step, Steps, sub_menu_default as SubMenu, Switch, tab_pane_default as TabPane, Table, table_column_default as TableColumn, Tabs, Tag, TagGroup, table_tbody_default as Tbody, table_td_default as Td, Textarea, table_th_default as Th, table_thead_default as Thead, ThemeProvider, ThinkingOrb, TimePicker, Timeline, item_default$1 as TimelineItem, Toolbar, Tooltip, Tour, table_tr_default as Tr, Transfer, Tree, TreeSelect, Trigger, Typography, paragraph_default as TypographyParagraph, text_default as TypographyText, title_default as TypographyTitle, Upload, VerificationCode, Watermark, week_picker_default as WeekPicker, year_picker_default as YearPicker, addI18nMessages, SDVue as default, defineJsonFormComponents, defineJsonFormSchemas, getCssVarToken, getLocale, useFormItem, useLocale };
175
+ export { $createInlineComponentNode, $isInlineComponentNode, A2UI_0_9_1, Affix, Alert, Anchor, anchor_link_default as AnchorLink, AutoComplete, Avatar, AvatarGroup, BackTop, Badge, BasicCrudTable, BorderBeam, Breadcrumb, breadcrumb_item_default as BreadcrumbItem, Button, button_group_default as ButtonGroup, Calendar, Card, card_grid_default as CardGrid, card_meta_default as CardMeta, Carousel, carousel_item_default as CarouselItem, Cascader, cascader_panel_default as CascaderPanel, Checkbox, checkbox_group_default as CheckboxGroup, grid_col_default as Col, Collapse, collapse_item_default as CollapseItem, ColorPicker, Comment, ConfigProvider, Copy, countdown_default as Countdown, Cropper, DEFAULT_LOCALE, DEFAULT_LOCALE_KEY, DatePicker, Descriptions, descriptions_item_default as DescriptionsItem, dropdown_group_default as Dgroup, Divider, dropdown_option_default as Doption, Drawer, Dropdown, dropdown_button_default as DropdownButton, dropdown_submenu_default as Dsubmenu, Ellipsis, Empty, FilePreviewer, Form, form_item_default as FormItem, Grid, grid_item_default as GridItem, Icon, Image, preview_default as ImagePreview, preview_action_default as ImagePreviewAction, preview_group_default as ImagePreviewGroup, InlineComponentNode, Input, input_group_default as InputGroup, InputMask, InputNumber, input_password_default as InputPassword, input_search_default as InputSearch, InputTag, JsonForm, KvList, Layout, content_default as LayoutContent, footer_default as LayoutFooter, header_default as LayoutHeader, sider_default as LayoutSider, Link, List, list_item_default as ListItem, list_item_meta_default as ListItemMeta, MODEL_SELECTOR_PROVIDERS, Mention, Menu, item_default as MenuItem, item_group_default as MenuItemGroup, Message, Modal, ModelSelector, model_selector_content_default as ModelSelectorContent, model_selector_dialog_default as ModelSelectorDialog, model_selector_empty_default as ModelSelectorEmpty, model_selector_group_default as ModelSelectorGroup, model_selector_input_default as ModelSelectorInput, model_selector_item_default as ModelSelectorItem, model_selector_list_default as ModelSelectorList, model_selector_logo_default as ModelSelectorLogo, model_selector_logo_group_default as ModelSelectorLogoGroup, model_selector_name_default as ModelSelectorName, model_selector_separator_default as ModelSelectorSeparator, model_selector_shortcut_default as ModelSelectorShortcut, model_selector_trigger_default as ModelSelectorTrigger, month_picker_default as MonthPicker, Notification, OverflowList, PageHeader, Pagination, PerformantEllipsis, Popconfirm, Popover, Progress, QrCode, quarter_picker_default as QuarterPicker, RICH_TEXT_EDITOR_BUILT_IN_NODE_NAMES, RICH_TEXT_EDITOR_JSON_FORM_NODE_NAMES, Radio, radio_group_default as RadioGroup, range_picker_default as RangePicker, Rate, recorder_core_default as RecorderCore, ResizeBox, Result, RichTextEditor, grid_row_default as Row, Scrollbar, Secret, Select, SelectableCard, Sender, SenderHeader, SenderSwitch, Skeleton, line_default as SkeletonLine, shape_default as SkeletonShape, Slider, Space, Spin, Split, Statistic, step_default as Step, Steps, sub_menu_default as SubMenu, Switch, tab_pane_default as TabPane, Table, table_column_default as TableColumn, Tabs, Tag, TagGroup, table_tbody_default as Tbody, table_td_default as Td, Textarea, table_th_default as Th, table_thead_default as Thead, ThemeProvider, ThinkingOrb, TimePicker, Timeline, item_default$1 as TimelineItem, Toolbar, Tooltip, Tour, table_tr_default as Tr, Transfer, Tree, TreeSelect, Trigger, Typography, paragraph_default as TypographyParagraph, text_default as TypographyText, title_default as TypographyTitle, Upload, VerificationCode, Watermark, week_picker_default as WeekPicker, year_picker_default as YearPicker, addI18nMessages, SDVue as default, defaultInputMaskFormatChars, defineJsonFormComponents, defineJsonFormSchemas, formatInputMask, getCssVarToken, getLocale, inputMaskPresets, useFormItem, useLocale };
package/es/index.scss CHANGED
@@ -58,6 +58,7 @@
58
58
  @use '@components/input-tag/style/index.scss' as *;
59
59
  @use '@components/input-number/style/index.scss' as *;
60
60
  @use '@components/input/style/index.scss' as *;
61
+ @use '@components/input-mask/style/index.scss' as *;
61
62
  @use '@components/image/style/index.scss' as *;
62
63
  @use '@components/kv-list/style/index.scss' as *;
63
64
  @use '@components/grid/style/index.scss' as *;
package/es/input/input.js CHANGED
@@ -13,6 +13,7 @@ import { useFitWidth } from "../_hooks/use-fit-width.js";
13
13
  import { isReadonlyModificationKey, useReadonlyTip, useReadonlyTipText } from "../_hooks/use-readonly-tip.js";
14
14
  import { useSize } from "../_hooks/use-size.js";
15
15
  import { INPUT_EVENTS } from "../_utils/constant.js";
16
+ import { countGraphemes, sliceGraphemes } from "../_utils/grapheme.js";
16
17
  import { Enter } from "../_utils/keycode.js";
17
18
  import { omit } from "../_utils/omit.js";
18
19
  import pick from "../_utils/pick.js";
@@ -255,9 +256,8 @@ var input_default = /* @__PURE__ */ defineComponent({
255
256
  target: inputRef
256
257
  });
257
258
  const getValueLength = (value) => {
258
- var _value$length;
259
259
  if (isFunction(props.wordLength)) return props.wordLength(value);
260
- return (_value$length = value.length) !== null && _value$length !== void 0 ? _value$length : 0;
260
+ return countGraphemes(value);
261
261
  };
262
262
  const valueLength = computed(() => getValueLength(computedValue.value));
263
263
  const mergedError = computed(() => _mergedError.value || Boolean(isObject(props.maxLength) && props.maxLength.errorOnly && valueLength.value > maxLength.value));
@@ -271,10 +271,9 @@ var input_default = /* @__PURE__ */ defineComponent({
271
271
  return Math.floor(maxLength.value / bytePerChar);
272
272
  });
273
273
  const updateValue = (value) => {
274
- if (maxLength.value && !maxLengthErrorOnly.value && getValueLength(value) > maxLength.value) {
275
- var _props$wordSlice, _props$wordSlice2;
276
- value = (_props$wordSlice = (_props$wordSlice2 = props.wordSlice) === null || _props$wordSlice2 === void 0 ? void 0 : _props$wordSlice2.call(props, value, maxLength.value)) !== null && _props$wordSlice !== void 0 ? _props$wordSlice : value.slice(0, defaultMaxLength.value);
277
- }
274
+ if (maxLength.value && !maxLengthErrorOnly.value && getValueLength(value) > maxLength.value) if (isFunction(props.wordSlice)) value = props.wordSlice(value, maxLength.value);
275
+ else if (isFunction(props.wordLength)) value = value.slice(0, defaultMaxLength.value);
276
+ else value = sliceGraphemes(value, defaultMaxLength.value);
278
277
  _value.value = value;
279
278
  emit("update:modelValue", value);
280
279
  };
@@ -0,0 +1,120 @@
1
+ import type { App } from 'vue';
2
+ import type { SDOptions } from '../_utils/types';
3
+ import _InputMask from './input-mask.vue';
4
+ declare const InputMask: {
5
+ new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("./types").InputMaskProps> & Readonly<{
6
+ onClear?: ((event: MouseEvent) => any) | undefined;
7
+ onFocus?: ((event: FocusEvent) => any) | undefined;
8
+ onBlur?: ((event: FocusEvent) => any) | undefined;
9
+ onChange?: ((value: string, event: Event) => any) | undefined;
10
+ onInput?: ((value: string, event: Event) => any) | undefined;
11
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
12
+ onPressEnter?: ((event: KeyboardEvent) => any) | undefined;
13
+ onComplete?: ((value: string) => any) | undefined;
14
+ }>, {
15
+ readonly inputRef: HTMLInputElement | undefined;
16
+ focus: () => void | undefined;
17
+ blur: () => void | undefined;
18
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
+ clear: (event: MouseEvent) => any;
20
+ focus: (event: FocusEvent) => any;
21
+ blur: (event: FocusEvent) => any;
22
+ change: (value: string, event: Event) => any;
23
+ input: (value: string, event: Event) => any;
24
+ "update:modelValue": (value: string) => any;
25
+ pressEnter: (event: KeyboardEvent) => any;
26
+ complete: (value: string) => any;
27
+ }, import("vue").PublicProps, {
28
+ disabled: boolean;
29
+ error: boolean;
30
+ readonly: boolean | string;
31
+ defaultValue: string;
32
+ allowClear: boolean;
33
+ fitWidth: boolean;
34
+ maxWFull: boolean;
35
+ showWordLimit: boolean;
36
+ maskChar: string | null;
37
+ alwaysShowMask: boolean;
38
+ }, false, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
39
+ P: {};
40
+ B: {};
41
+ D: {};
42
+ C: {};
43
+ M: {};
44
+ Defaults: {};
45
+ }, Readonly<import("./types").InputMaskProps> & Readonly<{
46
+ onClear?: ((event: MouseEvent) => any) | undefined;
47
+ onFocus?: ((event: FocusEvent) => any) | undefined;
48
+ onBlur?: ((event: FocusEvent) => any) | undefined;
49
+ onChange?: ((value: string, event: Event) => any) | undefined;
50
+ onInput?: ((value: string, event: Event) => any) | undefined;
51
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
52
+ onPressEnter?: ((event: KeyboardEvent) => any) | undefined;
53
+ onComplete?: ((value: string) => any) | undefined;
54
+ }>, {
55
+ readonly inputRef: HTMLInputElement | undefined;
56
+ focus: () => void | undefined;
57
+ blur: () => void | undefined;
58
+ }, {}, {}, {}, {
59
+ disabled: boolean;
60
+ error: boolean;
61
+ readonly: boolean | string;
62
+ defaultValue: string;
63
+ allowClear: boolean;
64
+ fitWidth: boolean;
65
+ maxWFull: boolean;
66
+ showWordLimit: boolean;
67
+ maskChar: string | null;
68
+ alwaysShowMask: boolean;
69
+ }>;
70
+ __isFragment?: never;
71
+ __isTeleport?: never;
72
+ __isSuspense?: never;
73
+ } & import("vue").ComponentOptionsBase<Readonly<import("./types").InputMaskProps> & Readonly<{
74
+ onClear?: ((event: MouseEvent) => any) | undefined;
75
+ onFocus?: ((event: FocusEvent) => any) | undefined;
76
+ onBlur?: ((event: FocusEvent) => any) | undefined;
77
+ onChange?: ((value: string, event: Event) => any) | undefined;
78
+ onInput?: ((value: string, event: Event) => any) | undefined;
79
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
80
+ onPressEnter?: ((event: KeyboardEvent) => any) | undefined;
81
+ onComplete?: ((value: string) => any) | undefined;
82
+ }>, {
83
+ readonly inputRef: HTMLInputElement | undefined;
84
+ focus: () => void | undefined;
85
+ blur: () => void | undefined;
86
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
87
+ clear: (event: MouseEvent) => any;
88
+ focus: (event: FocusEvent) => any;
89
+ blur: (event: FocusEvent) => any;
90
+ change: (value: string, event: Event) => any;
91
+ input: (value: string, event: Event) => any;
92
+ "update:modelValue": (value: string) => any;
93
+ pressEnter: (event: KeyboardEvent) => any;
94
+ complete: (value: string) => any;
95
+ }, string, {
96
+ disabled: boolean;
97
+ error: boolean;
98
+ readonly: boolean | string;
99
+ defaultValue: string;
100
+ allowClear: boolean;
101
+ fitWidth: boolean;
102
+ maxWFull: boolean;
103
+ showWordLimit: boolean;
104
+ maskChar: string | null;
105
+ alwaysShowMask: boolean;
106
+ }, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
107
+ $slots: {
108
+ prefix?: () => unknown;
109
+ suffix?: () => unknown;
110
+ prepend?: () => unknown;
111
+ append?: () => unknown;
112
+ };
113
+ }) & {
114
+ install: (app: App, options?: SDOptions) => void;
115
+ };
116
+ export type InputMaskInstance = InstanceType<typeof _InputMask>;
117
+ export type { InputMaskBeforeChange, InputMaskPattern, InputMaskPresetDefinition, InputMaskPresetName, InputMaskProps, InputMaskSelection, InputMaskState, InputMaskToken, } from './types';
118
+ export { defaultInputMaskFormatChars, formatInputMask } from './mask-engine';
119
+ export { inputMaskPresets } from './presets';
120
+ export default InputMask;
@@ -0,0 +1,12 @@
1
+ import { getComponentPrefix, setGlobalConfig } from "../_utils/global-config.js";
2
+ import { defaultInputMaskFormatChars, formatInputMask } from "./mask-engine.js";
3
+ import { inputMaskPresets } from "./presets.js";
4
+ import input_mask_default from "./input-mask.js";
5
+ //#region components/input-mask/index.ts
6
+ var InputMask = Object.assign(input_mask_default, { install: (app, options) => {
7
+ setGlobalConfig(app, options);
8
+ const componentPrefix = getComponentPrefix(options);
9
+ app.component(componentPrefix + input_mask_default.name, input_mask_default);
10
+ } });
11
+ //#endregion
12
+ export { InputMask as default, defaultInputMaskFormatChars, formatInputMask, inputMaskPresets };
@@ -0,0 +1,5 @@
1
+ import input_mask_vue_vue_type_script_setup_true_lang_default from "./input-mask.vue_vue_type_script_setup_true_lang.js";
2
+ //#region components/input-mask/input-mask.vue
3
+ var input_mask_default = input_mask_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { input_mask_default as default };
@@ -0,0 +1,49 @@
1
+ import type { InputMaskProps } from './types';
2
+ type __VLS_Slots = {
3
+ prefix?: () => unknown;
4
+ suffix?: () => unknown;
5
+ prepend?: () => unknown;
6
+ append?: () => unknown;
7
+ };
8
+ declare const __VLS_base: import("vue").DefineComponent<InputMaskProps, {
9
+ readonly inputRef: HTMLInputElement | undefined;
10
+ focus: () => void | undefined;
11
+ blur: () => void | undefined;
12
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ clear: (event: MouseEvent) => any;
14
+ focus: (event: FocusEvent) => any;
15
+ blur: (event: FocusEvent) => any;
16
+ change: (value: string, event: Event) => any;
17
+ input: (value: string, event: Event) => any;
18
+ "update:modelValue": (value: string) => any;
19
+ pressEnter: (event: KeyboardEvent) => any;
20
+ complete: (value: string) => any;
21
+ }, string, import("vue").PublicProps, Readonly<InputMaskProps> & Readonly<{
22
+ onClear?: ((event: MouseEvent) => any) | undefined;
23
+ onFocus?: ((event: FocusEvent) => any) | undefined;
24
+ onBlur?: ((event: FocusEvent) => any) | undefined;
25
+ onChange?: ((value: string, event: Event) => any) | undefined;
26
+ onInput?: ((value: string, event: Event) => any) | undefined;
27
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
28
+ onPressEnter?: ((event: KeyboardEvent) => any) | undefined;
29
+ onComplete?: ((value: string) => any) | undefined;
30
+ }>, {
31
+ disabled: boolean;
32
+ error: boolean;
33
+ readonly: boolean | string;
34
+ defaultValue: string;
35
+ allowClear: boolean;
36
+ fitWidth: boolean;
37
+ maxWFull: boolean;
38
+ showWordLimit: boolean;
39
+ maskChar: string | null;
40
+ alwaysShowMask: boolean;
41
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
42
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
43
+ declare const _default: typeof __VLS_export;
44
+ export default _default;
45
+ type __VLS_WithSlots<T, S> = T & {
46
+ new (): {
47
+ $slots: S;
48
+ };
49
+ };