sard-uniapp 1.9.2 → 1.10.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 (43) hide show
  1. package/README.md +39 -1
  2. package/changelog.md +9 -0
  3. package/components/calendar/calendar.d.ts +4 -4
  4. package/components/calendar/calendar.vue +33 -10
  5. package/components/calendar/common.d.ts +4 -3
  6. package/components/calendar-input/calendar-input.d.ts +5 -4
  7. package/components/calendar-input/calendar-input.vue +21 -10
  8. package/components/calendar-input/common.d.ts +4 -2
  9. package/components/cascader-input/cascader-input.vue +1 -1
  10. package/components/checkbox-input/checkbox-input.vue +1 -1
  11. package/components/config/index.d.ts +6 -0
  12. package/components/config/index.js +5 -0
  13. package/components/datetime-picker/common.d.ts +4 -3
  14. package/components/datetime-picker/datetime-picker.d.ts +4 -4
  15. package/components/datetime-picker/datetime-picker.vue +28 -12
  16. package/components/datetime-picker-input/common.d.ts +4 -2
  17. package/components/datetime-picker-input/common.js +1 -0
  18. package/components/datetime-picker-input/datetime-picker-input.d.ts +4 -4
  19. package/components/datetime-picker-input/datetime-picker-input.vue +15 -10
  20. package/components/dialog/common.d.ts +4 -0
  21. package/components/dialog/dialog.vue +6 -1
  22. package/components/dialog-agent/dialog-agent.vue +4 -16
  23. package/components/input/input.vue +11 -3
  24. package/components/picker-input/picker-input.vue +1 -1
  25. package/components/popout-input/popout-input.vue +1 -1
  26. package/components/radio-input/radio-input.vue +1 -1
  27. package/components/space/common.d.ts +20 -0
  28. package/components/space/common.js +7 -0
  29. package/components/space/index.d.ts +1 -0
  30. package/components/space/index.js +1 -0
  31. package/components/space/index.scss +38 -0
  32. package/components/space/space.d.ts +13 -0
  33. package/components/space/space.vue +65 -0
  34. package/components/space/variables.scss +7 -0
  35. package/global.d.ts +2 -1
  36. package/index.d.ts +1 -0
  37. package/index.js +1 -0
  38. package/index.scss +1 -0
  39. package/package.json +2 -2
  40. package/utils/date.d.ts +2 -1
  41. package/utils/date.js +72 -21
  42. package/utils/regexp.d.ts +1 -0
  43. package/utils/regexp.js +3 -0
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
 
22
22
  ## 特性
23
23
 
24
- - 🧩 70+个高质量组件,覆盖移动端主流场景
24
+ - 🧩 74+个高质量组件,覆盖移动端主流场景
25
25
  - 💪 支持一套代码同时开发 H5 / 小程序 / App
26
26
  - 🌿 支持按需引入和 `Tree Shaking`
27
27
  - 📖 详尽的文档和案例展示
@@ -100,3 +100,41 @@ npm run deploy
100
100
  ```bash
101
101
  npm run release
102
102
  ```
