savor-ui 0.28.0 → 0.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
 
4
4
 
5
+ # [0.29.0](https://gitee.com/mach552/savor-ui/compare/v0.28.0...v0.29.0) (2026-08-30)
6
+
7
+
8
+ ### Features
9
+
10
+ * **steps:** 新增`arrow`属性开启箭头模式 ([707c65d](https://gitee.com/mach552/savor-ui/commits/707c65db08fa6a996ef2be37ab92d90fe32a1009))
11
+
5
12
  # [0.28.0](https://gitee.com/mach552/savor-ui/compare/v0.27.0...v0.28.0) (2026-08-29)
6
13
 
7
14
 
@@ -9,12 +9,13 @@ export declare const SSteps: ((__VLS_props: NonNullable<Awaited<typeof __VLS_set
9
9
  items: StepsItemProps[];
10
10
  current?: number | undefined;
11
11
  vertical?: boolean | undefined;
12
- size?: "small" | "medium" | undefined;
12
+ size?: "mini" | "small" | "medium" | "large" | "larger" | undefined;
13
13
  alignCenter?: boolean | undefined;
14
14
  status?: "wait" | "loading" | "done" | "error" | "process" | undefined;
15
15
  changeable?: boolean | undefined;
16
16
  dot?: boolean | undefined;
17
17
  simple?: boolean | undefined;
18
+ arrow?: boolean | undefined;
18
19
  onChange?: ((index: number) => any) | undefined;
19
20
  "onUpdate:current"?: ((value: number) => any) | undefined;
20
21
  } & (typeof globalThis extends {
@@ -1,44 +1,41 @@
1
- import { useNamespace as e } from "../../../hooks/src/use-namespace.mjs";
1
+ import { useElementSize as e } from "../../../hooks/src/use-element-size.mjs";
2
+ import { useNamespace as t } from "../../../hooks/src/use-namespace.mjs";
2
3
  import "../../../hooks/index.mjs";
3
- import { RightLine as t } from "../../../icons/src/svg/arrow/index.mjs";
4
- import { CheckLine as n } from "../../../icons/src/svg/system/index.mjs";
5
- import { SIcon as r } from "../icon/index.mjs";
6
- import { child as i, createComponent as a, createFor as o, createIf as s, createInvoker as c, defineVaporComponent as l, delegateEvents as u, mergeModels as d, next as f, renderEffect as p, setClass as m, setInsertionState as h, setStyle as g, setText as _, template as v, toDisplayString as y, txt as b, unref as x, useModel as S, watch as C } from "vue";
4
+ import { RightLine as n } from "../../../icons/src/svg/arrow/index.mjs";
5
+ import { CheckLine as r } from "../../../icons/src/svg/system/index.mjs";
6
+ import { SIcon as i } from "../icon/index.mjs";
7
+ import { child as a, createComponent as o, createFor as s, createIf as c, createInvoker as l, defineVaporComponent as u, delegateEvents as d, mergeModels as f, renderEffect as p, setClass as m, setInsertionState as h, setStaticTemplateRef as g, setStyle as _, setText as v, template as y, toDisplayString as b, txt as x, unref as S, useModel as C, useTemplateRef as w, watch as T } from "vue";
7
8
  //#region ../components/src/steps/steps.vue?vue&type=script&setup=true&vapor=true&lang.ts
8
- var w = v("<div>"), T = v("<span> "), E = v("<div> "), D = v("<div><div></div><div><div> </div></div>"), O = v("<div>", 1);
9
- u("click");
10
- var k = /*@__PURE__*/ l({
9
+ var E = y("<div>"), D = y("<span> "), O = y("<div> "), k = y("<div><div><div> </div></div>"), A = y("<div>", 1);
10
+ d("click");
11
+ var j = /*@__PURE__*/ u({
11
12
  name: "SSteps",
12
13
  __name: "steps",
13
- props: /*@__PURE__*/ d({
14
+ props: /*@__PURE__*/ f({
14
15
  items: { default: () => [] },
15
16
  current: {},
16
- vertical: {
17
- type: Boolean,
18
- default: !1
19
- },
17
+ vertical: { type: Boolean },
20
18
  size: { default: "medium" },
21
19
  alignCenter: { type: Boolean },
22
20
  status: { default: "process" },
23
- changeable: {
24
- type: Boolean,
25
- default: !1
26
- },
27
- dot: {
28
- type: Boolean,
29
- default: !1
30
- },
31
- simple: { type: Boolean }
21
+ changeable: { type: Boolean },
22
+ dot: { type: Boolean },
23
+ simple: { type: Boolean },
24
+ arrow: { type: Boolean }
32
25
  }, {
33
26
  current: { default: 0 },
34
27
  currentModifiers: {}
35
28
  }),
36
- emits: /*@__PURE__*/ d(["change"], ["update:current"]),
37
- setup(l, { emit: u }) {
38
- let d = l, v = u, k = e("steps"), A = S(l, "current"), j = (e) => e > A.value ? "wait" : e < A.value ? "done" : e === A.value ? d.status : "", M = (e) => {
29
+ emits: /*@__PURE__*/ f(["change"], ["update:current"]),
30
+ setup(u, { emit: d }) {
31
+ let f = u, y = d, j = t("steps"), M = C(u, "current"), N = w("stepsRef"), { height: P } = e(N);
32
+ T(P, (e) => {
33
+ N.value?.style.setProperty("--s-steps-height", e + "px");
34
+ }, { immediate: !0 });
35
+ let F = (e) => e > M.value ? "wait" : e < M.value ? "done" : e === M.value ? f.status : "", I = (e) => {
39
36
  let t = { backgroundColor: "" }, n = e + 1;
40
- if (n >= d.items.length) return t.backgroundColor = "var(--s-color-fill-3)", t;
41
- switch (j(n)) {
37
+ if (n >= f.items.length) return t.backgroundColor = "var(--s-color-fill-3)", t;
38
+ switch (F(n)) {
42
39
  case "done":
43
40
  t.backgroundColor = "var(--s-color-success-6)";
44
41
  break;
@@ -51,62 +48,66 @@ var k = /*@__PURE__*/ l({
51
48
  default: t.backgroundColor = "var(--s-color-fill-3)";
52
49
  }
53
50
  return t;
54
- }, N = (e) => {
55
- d.changeable && (d.items[e]?.disabled || (A.value = e));
51
+ }, L = (e) => f.arrow ? "0%" : e < f.items.length - 1 && !f.alignCenter ? 100 / (f.items.length - 1) + "%" : 100 / f.items.length + "%", R = (e) => {
52
+ f.changeable && (f.items[e]?.disabled || (M.value = e));
56
53
  };
57
- C(A, (e) => {
58
- v("change", e);
54
+ T(M, (e) => {
55
+ y("change", e);
59
56
  });
60
- let P = O();
57
+ let z = A();
61
58
  return p(() => {
62
- let e = x(k);
63
- m(P, [
59
+ let e = S(j);
60
+ m(z, [
64
61
  e.b(),
65
- e.m(l.size),
66
- e.is("vertical", l.vertical),
67
- e.is("dot", l.dot),
68
- e.is("simple", l.simple)
62
+ e.m(u.size),
63
+ e.is("vertical", u.vertical),
64
+ e.is("dot", u.dot),
65
+ e.is("simple", u.simple),
66
+ e.is("arrow", u.arrow)
69
67
  ]);
70
- }), h(P, null, 0), o(() => l.items, (e, o) => {
71
- let u = D(), d = i(u), v = f(d, 1), S = i(v);
68
+ }), h(z, null, 0), s(() => u.items, (e, t) => {
69
+ let s = k(), d = a(s, 1), f = a(d);
72
70
  p(() => {
73
- let e = x(k), t = o.value, n = l.alignCenter, r = l.items.length;
74
- m(u, [
71
+ let e = S(j), n = t.value;
72
+ m(s, [
75
73
  e.e("step"),
76
- e.m(j(t)),
77
- e.is("center", n),
78
- e.is("changeable", l.changeable)
79
- ]), g(u, { flexBasis: t < r - 1 && !n ? 100 / (r - 1) + "%" : 100 / r + "%" }), m(d, [e.e("head")]);
80
- }), h(d, null, 0), s(() => o.value < l.items.length - 1 && !l.simple, () => {
81
- let e = w();
82
- return p(() => {
83
- m(e, [x(k).e("line")]), g(e, M(o.value));
84
- }), e;
85
- }), h(d, null, 1), s(() => l.dot, () => {
86
- let e = w();
87
- return p(() => m(e, [x(k).e("dot")])), e;
88
- }, () => {
89
- let e = w();
90
- return p(() => m(e, [x(k).e("icon")])), h(e, null, 0), s(() => j(o.value) === "loading", () => a(x(r), { loading: "" })), h(e, null, 1), s(() => j(o.value) === "done", () => a(x(n)), () => {
91
- let e = T(), t = b(e);
92
- return p(() => _(t, y(o.value + 1))), e;
93
- }, 1029), e;
94
- }, 517);
95
- let C = b(S);
74
+ e.m(F(n)),
75
+ e.is("center", u.alignCenter),
76
+ e.is("changeable", u.changeable)
77
+ ]), _(s, { flexBasis: L(n) });
78
+ }), h(s, 0, 0), c(() => !u.arrow, () => {
79
+ let e = E();
80
+ return p(() => m(e, [S(j).e("head")])), h(e, null, 0), c(() => t.value < u.items.length - 1 && !u.simple, () => {
81
+ let e = E();
82
+ return p(() => {
83
+ m(e, [S(j).e("line")]), _(e, I(t.value));
84
+ }), e;
85
+ }), h(e, null, 1), c(() => u.dot, () => {
86
+ let e = E();
87
+ return p(() => m(e, [S(j).e("dot")])), e;
88
+ }, () => {
89
+ let e = E();
90
+ return p(() => m(e, [S(j).e("icon")])), h(e, null, 0), c(() => F(t.value) === "loading", () => o(S(i), { loading: "" })), h(e, null, 1), c(() => F(t.value) === "done", () => o(S(r)), () => {
91
+ let e = D(), n = x(e);
92
+ return p(() => v(n, b(t.value + 1))), e;
93
+ }, 1029), e;
94
+ }, 517), e;
95
+ });
96
+ let g = x(f);
96
97
  return p(() => {
97
- let t = x(k);
98
- m(v, [t.e("content")]), m(S, [t.e("title")]), _(C, y(e.value.title));
99
- }), h(v, null, 1), s(() => !l.simple, () => {
100
- let t = E(), n = b(t);
98
+ let t = S(j);
99
+ m(d, [t.e("content")]), m(f, [t.e("title")]), v(g, b(e.value.title));
100
+ }), h(d, null, 1), c(() => !u.simple && !u.arrow || u.arrow && e.value.description, () => {
101
+ let t = O(), n = x(t);
101
102
  return p(() => {
102
- m(t, [x(k).e("description")]), _(n, y(e.value.description));
103
+ m(t, [S(j).e("description")]), v(n, b(e.value.description));
103
104
  }), t;
104
- }), h(u, null, 2), s(() => o.value < l.items.length - 1 && l.simple, () => {
105
- let e = w();
106
- return p(() => m(e, [x(k).e("arrow")])), h(e, null, 0), a(x(t)), e;
107
- }), u.$evtclick = c(() => N(o.value)), u;
108
- }, (e, t) => t, 9), P;
105
+ }), h(s, null, 2), c(() => t.value < u.items.length - 1 && u.simple, () => {
106
+ let e = E();
107
+ return p(() => m(e, [S(j).e("arrow")])), h(e, null, 0), o(S(n)), e;
108
+ }), s.$evtclick = l(() => R(t.value)), s;
109
+ }, (e, t) => t, 9), g(z, N, null, "stepsRef"), z;
109
110
  }
110
111
  });
111
112
  //#endregion
112
- export { k as default };
113
+ export { j as default };
@@ -6,7 +6,7 @@ export interface StepsProps {
6
6
  /** 是否垂直布局 */
7
7
  vertical?: boolean;
8
8
  /** 步骤项大小 */
9
- size?: "small" | "medium";
9
+ size?: "mini" | "small" | "medium" | "large" | "larger";
10
10
  /** 节点标题布局方向 */
11
11
  alignCenter?: boolean;
12
12
  /** 当前步骤项状态 */
@@ -17,6 +17,8 @@ export interface StepsProps {
17
17
  dot?: boolean;
18
18
  /** 是否显示为简单步骤 */
19
19
  simple?: boolean;
20
+ /** 是否使用箭头形步骤条 */
21
+ arrow?: boolean;
20
22
  }
21
23
  export interface StepsItemProps {
22
24
  /** 标题 */
@@ -1,10 +1,41 @@
1
- import "vue";
1
+ import { onMounted as e, onUnmounted as t, ref as n, watch as r } from "vue";
2
2
  //#region ../hooks/src/use-element-size.ts
3
- var e = /* @__PURE__ */ new WeakMap();
4
- new ResizeObserver((t) => {
5
- for (let n of t) {
6
- let t = e.get(n.target);
7
- t && (t.width.value = n.contentRect.width, t.height.value = n.contentRect.height);
3
+ var i = /* @__PURE__ */ new WeakMap(), a = /* @__PURE__ */ new Set(), o = new ResizeObserver((e) => {
4
+ for (let t of e) {
5
+ let e = i.get(t.target);
6
+ e && (e.width.value = t.contentRect.width, e.height.value = t.contentRect.height);
8
7
  }
9
- });
8
+ }), s = (s) => {
9
+ let c = n(0), l = n(0), u = () => {
10
+ c.value = window.innerWidth, l.value = window.innerHeight;
11
+ }, d = (e) => {
12
+ i.set(e, {
13
+ width: c,
14
+ height: l
15
+ }), o.observe(e);
16
+ let t = e.getBoundingClientRect();
17
+ c.value = t.width, l.value = t.height;
18
+ }, f = (e) => {
19
+ o.unobserve(e), i.delete(e);
20
+ }, p = () => {
21
+ c.value = window.innerWidth, l.value = window.innerHeight, window.addEventListener("resize", u), a.add(u);
22
+ }, m = () => {
23
+ window.removeEventListener("resize", u), a.delete(u);
24
+ }, h = (e) => {
25
+ e && (e === window ? p() : e instanceof Element && d(e));
26
+ }, g = (e) => {
27
+ e && (e === window ? m() : e instanceof Element && f(e));
28
+ };
29
+ return e(() => {
30
+ h(s === window ? window : s.value);
31
+ }), t(() => {
32
+ g(s === window ? window : s.value);
33
+ }), s !== window && r(() => s.value, (e, t) => {
34
+ t && g(t), e && h(e);
35
+ }, { immediate: !1 }), {
36
+ width: c,
37
+ height: l
38
+ };
39
+ };
10
40
  //#endregion
41
+ export { s as useElementSize };
@@ -1,10 +1,46 @@
1
1
  @use "../mixins/function.scss" as *;
2
2
  @use "../mixins/mixins.scss" as *;
3
+ @use "../common/var.scss" as *;
3
4
 
4
5
  @include b(steps) {
5
6
  display: flex;
6
7
  width: 100%;
7
8
 
9
+ @each $size in $size-list {
10
+ @include m(#{$size}) {
11
+ @include this-is(simple) {
12
+ min-height: getCssVar("size", $size);
13
+ }
14
+ @include this-is(arrow) {
15
+ border-radius: getCssVar("radius", $size);
16
+ @include child-be(steps, step) {
17
+ min-height: getCssVar("size", $size);
18
+ }
19
+ }
20
+ @include be(steps, icon) {
21
+ height: calc(getCssVar("size", $size) - 12px);
22
+ width: calc(getCssVar("size", $size) - 12px);
23
+ font-size: getCssVar("font-size", $size);
24
+ }
25
+ @include be(steps, title) {
26
+ font-size: getCssVar("font-size", $size);
27
+ line-height: getCssVar("line-height", $size);
28
+ }
29
+ @include be(steps, description) {
30
+ font-size: getCssVar("font-size", $size);
31
+ line-height: getCssVar("line-height", $size);
32
+ }
33
+ @include be(steps, line) {
34
+ top: calc((getCssVar("size", $size) - 12px) / 2);
35
+ }
36
+ @include this-is(vertical) {
37
+ @include be(steps, line) {
38
+ left: calc((getCssVar("size", $size) - 12px) / 2);
39
+ }
40
+ }
41
+ }
42
+ }
43
+
8
44
  @include when(vertical) {
9
45
  height: 100%;
10
46
  flex-direction: column;
@@ -19,7 +55,6 @@
19
55
  width: 2px;
20
56
  top: 0;
21
57
  bottom: 0;
22
- left: 11px;
23
58
  height: 100%;
24
59
  }
25
60
  @include be(steps, content) {
@@ -40,8 +75,8 @@
40
75
  }
41
76
 
42
77
  @include when(simple) {
43
- padding: 12px 8%;
44
- background-color: getCssVar("color", "fill-3");
78
+ padding: 4px 8%;
79
+ background-color: getCssVar("color", "fill-2");
45
80
  flex-direction: row;
46
81
  border-radius: getCssVar("radius", "medium");
47
82
  @include be(steps, step) {
@@ -136,38 +171,6 @@
136
171
  }
137
172
  }
138
173
 
139
- @include m(small) {
140
- @include be(steps, icon) {
141
- width: 20px;
142
- height: 20px;
143
- font-size: 12px;
144
- }
145
- @include be(steps, title) {
146
- font-size: getCssVar("font-size", "medium");
147
- line-height: getCssVar("line-height", "large");
148
- }
149
- @include be(steps, description) {
150
- font-size: getCssVar("font-size", "small");
151
- line-height: getCssVar("line-height", "small");
152
- }
153
- }
154
-
155
- @include m(medium) {
156
- @include be(steps, icon) {
157
- width: 24px;
158
- height: 24px;
159
- font-size: 14px;
160
- }
161
- @include be(steps, title) {
162
- font-size: getCssVar("font-size", "large");
163
- line-height: getCssVar("line-height", "larger");
164
- }
165
- @include be(steps, description) {
166
- font-size: getCssVar("font-size", "medium");
167
- line-height: getCssVar("line-height", "medium");
168
- }
169
- }
170
-
171
174
  @include e(step) {
172
175
  @include when(changeable) {
173
176
  cursor: pointer;
@@ -197,7 +200,6 @@
197
200
  @include e(line) {
198
201
  position: absolute;
199
202
  height: 2px;
200
- top: 11px;
201
203
  left: 0;
202
204
  right: 0;
203
205
  }
@@ -234,4 +236,124 @@
234
236
  line-height: getCssVar("line-height", "medium");
235
237
  color: getCssVar("color", "text-3");
236
238
  }
239
+
240
+ @include when(arrow) {
241
+ flex-wrap: nowrap;
242
+ align-items: stretch;
243
+ overflow: hidden;
244
+
245
+ @include be(steps, step) {
246
+ position: relative;
247
+ flex: 1 1 0;
248
+ min-width: 0;
249
+ display: flex;
250
+ align-items: center;
251
+ padding: 4px 16px;
252
+ color: #fff;
253
+ overflow: visible;
254
+
255
+ &:not(:first-child) {
256
+ padding-left: var(--s-steps-height);
257
+ }
258
+
259
+ &:not(:last-child) {
260
+ margin-right: 4px;
261
+ }
262
+
263
+ &:not(:first-child)::before {
264
+ content: "";
265
+ position: absolute;
266
+ top: 0;
267
+ left: 0;
268
+ z-index: 1;
269
+ width: 0;
270
+ height: 0;
271
+
272
+ border-top: calc(var(--s-steps-height) / 2) solid transparent;
273
+ border-bottom: calc(var(--s-steps-height) / 2) solid transparent;
274
+ border-left: calc(var(--s-steps-height) / 2) solid getCssVar("color", "bg-2");
275
+ }
276
+
277
+ &:not(:last-child)::after {
278
+ content: "";
279
+ position: absolute;
280
+ top: 0;
281
+ z-index: 2;
282
+ width: 0;
283
+ height: 0;
284
+ right: calc(var(--s-steps-height) / 2 * -1);
285
+ border-top: calc(var(--s-steps-height) / 2) solid transparent;
286
+ border-bottom: calc(var(--s-steps-height) / 2) solid transparent;
287
+ border-left: calc(var(--s-steps-height) / 2) solid getCssVar("color", "fill-2");
288
+ }
289
+
290
+ @include when(changeable) {
291
+ cursor: pointer;
292
+ }
293
+
294
+ @include this-bm(steps, wait) {
295
+ background-color: getCssVar("color", "fill-2");
296
+
297
+ &:not(:last-child)::after {
298
+ border-left-color: getCssVar("color", "fill-2");
299
+ }
300
+
301
+ @include be(steps, title) {
302
+ color: getCssVar("color", "text-1");
303
+ }
304
+ @include be(steps, description) {
305
+ color: getCssVar("color", "text-3");
306
+ opacity: 1;
307
+ }
308
+ }
309
+
310
+ @include this-bm(steps, process) {
311
+ background-color: getCssVar("color", "primary-6");
312
+
313
+ &:not(:last-child)::after {
314
+ border-left-color: getCssVar("color", "primary-6");
315
+ }
316
+ }
317
+
318
+ @include this-bm(steps, done) {
319
+ background-color: getCssVar("color", "success-6");
320
+
321
+ &:not(:last-child)::after {
322
+ border-left-color: getCssVar("color", "success-6");
323
+ }
324
+ }
325
+
326
+ @include this-bm(steps, error) {
327
+ background-color: getCssVar("color", "danger-6");
328
+
329
+ &:not(:last-child)::after {
330
+ border-left-color: getCssVar("color", "danger-6");
331
+ }
332
+ }
333
+ }
334
+
335
+ @include be(steps, content) {
336
+ margin-top: 0;
337
+ overflow: hidden;
338
+ display: flex;
339
+ flex-direction: column;
340
+ gap: 4px;
341
+ }
342
+
343
+ @include be(steps, title) {
344
+ color: inherit;
345
+ font-weight: 500;
346
+ white-space: nowrap;
347
+ overflow: hidden;
348
+ text-overflow: ellipsis;
349
+ }
350
+
351
+ @include be(steps, description) {
352
+ color: inherit;
353
+ opacity: 0.85;
354
+ white-space: nowrap;
355
+ overflow: hidden;
356
+ text-overflow: ellipsis;
357
+ }
358
+ }
237
359
  }
@@ -2286,6 +2286,10 @@
2286
2286
  "description": "是否显示为简单步骤",
2287
2287
  "type": "boolean"
2288
2288
  },
2289
+ "s-steps/arrow": {
2290
+ "description": "是否使用箭头形步骤条",
2291
+ "type": "boolean"
2292
+ },
2289
2293
  "s-steps-item/title": {
2290
2294
  "description": "标题",
2291
2295
  "type": "string"
@@ -948,7 +948,8 @@
948
948
  "status",
949
949
  "changeable",
950
950
  "dot",
951
- "simple"
951
+ "simple",
952
+ "arrow"
952
953
  ]
953
954
  },
954
955
  "s-steps-item": {
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "framework": "vue",
4
4
  "name": "savor-ui",
5
- "version": "0.27.0",
5
+ "version": "0.28.0",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "types-syntax": "typescript",
@@ -5868,7 +5868,7 @@
5868
5868
  "name": "size",
5869
5869
  "description": "步骤项大小",
5870
5870
  "value": {
5871
- "type": "small | medium",
5871
+ "type": "mini | small | medium | large | larger",
5872
5872
  "kind": "expression"
5873
5873
  }
5874
5874
  },
@@ -5911,6 +5911,14 @@
5911
5911
  "type": "boolean",
5912
5912
  "kind": "expression"
5913
5913
  }
5914
+ },
5915
+ {
5916
+ "name": "arrow",
5917
+ "description": "是否使用箭头形步骤条",
5918
+ "value": {
5919
+ "type": "boolean",
5920
+ "kind": "expression"
5921
+ }
5914
5922
  }
5915
5923
  ],
5916
5924
  "events": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "savor-ui",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "A Vue3 Components Library",
5
5
  "keywords": [
6
6
  "component library",