103
+
104
+ ## 修复问题流程
105
+
106
+ - 修复问题
107
+ - 测试
108
+ - 修改版本号
109
+ - 暂存
110
+ - 提交
111
+ - 给提交打标签
112
+ - 运行 `npm run buildAndRelease` 打包组件库并发布到 npm
113
+ - 发布到 uniapp 插件市场
114
+ - 运行 `npm run push` 推送代码和标签
115
+ - 运行 `npm run build:site` 打包文档(如果文档有修改)
116
+ - 运行 `npm run deploy` 部署文档(如果文档有修改)
117
+ - 更新 gitee 上的文档(如果文档有修改)
118
+
119
+ ## 新增组件流程
120
+
121
+ - 运行 `npm run newComponent` 命令自动创建组件
122
+ - 编写组件代码
123
+ - 编写案例代码
124
+ - 编写组件文档
125
+ - 编写测试用例
126
+ - 使用实际项目本地安装测试 `pnpm link ../sard-uniapp`
127
+ - 从上面的“修复问题流程”第三部“修改版本号”开始走一遍
128
+
129
+ ## 打包安卓包流程
130
+
131
+ - 在 `HBuilder` 中打开 `sard-uniapp` 项目
132
+ - 点击 发行->App-Android/iOS-云打包
133
+ - 勾选“android(apk 包)” 、“使用云端证书”、“打正式包”、“快速安心打包”
134
+ - 点击“打包“按钮开始打包
135
+ - 注意:如果控制台出现错误:`[ERROR] Cannot start service: Host version "_._._" does not match - binary version "_._._"`,需安装和 Host version 一样版本的 `@esbuild/darwin-x64`
136
+ - 等待云端打包完成
137
+ - 到 `gitee` 仓库创建发行版:[resource 发行版 - Gitee.com](https://gitee.com/sutras/resource/releases/new)
138
+ - 将 gitee 发行版 apk 资源链接转换为二维码图片
139
+ - 将图片更新到 `sard-assets` 项目,并发布到 npm
140
+ - 最后等待 http://fastly.jsdelivr.net 链接生效
package/changelog.md CHANGED
@@ -1,3 +1,12 @@
1
+ # [1.10.0](https://github.com/sutras/sard-uniapp/compare/v1.9.2...v1.10.0) (2025-01-01)
2
+
3
+
4
+ ### Features
5
+
6
+ * 新增 Space 组件, 新增 Dialog 组件的按钮配置, 新增 valueFormat 属性, 修复已知问题 ([7648ea6](https://github.com/sutras/sard-uniapp/commit/7648ea65937c5af9a2b6a8cfa9c5b70ade14ef65))
7
+
8
+
9
+
1
10
  ## [1.9.2](https://github.com/sutras/sard-uniapp/compare/v1.9.1...v1.9.2) (2024-12-22)
2
11
 
3
12
 
@@ -1,10 +1,10 @@
1
1
  import { type CalendarProps } from './common';
2
2
  declare const _default: import("vue").DefineComponent<CalendarProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
3
- "update:model-value": (value: Date | Date[]) => any;
4
- change: (value: Date | Date[]) => any;
3
+ "update:model-value": (value: string | string[] | Date | Date[]) => any;
4
+ change: (value: string | string[] | Date | Date[]) => any;
5
5
  }, string, import("vue").PublicProps, Readonly<CalendarProps> & Readonly<{
6
- "onUpdate:model-value"?: ((value: Date | Date[]) => any) | undefined;
7
- onChange?: ((value: Date | Date[]) => any) | undefined;
6
+ "onUpdate:model-value"?: ((value: string | string[] | Date | Date[]) => any) | undefined;
7
+ onChange?: ((value: string | string[] | Date | Date[]) => any) | undefined;
8
8
  }>, {
9
9
  type: import("./common").CalendarType;
10
10
  maxDays: number;
@@ -88,7 +88,9 @@ import {
88
88
  toMonthNumber,
89
89
  getPrevMonthDate,
90
90
  getNextMonthDate,
91
- toArray
91
+ toArray,
92
+ parseDate,
93
+ formatDate
92
94
  } from "../../utils";
93
95
  import {
94
96
  defaultCalendarProps,
@@ -123,7 +125,7 @@ export default _defineComponent({
123
125
  rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
124
126
  rootClass: { type: String, required: false },
125
127
  type: { type: String, required: false },
126
- modelValue: { type: [Date, Array], required: false },
128
+ modelValue: { type: [Date, Array, String], required: false },
127
129
  min: { type: Date, required: false },
128
130
  max: { type: Date, required: false },
129
131
  currentDate: { type: Date, required: false },
@@ -133,7 +135,8 @@ export default _defineComponent({
133
135
  weekStartsOn: { type: Number, required: false },
134
136
  formatter: { type: Function, required: false },
135
137
  allowSameDay: { type: Boolean, required: false },
136
- severalMonths: { type: Boolean, required: false }
138
+ severalMonths: { type: Boolean, required: false },
139
+ valueFormat: { type: String, required: false }
137
140
  }, defaultCalendarProps),
138
141
  emits: ["update:model-value", "change"],
139
142
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -149,20 +152,34 @@ export default _defineComponent({
149
152
  const maxDate2 = props.max || getMaxDate(props.severalMonths);
150
153
  return maxDate2.getTime() < minDate.value.getTime() ? new Date(minDate.value) : maxDate2;
151
154
  });
155
+ const toDate = (date) => {
156
+ if (date instanceof Date) {
157
+ return date;
158
+ }
159
+ return parseDate(date, props.valueFormat);
160
+ };
161
+ const makeDate = (date) => {
162
+ return Array.isArray(date) ? date.map((item) => toDate(item)) : toDate(date);
163
+ };
164
+ const normalizeValue = (value) => {
165
+ return value ? makeDate(value) : props.type === "single" ? void 0 : [];
166
+ };
152
167
  const innerValue = ref(
153
- props.modelValue ?? (props.type === "single" ? void 0 : [])
168
+ normalizeValue(props.modelValue)
154
169
  );
170
+ let currentEmitValue = innerValue.value;
155
171
  watch(
156
172
  () => props.modelValue,
157
173
  () => {
158
- if (innerValue.value !== props.modelValue) {
159
- innerValue.value = props.modelValue ?? (props.type === "single" ? void 0 : []);
174
+ if (currentEmitValue !== props.modelValue) {
175
+ innerValue.value = normalizeValue(props.modelValue);
176
+ currentEmitValue = props.modelValue;
160
177
  }
161
178
  }
162
179
  );
163
180
  const getInitialCurrentDate = () => {
164
181
  let date = new Date();
165
- const value = toArray(props.modelValue)[0];
182
+ const value = toArray(innerValue.value)[0];
166
183
  if (value) {
167
184
  date = value;
168
185
  }
@@ -286,8 +303,10 @@ export default _defineComponent({
286
303
  }
287
304
  if (nextValue !== void 0) {
288
305
  innerValue.value = nextValue;
289
- emit("update:model-value", nextValue);
290
- emit("change", nextValue);
306
+ const emitValue = props.valueFormat ? Array.isArray(nextValue) ? nextValue.map((item) => formatDate(item, props.valueFormat)) : formatDate(nextValue, props.valueFormat) : nextValue;
307
+ currentEmitValue = emitValue;
308
+ emit("update:model-value", emitValue);
309
+ emit("change", emitValue);
291
310
  }
292
311
  };
293
312
  const inPopup = useInPopup();
@@ -305,7 +324,11 @@ export default _defineComponent({
305
324
  const calendarStyle = computed(() => {
306
325
  return stringifyStyle(props.rootStyle);
307
326
  });
308
- const __returned__ = { props, emit, bem, t, minDate, maxDate, innerValue, getInitialCurrentDate, innerCurrentDate, startDate, onPrevMonthClick, onNextMonthClick, pickerVisible, pickerValue, onMonthClick, onPickerConfirm, weeks, months, todayNumber, currentDates, onDayClick, inPopup, preventPageScroll, calendarClass, calendarStyle, get toMonthNumber() {
327
+ const __returned__ = { props, emit, bem, t, minDate, maxDate, toDate, makeDate, normalizeValue, innerValue, get currentEmitValue() {
328
+ return currentEmitValue;
329
+ }, set currentEmitValue(v) {
330
+ currentEmitValue = v;
331
+ }, getInitialCurrentDate, innerCurrentDate, startDate, onPrevMonthClick, onNextMonthClick, pickerVisible, pickerValue, onMonthClick, onPickerConfirm, weeks, months, todayNumber, currentDates, onDayClick, inPopup, preventPageScroll, calendarClass, calendarStyle, get toMonthNumber() {
309
332
  return toMonthNumber;
310
333
  }, SarButton, SarIcon, SarCalendarMonth, SarPopout, SarDatetimePicker };
311
334
  return __returned__;
@@ -16,7 +16,7 @@ export interface CalendarProps {
16
16
  rootStyle?: StyleValue;
17
17
  rootClass?: string;
18
18
  type?: CalendarType;
19
- modelValue?: Date | Date[];
19
+ modelValue?: Date | Date[] | string | string[];
20
20
  min?: Date;
21
21
  max?: Date;
22
22
  currentDate?: Date;
@@ -27,6 +27,7 @@ export interface CalendarProps {
27
27
  formatter?: (day: CalendarDay) => void;
28
28
  allowSameDay?: boolean;
29
29
  severalMonths?: boolean;
30
+ valueFormat?: string;
30
31
  }
31
32
  export declare const defaultCalendarProps: {
32
33
  type: CalendarProps["type"];
@@ -34,8 +35,8 @@ export declare const defaultCalendarProps: {
34
35
  weekStartsOn: number;
35
36
  };
36
37
  export interface CalendarEmits {
37
- (e: 'update:model-value', value: Date | Date[]): void;
38
- (e: 'change', value: Date | Date[]): void;
38
+ (e: 'update:model-value', value: Date | Date[] | string | string[]): void;
39
+ (e: 'change', value: Date | Date[] | string | string[]): void;
39
40
  }
40
41
  export interface CalendarMonthProps {
41
42
  year: number;
@@ -1,12 +1,12 @@
1
1
  import { type CalendarType } from '../calendar/common';
2
2
  import { type CalendarInputProps } from './common';
3
3
  declare const _default: import("vue").DefineComponent<CalendarInputProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
4
- "update:model-value": (value: Date | Date[] | undefined) => any;
5
- change: (value: Date | Date[] | undefined) => any;
4
+ "update:model-value": (value: string | string[] | Date | Date[] | undefined) => any;
5
+ change: (value: string | string[] | Date | Date[] | undefined) => any;
6
6
  "update:visible": (visible: boolean) => any;
7
7
  }, string, import("vue").PublicProps, Readonly<CalendarInputProps> & Readonly<{
8
- "onUpdate:model-value"?: ((value: Date | Date[] | undefined) => any) | undefined;
9
- onChange?: ((value: Date | Date[] | undefined) => any) | undefined;
8
+ "onUpdate:model-value"?: ((value: string | string[] | Date | Date[] | undefined) => any) | undefined;
9
+ onChange?: ((value: string | string[] | Date | Date[] | undefined) => any) | undefined;
10
10
  "onUpdate:visible"?: ((visible: boolean) => any) | undefined;
11
11
  }>, {
12
12
  type: CalendarType;
@@ -14,5 +14,6 @@ declare const _default: import("vue").DefineComponent<CalendarInputProps, {}, {}
14
14
  maxDays: number;
15
15
  weekStartsOn: number;
16
16
  showConfirm: boolean;
17
+ outletFormat: string;
17
18
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
19
  export default _default;
@@ -23,7 +23,7 @@
23
23
  <sar-calendar
24
24
  v-if="already"
25
25
  :model-value="popoutValue"
26
- @update:model-value="onChange"
26
+ @change="onChange"
27
27
  :type="type"
28
28
  :min="min"
29
29
  :max="max"
@@ -35,6 +35,7 @@
35
35
  :formatter="formatter"
36
36
  :allow-same-day="allowSameDay"
37
37
  :several-months="severalMonths"
38
+ :value-format="valueFormat"
38
39
  />
39
40
  </template>
40
41
  </sar-popout>
@@ -46,13 +47,12 @@ import { ref, watch, computed } from "vue";
46
47
  import SarPopoutInput from "../popout-input/popout-input.vue";
47
48
  import SarCalendar from "../calendar/calendar.vue";
48
49
  import SarPopout from "../popout/popout.vue";
49
- import { formatDate } from "../../utils";
50
+ import { formatDate, isString, parseDate } from "../../utils";
50
51
  import { useTranslate } from "../locale";
51
52
  import {
52
53
  defaultCalendarInputProps
53
54
  } from "./common";
54
55
  import { useFormItemContext } from "../form/common";
55
- const format = "YYYY-MM-DD";
56
56
  export default _defineComponent({
57
57
  components: {
58
58
  SarPopoutInput,
@@ -70,11 +70,12 @@ export default _defineComponent({
70
70
  visible: { type: Boolean, required: false },
71
71
  title: { type: String, required: false },
72
72
  showConfirm: { type: Boolean, required: false },
73
+ outletFormat: { type: String, required: false },
73
74
  validateEvent: { type: Boolean, required: false },
74
75
  rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
75
76
  rootClass: { type: String, required: false },
76
77
  type: { type: String, required: false },
77
- modelValue: { type: [Date, Array], required: false },
78
+ modelValue: { type: [Date, Array, String], required: false },
78
79
  min: { type: Date, required: false },
79
80
  max: { type: Date, required: false },
80
81
  currentDate: { type: Date, required: false },
@@ -85,6 +86,7 @@ export default _defineComponent({
85
86
  formatter: { type: Function, required: false },
86
87
  allowSameDay: { type: Boolean, required: false },
87
88
  severalMonths: { type: Boolean, required: false },
89
+ valueFormat: { type: String, required: false },
88
90
  placeholder: { type: String, required: false },
89
91
  readonly: { type: Boolean, required: false },
90
92
  disabled: { type: Boolean, required: false },
@@ -130,15 +132,23 @@ export default _defineComponent({
130
132
  };
131
133
  const inputValue = ref("");
132
134
  const { t } = useTranslate("calendar");
135
+ function getOutletTextMayByStr(date) {
136
+ if (isString(date) && props.valueFormat) {
137
+ date = parseDate(date, props.valueFormat);
138
+ }
139
+ if (date instanceof Date) {
140
+ return formatDate(date, props.outletFormat);
141
+ }
142
+ return date;
143
+ }
133
144
  function getOutletText(date, type) {
134
145
  if (type === "single") {
135
- return formatDate(date, format);
146
+ return getOutletTextMayByStr(date);
136
147
  }
137
148
  if (type === "range") {
138
- return `${formatDate(date[0], format)} ${t("to")} ${formatDate(
139
- date[1],
140
- format
141
- )}`;
149
+ return `${getOutletTextMayByStr(date[0])} ${t(
150
+ "to"
151
+ )} ${getOutletTextMayByStr(date[1])}`;
142
152
  }
143
153
  if (type === "multiple") {
144
154
  return t("multipleOutlet", {
@@ -166,6 +176,7 @@ export default _defineComponent({
166
176
  inputValue.value = "";
167
177
  innerValue.value = void 0;
168
178
  emit("update:model-value", void 0);
179
+ emit("change", void 0);
169
180
  };
170
181
  const innerVisible = ref(props.visible);
171
182
  watch(
@@ -182,7 +193,7 @@ export default _defineComponent({
182
193
  innerVisible.value = true;
183
194
  emit("update:visible", true);
184
195
  };
185
- const __returned__ = { props, emit, formItemContext, innerValue, popoutValue, confirmDisabled, onChange, onConfirm, inputValue, format, t, getOutletText, getInputValue, onClear, innerVisible, onVisible, onInputClick, SarPopoutInput, SarCalendar, SarPopout };
196
+ const __returned__ = { props, emit, formItemContext, innerValue, popoutValue, confirmDisabled, onChange, onConfirm, inputValue, t, getOutletTextMayByStr, getOutletText, getInputValue, onClear, innerVisible, onVisible, onInputClick, SarPopoutInput, SarCalendar, SarPopout };
186
197
  return __returned__;
187
198
  }
188
199
  });
@@ -4,6 +4,7 @@ export interface CalendarInputProps extends CalendarProps, Omit<PopoutInputProps
4
4
  visible?: boolean;
5
5
  title?: string;
6
6
  showConfirm?: boolean;
7
+ outletFormat?: string;
7
8
  validateEvent?: boolean;
8
9
  }
9
10
  export declare const defaultCalendarInputProps: {
@@ -12,9 +13,10 @@ export declare const defaultCalendarInputProps: {
12
13
  weekStartsOn: number;
13
14
  showConfirm: boolean;
14
15
  validateEvent: boolean;
16
+ outletFormat: string;
15
17
  };
16
18
  export interface CalendarInputEmits {
17
19
  (e: 'update:visible', visible: boolean): void;
18
- (e: 'update:model-value', value: Date | Date[] | undefined): void;
19
- (e: 'change', value: Date | Date[] | undefined): void;
20
+ (e: 'update:model-value', value: Date | Date[] | string | string[] | undefined): void;
21
+ (e: 'change', value: Date | Date[] | string | string[] | undefined): void;
20
22
  }
@@ -23,7 +23,7 @@
23
23
  <sar-cascader
24
24
  v-if="already"
25
25
  :model-value="popoutValue"
26
- @update:model-value="onChange"
26
+ @change="onChange"
27
27
  :options="options"
28
28
  :field-keys="fieldKeys"
29
29
  :placeholder="hintText"
@@ -27,7 +27,7 @@
27
27
  :direction="direction"
28
28
  :validate-event="false"
29
29
  :model-value="popoutValue"
30
- @update:model-value="onChange"
30
+ @change="onChange"
31
31
  >
32
32
  <template #custom="{ toggle }">
33
33
  <sar-list inlaid>
@@ -25,6 +25,7 @@ import { type RadioGroupProps } from '../radio';
25
25
  import { type RadioInputProps } from '../radio-input';
26
26
  import { type ResultProps } from '../result';
27
27
  import { type SearchProps } from '../search';
28
+ import { type SpaceProps } from '../space';
28
29
  import { type StepperProps } from '../stepper';
29
30
  import { type StepsProps } from '../steps';
30
31
  import { type SwiperDotProps } from '../swiper-dot';
@@ -70,6 +71,7 @@ export declare const defaultConfig: {
70
71
  calendarInput: {
71
72
  showConfirm: boolean;
72
73
  validateEvent: boolean;
74
+ outletFormat: string;
73
75
  };
74
76
  cascaderInput: {
75
77
  showConfirm: boolean;
@@ -304,6 +306,10 @@ export declare const defaultConfig: {
304
306
  step: number;
305
307
  validateEvent: boolean;
306
308
  };
309
+ space: {
310
+ direction: SpaceProps["direction"];
311
+ size: SpaceProps["size"];
312
+ };
307
313
  stepper: {
308
314
  min: number;
309
315
  max: number;
@@ -32,6 +32,7 @@ export const defaultConfig = {
32
32
  calendarInput: {
33
33
  showConfirm: true,
34
34
  validateEvent: true,
35
+ outletFormat: 'YYYY-MM-DD',
35
36
  },
36
37
  cascaderInput: {
37
38
  showConfirm: true,
@@ -266,6 +267,10 @@ export const defaultConfig = {
266
267
  step: 1,
267
268
  validateEvent: true,
268
269
  },
270
+ space: {
271
+ direction: 'horizontal',
272
+ size: 'middle',
273
+ },
269
274
  stepper: {
270
275
  min: Number.MIN_SAFE_INTEGER,
271
276
  max: Number.MAX_SAFE_INTEGER,
@@ -5,16 +5,17 @@ export interface DatetimePickerProps {
5
5
  type?: string;
6
6
  min?: Date;
7
7
  max?: Date;
8
- modelValue?: Date;
8
+ modelValue?: Date | string;
9
9
  filter?: (letter: DatetimeLetter, value: number, date: Date, index: number) => boolean;
10
10
  formatter?: (letter: DatetimeLetter, option: DatetimeColumnOption, date: Date, index: number) => string | void | undefined;
11
+ valueFormat?: string;
11
12
  }
12
13
  export declare const defaultDatetimePickerProps: {
13
14
  type: string;
14
15
  };
15
16
  export interface DatetimePickerEmits {
16
- (e: 'update:model-value', date: Date): void;
17
- (e: 'change', date: Date): void;
17
+ (e: 'update:model-value', date: Date | string): void;
18
+ (e: 'change', date: Date | string): void;
18
19
  }
19
20
  export interface DatetimeColumnOption {
20
21
  value: number;
@@ -1,10 +1,10 @@
1
1
  import { type DatetimePickerProps } from './common';
2
2
  declare const _default: import("vue").DefineComponent<DatetimePickerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
3
- "update:model-value": (date: Date) => any;
4
- change: (date: Date) => any;
3
+ "update:model-value": (date: string | Date) => any;
4
+ change: (date: string | Date) => any;
5
5
  }, string, import("vue").PublicProps, Readonly<DatetimePickerProps> & Readonly<{
6
- "onUpdate:model-value"?: ((date: Date) => any) | undefined;
7
- onChange?: ((date: Date) => any) | undefined;
6
+ "onUpdate:model-value"?: ((date: string | Date) => any) | undefined;
7
+ onChange?: ((date: string | Date) => any) | undefined;
8
8
  }>, {
9
9
  type: string;
10
10
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -4,14 +4,14 @@
4
4
  :root-style="stringifyStyle(rootStyle)"
5
5
  :columns="columns"
6
6
  :model-value="pickerValue"
7
- @update:model-value="onChange"
7
+ @change="onChange"
8
8
  />
9
9
  </template>
10
10
 
11
11
  <script>
12
12
  import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
13
13
  import { computed, ref, watch } from "vue";
14
- import { classNames, stringifyStyle } from "../../utils";
14
+ import { classNames, formatDate, parseDate, stringifyStyle } from "../../utils";
15
15
  import SarPicker from "../picker/picker.vue";
16
16
  import {
17
17
  correctDate,
@@ -41,9 +41,10 @@ export default _defineComponent({
41
41
  type: { type: String, required: false },
42
42
  min: { type: Date, required: false },
43
43
  max: { type: Date, required: false },
44
- modelValue: { type: Date, required: false },
44
+ modelValue: { type: [Date, String], required: false },
45
45
  filter: { type: Function, required: false },
46
- formatter: { type: Function, required: false }
46
+ formatter: { type: Function, required: false },
47
+ valueFormat: { type: String, required: false }
47
48
  }, defaultDatetimePickerProps),
48
49
  emits: ["update:model-value", "change"],
49
50
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -109,9 +110,15 @@ export default _defineComponent({
109
110
  const date = new Date(...currEvery);
110
111
  return date;
111
112
  };
113
+ const toDate = (date) => {
114
+ if (date instanceof Date) {
115
+ return date;
116
+ }
117
+ return parseDate(date, props.valueFormat);
118
+ };
112
119
  const normalizeValue = (value) => {
113
- value = value ?? new Date();
114
- return value.getTime() < minDate.value.getTime() ? minDate.value : value.getTime() > maxDate.value.getTime() ? maxDate.value : value;
120
+ const date = value ? toDate(value) : new Date();
121
+ return date.getTime() < minDate.value.getTime() ? minDate.value : date.getTime() > maxDate.value.getTime() ? maxDate.value : date;
115
122
  };
116
123
  const innerType = computed(() => {
117
124
  return props.type.split("");
@@ -122,12 +129,15 @@ export default _defineComponent({
122
129
  return maxDate2 < minDate.value ? new Date(minDate.value) : maxDate2;
123
130
  });
124
131
  const innerValue = ref(normalizeValue(props.modelValue));
132
+ let currentEmitValue = innerValue.value;
125
133
  watch(
126
134
  () => props.modelValue,
127
135
  () => {
128
- innerValue.value = normalizeValue(props.modelValue);
129
- if (props.modelValue) {
130
- updateColumns(props.modelValue);
136
+ if (currentEmitValue !== props.modelValue) {
137
+ innerValue.value = normalizeValue(props.modelValue);
138
+ if (props.modelValue) {
139
+ updateColumns(innerValue.value);
140
+ }
131
141
  }
132
142
  }
133
143
  );
@@ -143,11 +153,17 @@ export default _defineComponent({
143
153
  const onChange = (value) => {
144
154
  const nextValue = getDateByPickerValue(value);
145
155
  innerValue.value = nextValue;
156
+ const emitValue = props.valueFormat ? formatDate(nextValue, props.valueFormat) : nextValue;
157
+ currentEmitValue = emitValue;
146
158
  updateColumns(nextValue);
147
- emit("update:model-value", nextValue);
148
- emit("change", nextValue);
159
+ emit("update:model-value", emitValue);
160
+ emit("change", emitValue);
149
161
  };
150
- const __returned__ = { props, emit, t, createColumnData, getChangedLetter, updateColumns, getDateByPickerValue, normalizeValue, innerType, minDate, maxDate, innerValue, pickerValue, columnsMap, get minValues() {
162
+ const __returned__ = { props, emit, t, createColumnData, getChangedLetter, updateColumns, getDateByPickerValue, toDate, normalizeValue, innerType, minDate, maxDate, innerValue, get currentEmitValue() {
163
+ return currentEmitValue;
164
+ }, set currentEmitValue(v) {
165
+ currentEmitValue = v;
166
+ }, pickerValue, columnsMap, get minValues() {
151
167
  return minValues;
152
168
  }, set minValues(v) {
153
169
  minValues = v;
@@ -4,6 +4,7 @@ export interface DatetimePickerInputProps extends DatetimePickerProps, Omit<Popo
4
4
  visible?: boolean;
5
5
  title?: string;
6
6
  outletFormat?: string;
7
+ valueFormat?: string;
7
8
  validateEvent?: boolean;
8
9
  }
9
10
  export declare const defaultDatetimePickerInputProps: {
@@ -12,13 +13,14 @@ export declare const defaultDatetimePickerInputProps: {
12
13
  };
13
14
  export interface DatetimePickerInputEmits {
14
15
  (e: 'update:visible', visible: boolean): void;
15
- (e: 'update:model-value', date: Date | undefined): void;
16
- (e: 'change', date: Date | undefined): void;
16
+ (e: 'update:model-value', date: Date | string | undefined): void;
17
+ (e: 'change', date: Date | string | undefined): void;
17
18
  }
18
19
  export declare const mapTypeFormat: {
19
20
  y: string;
20
21
  yM: string;
21
22
  yMd: string;
23
+ yMdh: string;
22
24
  yMdhm: string;
23
25
  yMdhms: string;
24
26
  hm: string;
@@ -7,6 +7,7 @@ export const mapTypeFormat = {
7
7
  y: 'YYYY',
8
8
  yM: 'YYYY-MM',
9
9
  yMd: 'YYYY-MM-DD',
10
+ yMdh: 'YYYY-MM-DD HH',
10
11
  yMdhm: 'YYYY-MM-DD HH:mm',
11
12
  yMdhms: 'YYYY-MM-DD HH:mm:ss',
12
13
  hm: 'HH:mm',
@@ -1,11 +1,11 @@
1
1
  import { type DatetimePickerInputProps } from './common';
2
2
  declare const _default: import("vue").DefineComponent<DatetimePickerInputProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
3
- "update:model-value": (date: Date | undefined) => any;
4
- change: (date: Date | undefined) => any;
3
+ "update:model-value": (date: string | Date | undefined) => any;
4
+ change: (date: string | Date | undefined) => any;
5
5
  "update:visible": (visible: boolean) => any;
6
6
  }, string, import("vue").PublicProps, Readonly<DatetimePickerInputProps> & Readonly<{
7
- "onUpdate:model-value"?: ((date: Date | undefined) => any) | undefined;
8
- onChange?: ((date: Date | undefined) => any) | undefined;
7
+ "onUpdate:model-value"?: ((date: string | Date | undefined) => any) | undefined;
8
+ onChange?: ((date: string | Date | undefined) => any) | undefined;
9
9
  "onUpdate:visible"?: ((visible: boolean) => any) | undefined;
10
10
  }>, {
11
11
  type: string;
@@ -22,12 +22,13 @@
22
22
  <sar-datetime-picker
23
23
  v-if="already"
24
24
  :model-value="popoutValue"
25
- @update:model-value="onChange"
25
+ @change="onChange"
26
26
  :type="type"
27
27
  :min="min"
28
28
  :max="max"
29
29
  :filter="filter"
30
30
  :formatter="formatter"
31
+ :value-format="valueFormat"
31
32
  />
32
33
  </template>
33
34
  </sar-popout>
@@ -39,7 +40,7 @@ import { ref, watch, computed } from "vue";
39
40
  import SarPopoutInput from "../popout-input/popout-input.vue";
40
41
  import SarPopout from "../popout/popout.vue";
41
42
  import SarDatetimePicker from "../datetime-picker/datetime-picker.vue";
42
- import { formatDate, isNullish } from "../../utils";
43
+ import { formatDate, isNullish, isString, parseDate } from "../../utils";
43
44
  import {
44
45
  getInitialValue,
45
46
  getMinDate,
@@ -67,13 +68,14 @@ export default _defineComponent({
67
68
  visible: { type: Boolean, required: false },
68
69
  title: { type: String, required: false },
69
70
  outletFormat: { type: String, required: false },
71
+ valueFormat: { type: String, required: false },
70
72
  validateEvent: { type: Boolean, required: false },
71
73
  rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
72
74
  rootClass: { type: String, required: false },
73
75
  type: { type: String, required: false },
74
76
  min: { type: Date, required: false },
75
77
  max: { type: Date, required: false },
76
- modelValue: { type: Date, required: false },
78
+ modelValue: { type: [Date, String], required: false },
77
79
  filter: { type: Function, required: false },
78
80
  formatter: { type: Function, required: false },
79
81
  placeholder: { type: String, required: false },
@@ -123,16 +125,19 @@ export default _defineComponent({
123
125
  };
124
126
  const inputValue = ref("");
125
127
  function getOutletText(value) {
126
- if (!value) {
127
- return "";
128
+ if (isString(value) && props.valueFormat) {
129
+ value = parseDate(value, props.valueFormat);
130
+ }
131
+ if (value instanceof Date) {
132
+ return formatDate(
133
+ value,
134
+ props.outletFormat || mapTypeFormat[props.type]
135
+ );
128
136
  }
129
- return formatDate(
130
- value,
131
- props.outletFormat || mapTypeFormat[props.type]
132
- );
137
+ return value;
133
138
  }
134
139
  function getInputValue() {
135
- if (isNullish(innerValue.value)) {
140
+ if (!innerValue.value) {
136
141
  return "";
137
142
  }
138
143
  return getOutletText(innerValue.value);
@@ -1,5 +1,6 @@
1
1
  import { type StyleValue } from 'vue';
2
2
  import { type TransitionHookName } from '../../use';
3
+ import { type ButtonProps } from '../button';
3
4
  export interface DialogProps {
4
5
  rootStyle?: StyleValue;
5
6
  rootClass?: string;
@@ -15,6 +16,9 @@ export interface DialogProps {
15
16
  overlayClosable?: boolean;
16
17
  beforeClose?: (type: 'close' | 'cancel' | 'confirm') => any | Promise<any>;
17
18
  duration?: number;
19
+ cancelProps?: ButtonProps;
20
+ confirmProps?: ButtonProps;
21
+ id?: string;
18
22
  }
19
23
  export declare const defaultDialogProps: {
20
24
  headed: boolean;
@@ -43,6 +43,7 @@
43
43
  :theme="buttonProps.cancel.theme"
44
44
  :size="buttonProps.cancel.size"
45
45
  :round="buttonProps.confirm.round"
46
+ v-bind="cancelProps"
46
47
  @click="onCancel"
47
48
  >
48
49
  {{ cancelText || t('cancel') }}
@@ -59,6 +60,7 @@
59
60
  :theme="buttonProps.confirm.theme"
60
61
  :size="buttonProps.confirm.size"
61
62
  :round="buttonProps.confirm.round"
63
+ v-bind="confirmProps"
62
64
  @click="onConfirm"
63
65
  >
64
66
  {{ confirmText || t('confirm') }}
@@ -106,7 +108,10 @@ export default _defineComponent({
106
108
  confirmText: { type: String, required: false },
107
109
  overlayClosable: { type: Boolean, required: false },
108
110
  beforeClose: { type: Function, required: false },
109
- duration: { type: Number, required: false }
111
+ duration: { type: Number, required: false },
112
+ cancelProps: { type: Object, required: false },
113
+ confirmProps: { type: Object, required: false },
114
+ id: { type: String, required: false }
110
115
  }, defaultDialogProps),
111
116
  emits: ["update:visible", "close", "cancel", "confirm", "visible-hook"],
112
117
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -1,19 +1,5 @@
1
1
  <template>
2
- <sar-dialog
3
- :root-style="innerProps.rootStyle"
4
- :root-class="innerProps.rootClass"
5
- v-model:visible="innerProps.visible"
6
- :title="innerProps.title"
7
- :message="innerProps.message"
8
- :headed="innerProps.headed"
9
- :button-type="innerProps.buttonType"
10
- :show-cancel="innerProps.showCancel"
11
- :cancel-text="innerProps.cancelText"
12
- :show-confirm="innerProps.showConfirm"
13
- :confirm-text="innerProps.confirmText"
14
- :overlay-closable="innerProps.overlayClosable"
15
- :before-close="innerProps.beforeClose"
16
- />
2
+ <sar-dialog v-bind="innerProps" v-model:visible="innerProps.visible" />
17
3
  </template>
18
4
 
19
5
  <script>
@@ -51,7 +37,9 @@ export default _defineComponent({
51
37
  confirmText: { type: String, required: false },
52
38
  overlayClosable: { type: Boolean, required: false },
53
39
  beforeClose: { type: Function, required: false },
54
- duration: { type: Number, required: false }
40
+ duration: { type: Number, required: false },
41
+ cancelProps: { type: Object, required: false },
42
+ confirmProps: { type: Object, required: false }
55
43
  }, defaultDialogAgentProps),
56
44
  setup(__props, { expose: __expose }) {
57
45
  __expose();
@@ -14,7 +14,7 @@
14
14
  placeholderClass,
15
15
  )
16
16
  "
17
- :style="placeholderStyle"
17
+ :style="mergedPlaceholderStyle"
18
18
  >
19
19
  {{ placeholder }}
20
20
  </view>
@@ -60,7 +60,7 @@
60
60
  :class="classNames(bem.e('control'), bem.em('control', 'input'))"
61
61
  :value="innerValue"
62
62
  :placeholder="placeholder"
63
- :placeholder-style="placeholderStyle"
63
+ :placeholder-style="mergedPlaceholderStyle"
64
64
  :placeholder-class="classNames(bem.e('placeholder'), placeholderClass)"
65
65
  :disabled="isDisabled || isReadonly"
66
66
  :maxlength="maxlength"
@@ -295,11 +295,19 @@ export default _defineComponent({
295
295
  height: !props.autoHeight && props.minHeight
296
296
  });
297
297
  });
298
+ const mergedPlaceholderStyle = computed(() => {
299
+ return stringifyStyle(
300
+ {
301
+ color: "var(--sar-input-placeholder-color)"
302
+ },
303
+ props.placeholderStyle
304
+ );
305
+ });
298
306
  const __returned__ = { props, emit, bem, formContext, formItemContext, isDisabled, isReadonly, innerValue, setInnerValue, onInput, innerFocused, get oldValue() {
299
307
  return oldValue;
300
308
  }, set oldValue(v) {
301
309
  oldValue = v;
302
- }, onFocus, onBlur, clearVisible, holdupClear, onClearTouchStart, onClearTouchEnd, onClearMouseDown, onClearClick, onLinechange, onConfirm, onKeyboardheightchange, inputClass, inputStyle, controlStyle, get classNames() {
310
+ }, onFocus, onBlur, clearVisible, holdupClear, onClearTouchStart, onClearTouchEnd, onClearMouseDown, onClearClick, onLinechange, onConfirm, onKeyboardheightchange, inputClass, inputStyle, controlStyle, mergedPlaceholderStyle, get classNames() {
303
311
  return classNames;
304
312
  }, SarIcon };
305
313
  return __returned__;
@@ -22,7 +22,7 @@
22
22
  <sar-picker
23
23
  v-if="already"
24
24
  :model-value="popoutValue"
25
- @update:model-value="onChange"
25
+ @change="onChange"
26
26
  :columns="columns"
27
27
  :option-keys="optionKeys"
28
28
  :immediate-change="immediateChange"
@@ -3,7 +3,7 @@
3
3
  <sar-input
4
4
  inlaid
5
5
  :model-value="innerValue"
6
- @update:model-value="onChange"
6
+ @change="onChange"
7
7
  :placeholder="placeholder"
8
8
  :readonly="isReadonly"
9
9
  :disabled="isDisabled"
@@ -27,7 +27,7 @@
27
27
  :direction="direction"
28
28
  :validate-event="false"
29
29
  :model-value="popoutValue"
30
- @update:model-value="onChange"
30
+ @change="onChange"
31
31
  >
32
32
  <template #custom="{ toggle }">
33
33
  <sar-list inlaid>
@@ -0,0 +1,20 @@
1
+ import { type StyleValue } from 'vue';
2
+ export type SpaceSize = 'small' | 'middle' | 'large';
3
+ export type SpaceAlign = 'start' | 'end' | 'center' | 'baseline';
4
+ export interface SpaceProps {
5
+ rootStyle?: StyleValue;
6
+ rootClass?: string;
7
+ direction?: 'vertical' | 'horizontal';
8
+ size?: SpaceSize | (string & {});
9
+ align?: SpaceAlign | (string & {});
10
+ wrap?: boolean;
11
+ }
12
+ export declare const spaceSizes: string[];
13
+ export declare const spaceMapAlign: Record<string, string>;
14
+ export declare const defaultSpaceProps: {
15
+ direction: SpaceProps["direction"];
16
+ size: SpaceProps["size"];
17
+ };
18
+ export interface SpaceSlots {
19
+ default?(props: Record<string, never>): any;
20
+ }
@@ -0,0 +1,7 @@
1
+ import { defaultConfig } from '../config';
2
+ export const spaceSizes = ['small', 'middle', 'large'];
3
+ export const spaceMapAlign = {
4
+ start: 'flex-start',
5
+ end: 'flex-end',
6
+ };
7
+ export const defaultSpaceProps = defaultConfig.space;
@@ -0,0 +1 @@
1
+ export { type SpaceProps, type SpaceSlots, type SpaceSize, spaceSizes, } from './common';
@@ -0,0 +1 @@
1
+ export { spaceSizes, } from './common';
@@ -0,0 +1,38 @@
1
+ @use '../style/base' as *;
2
+
3
+ @include bem(space) {
4
+ @include b() {
5
+ @include universal;
6
+ }
7
+
8
+ @include e(element) {
9
+ @include universal;
10
+
11
+ @include m(modifier) {
12
+ }
13
+ }
14
+
15
+ @include m(vertical) {
16
+ flex-direction: column;
17
+ }
18
+
19
+ @include m(horizontal) {
20
+ flex-direction: row;
21
+ }
22
+
23
+ @include m(small) {
24
+ gap: var(--sar-space-small-gap);
25
+ }
26
+
27
+ @include m(middle) {
28
+ gap: var(--sar-space-middle-gap);
29
+ }
30
+
31
+ @include m(large) {
32
+ gap: var(--sar-space-large-gap);
33
+ }
34
+
35
+ @include m(wrap) {
36
+ flex-wrap: wrap;
37
+ }
38
+ }
@@ -0,0 +1,13 @@
1
+ import { type SpaceProps, type SpaceSlots } from './common';
2
+ declare function __VLS_template(): Readonly<SpaceSlots> & SpaceSlots;
3
+ declare const __VLS_component: import("vue").DefineComponent<SpaceProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<SpaceProps> & Readonly<{}>, {
4
+ size: import("./common").SpaceSize | (string & {});
5
+ direction: "vertical" | "horizontal";
6
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
8
+ export default _default;
9
+ type __VLS_WithTemplateSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <view :class="spaceClass" :style="spaceStyle">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
6
+
7
+ <script>
8
+ import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
9
+ import { computed } from "vue";
10
+ import { classNames, stringifyStyle, createBem } from "../../utils";
11
+ import {
12
+ defaultSpaceProps,
13
+ spaceMapAlign,
14
+ spaceSizes
15
+ } from "./common";
16
+ export default _defineComponent({
17
+ ...{
18
+ options: {
19
+ virtualHost: true,
20
+ styleIsolation: "shared"
21
+ }
22
+ },
23
+ __name: "space",
24
+ props: _mergeDefaults({
25
+ rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
26
+ rootClass: { type: String, required: false },
27
+ direction: { type: String, required: false },
28
+ size: { type: [String, Object], required: false },
29
+ align: { type: [String, Object], required: false },
30
+ wrap: { type: Boolean, required: false }
31
+ }, defaultSpaceProps),
32
+ setup(__props, { expose: __expose }) {
33
+ __expose();
34
+ const props = __props;
35
+ const bem = createBem("space");
36
+ const presetSize = computed(() => {
37
+ return spaceSizes.includes(props.size);
38
+ });
39
+ const spaceClass = computed(() => {
40
+ return classNames(
41
+ bem.b(),
42
+ bem.m(props.direction),
43
+ bem.m(props.size, presetSize.value),
44
+ bem.m("wrap", props.wrap),
45
+ props.rootClass
46
+ );
47
+ });
48
+ const spaceStyle = computed(() => {
49
+ return stringifyStyle(
50
+ {
51
+ gap: presetSize.value ? null : props.size,
52
+ alignItems: (props.align && spaceMapAlign[props.align]) ?? props.align
53
+ },
54
+ props.rootStyle
55
+ );
56
+ });
57
+ const __returned__ = { props, bem, presetSize, spaceClass, spaceStyle };
58
+ return __returned__;
59
+ }
60
+ });
61
+ </script>
62
+
63
+ <style lang="scss">
64
+ @import './index.scss';
65
+ </style>
@@ -0,0 +1,7 @@
1
+ // #variables
2
+ page {
3
+ --sar-space-small-gap: 8rpx;
4
+ --sar-space-middle-gap: 16rpx;
5
+ --sar-space-large-gap: 24rpx;
6
+ }
7
+ // #endvariables
package/global.d.ts CHANGED
@@ -77,6 +77,7 @@ declare module 'vue' {
77
77
  SarSkeletonParagraph: typeof import('./components/skeleton-paragraph/skeleton-paragraph').default
78
78
  SarSkeletonTitle: typeof import('./components/skeleton-title/skeleton-title').default
79
79
  SarSlider: typeof import('./components/slider/slider').default
80
+ SarSpace: typeof import('./components/space/space').default
80
81
  SarStepper: typeof import('./components/stepper/stepper').default
81
82
  SarSteps: typeof import('./components/steps/steps').default
82
83
  SarSwiperDot: typeof import('./components/swiper-dot/swiper-dot').default
@@ -85,8 +86,8 @@ declare module 'vue' {
85
86
  SarTabbar: typeof import('./components/tabbar/tabbar').default
86
87
  SarTabbarItem: typeof import('./components/tabbar-item/tabbar-item').default
87
88
  SarTable: typeof import('./components/table/table').default
88
- SarTableRow: typeof import('./components/table-row/table-row').default
89
89
  SarTableCell: typeof import('./components/table-cell/table-cell').default
90
+ SarTableRow: typeof import('./components/table-row/table-row').default
90
91
  SarTabs: typeof import('./components/tabs/tabs').default
91
92
  SarTag: typeof import('./components/tag/tag').default
92
93
  SarTimeline: typeof import('./components/timeline/timeline').default
package/index.d.ts CHANGED
@@ -63,6 +63,7 @@ export * from './components/search';
63
63
  export * from './components/share-sheet';
64
64
  export * from './components/skeleton';
65
65
  export * from './components/slider';
66
+ export * from './components/space';
66
67
  export * from './components/stepper';
67
68
  export * from './components/steps';
68
69
  export * from './components/swiper-dot';
package/index.js CHANGED
@@ -63,6 +63,7 @@ export * from './components/search';
63
63
  export * from './components/share-sheet';
64
64
  export * from './components/skeleton';
65
65
  export * from './components/slider';
66
+ export * from './components/space';
66
67
  export * from './components/stepper';
67
68
  export * from './components/steps';
68
69
  export * from './components/swiper-dot';
package/index.scss CHANGED
@@ -53,6 +53,7 @@
53
53
  @use './components/share-sheet/variables.scss' as *;
54
54
  @use './components/skeleton/variables.scss' as *;
55
55
  @use './components/slider/variables.scss' as *;
56
+ @use './components/space/variables.scss' as *;
56
57
  @use './components/stepper/variables.scss' as *;
57
58
  @use './components/steps/variables.scss' as *;
58
59
  @use './components/style/variables.scss' as *;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "sard-uniapp",
3
3
  "name": "sard-uniapp",
4
4
  "displayName": "sard-uniapp",
5
- "version": "1.9.2",
5
+ "version": "1.10.0",
6
6
  "description": "sard-uniapp 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库",
7
7
  "main": "index.js",
8
8
  "scripts": {
@@ -116,7 +116,7 @@
116
116
  "lodash-es": "^4.17.21",
117
117
  "prettier": "^2.8.8",
118
118
  "region-data": "^1.2.3",
119
- "sard-cli": "^1.0.3",
119
+ "sard-cli": "^1.0.4",
120
120
  "sass": "^1.43.4",
121
121
  "tel-area-code": "^1.0.1",
122
122
  "ts-custom-error": "^3.3.1",
package/utils/date.d.ts CHANGED
@@ -8,7 +8,8 @@ export declare function toMonthNumber(date: Date): number;
8
8
  export declare function getPadStartDays(year: number, month: number, amount: number): Date[];
9
9
  export declare function getPadEndDays(year: number, month: number, amount: number): Date[];
10
10
  export declare function getOffsetDaysFromFirstDay(weekOnFirstDay: number, weekStartsOn: number): number;
11
- export declare function formatDate(date: Date, formatStr?: string): string;
11
+ export declare function formatDate(date: Date, format?: string): string;
12
+ export declare function parseDate(value: string, format?: string): Date;
12
13
  export declare function minmaxDate(date: Date, minDate: Date, maxDate: Date): Date;
13
14
  export declare function getPrevMonthDate(date: Date): Date;
14
15
  export declare function getNextMonthDate(date: Date): Date;
package/utils/date.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { escapeRegExp } from './regexp';
1
2
  import { minmax } from './utils';
2
3
  // 判断是否为闰年
3
4
  export function isLeapYear(year) {
@@ -53,30 +54,80 @@ export function getPadEndDays(year, month, amount) {
53
54
  export function getOffsetDaysFromFirstDay(weekOnFirstDay, weekStartsOn) {
54
55
  return (weekOnFirstDay - weekStartsOn + 7) % 7;
55
56
  }
57
+ const dateTokensReg = /(YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|SSS)/g;
58
+ const dateGetters = {
59
+ YYYY: (date) => String(date.getFullYear()).padStart(4, '0'),
60
+ YY: (date) => String(date.getFullYear()).slice(-2),
61
+ MM: (date) => String(date.getMonth() + 1).padStart(2, '0'),
62
+ M: (date) => String(date.getMonth() + 1),
63
+ DD: (date) => String(date.getDate()).padStart(2, '0'),
64
+ D: (date) => String(date.getDate()),
65
+ HH: (date) => String(date.getHours()).padStart(2, '0'),
66
+ H: (date) => String(date.getHours()),
67
+ hh: (date) => String(date.getHours() % 24).padStart(2, '0'),
68
+ h: (date) => String(date.getHours() % 24),
69
+ mm: (date) => String(date.getMinutes()).padStart(2, '0'),
70
+ m: (date) => String(date.getMinutes()),
71
+ ss: (date) => String(date.getSeconds()).padStart(2, '0'),
72
+ s: (date) => String(date.getSeconds()),
73
+ SSS: (date) => String(date.getMilliseconds()).padStart(3, '0'),
74
+ };
56
75
  // 根据传入的占位符返回格式化后的日期
57
- export function formatDate(date, formatStr = 'YYYY-MM-DD HH:mm:ss') {
58
- const regexp = /YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|SSS/g;
59
- const matches = {
60
- YYYY: (date) => String(date.getFullYear()).padStart(4, '0'),
61
- YY: (date) => String(date.getFullYear()).slice(-2),
62
- MM: (date) => String(date.getMonth() + 1).padStart(2, '0'),
63
- M: (date) => String(date.getMonth() + 1),
64
- DD: (date) => String(date.getDate()).padStart(2, '0'),
65
- D: (date) => String(date.getDate()),
66
- HH: (date) => String(date.getHours()).padStart(2, '0'),
67
- H: (date) => String(date.getHours()),
68
- hh: (date) => String(date.getHours() % 24).padStart(2, '0'),
69
- h: (date) => String(date.getHours() % 24),
70
- mm: (date) => String(date.getMinutes()).padStart(2, '0'),
71
- m: (date) => String(date.getMinutes()),
72
- ss: (date) => String(date.getSeconds()).padStart(2, '0'),
73
- s: (date) => String(date.getSeconds()),
74
- SSS: (date) => String(date.getMilliseconds()).padStart(3, '0'),
75
- };
76
- return formatStr.replace(regexp, (match) => {
77
- return matches[match](date);
76
+ export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
77
+ return format.replace(dateTokensReg, (match) => {
78
+ return dateGetters[match](date);
78
79
  });
79
80
  }
81
+ const defaultTokenFrags = ['YYYY', 'MM', 'DD', 'HH', 'mm', 'ss', 'SSS'];
82
+ const dateSetters = {
83
+ YYYY: (date, year) => date.setFullYear(year),
84
+ YY: (date, year) => date.setFullYear(year),
85
+ MM: (date, month) => date.setMonth(month - 1),
86
+ M: (date, month) => date.setMonth(month - 1),
87
+ DD: (date, d) => date.setDate(d),
88
+ D: (date, d) => date.setDate(d),
89
+ HH: (date, hours) => date.setHours(hours),
90
+ H: (date, hours) => date.setHours(hours),
91
+ hh: (date, hours) => date.setHours(hours),
92
+ h: (date, hours) => date.setHours(hours),
93
+ mm: (date, minutes) => date.setMinutes(minutes),
94
+ m: (date, minutes) => date.setMinutes(minutes),
95
+ ss: (date, seconds) => date.setSeconds(seconds),
96
+ s: (date, seconds) => date.setSeconds(seconds),
97
+ SSS: (date, milliseconds) => date.setMilliseconds(milliseconds),
98
+ };
99
+ function parseDateWithoutFormat(value) {
100
+ const numbers = value.split(/\D+/).filter(Boolean);
101
+ const tokens = defaultTokenFrags.slice(0, numbers.length);
102
+ const date = new Date(0, 0);
103
+ tokens.forEach((token, i) => {
104
+ dateSetters[token](date, Number(numbers[i]));
105
+ });
106
+ return date;
107
+ }
108
+ // 解析日期的字符串表示形式,并返回 Date 实例对象
109
+ export function parseDate(value, format) {
110
+ if (!format) {
111
+ return parseDateWithoutFormat(value);
112
+ }
113
+ const frags = format.split(dateTokensReg);
114
+ const reg = new RegExp('^' +
115
+ frags
116
+ .filter((_, i) => i % 2 === 0)
117
+ .map((item) => escapeRegExp(item))
118
+ .join('(.*)') +
119
+ '$');
120
+ const dateFrags = reg.exec(value)?.slice(1);
121
+ if (!dateFrags) {
122
+ return parseDateWithoutFormat(value);
123
+ }
124
+ const tokenFrags = frags.filter((_, i) => i % 2 !== 0);
125
+ const date = new Date(0);
126
+ tokenFrags.forEach((token, i) => {
127
+ dateSetters[token](date, Number(dateFrags[i]));
128
+ });
129
+ return date;
130
+ }
80
131
  // 限定日期范围
81
132
  export function minmaxDate(date, minDate, maxDate) {
82
133
  return new Date(minmax(date.getTime(), minDate.getTime(), maxDate.getTime()));
@@ -0,0 +1 @@
1
+ export declare function escapeRegExp(str: string): string;
@@ -0,0 +1,3 @@
1
+ export function escapeRegExp(str) {
2
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
+ }