@hlw-uni/mp-vue 1.0.4 → 1.0.6

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/dist/index.d.ts CHANGED
@@ -3,7 +3,10 @@
3
3
  */
4
4
  export { default as HlwAd } from './components/hlw-ad/index.vue';
5
5
  export { default as HlwAvatar } from './components/hlw-avatar/index.vue';
6
+ export { default as HlwCard } from './components/hlw-card/index.vue';
6
7
  export { default as HlwEmpty } from './components/hlw-empty/index.vue';
8
+ export { default as HlwHeader } from './components/hlw-header/index.vue';
7
9
  export { default as HlwLoading } from './components/hlw-loading/index.vue';
8
10
  export { default as HlwMenuList } from './components/hlw-menu-list/index.vue';
11
+ export { default as HlwPage } from './components/hlw-page/index.vue';
9
12
  export type { MenuItem } from './components/hlw-menu-list/types';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vue")) : typeof define === "function" && define.amd ? define(["exports", "vue"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.HlwUniVue = {}, global.vue));
3
3
  })(this, function(exports2, vue) {
4
4
  "use strict";
5
- const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
5
+ const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
6
6
  ...{ name: "HlwAd" },
7
7
  __name: "index",
8
8
  props: {
@@ -33,13 +33,13 @@
33
33
  };
34
34
  }
35
35
  });
36
- const _hoisted_1$3 = ["src"];
37
- const _hoisted_2$3 = {
36
+ const _hoisted_1$6 = ["src"];
37
+ const _hoisted_2$6 = {
38
38
  key: 1,
39
39
  class: "hlw-avatar__placeholder"
40
40
  };
41
- const _hoisted_3$2 = { class: "hlw-avatar__initial" };
42
- const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
41
+ const _hoisted_3$4 = { class: "hlw-avatar__initial" };
42
+ const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
43
43
  __name: "index",
44
44
  props: {
45
45
  src: {},
@@ -64,8 +64,8 @@
64
64
  src: __props.src,
65
65
  mode: "aspectFill",
66
66
  onError: _cache[0] || (_cache[0] = ($event) => loadError.value = true)
67
- }, null, 40, _hoisted_1$3)) : (vue.openBlock(), vue.createElementBlock("view", _hoisted_2$3, [
68
- vue.createElementVNode("text", _hoisted_3$2, vue.toDisplayString(initial.value), 1)
67
+ }, null, 40, _hoisted_1$6)) : (vue.openBlock(), vue.createElementBlock("view", _hoisted_2$6, [
68
+ vue.createElementVNode("text", _hoisted_3$4, vue.toDisplayString(initial.value), 1)
69
69
  ]))
70
70
  ], 2);
71
71
  };
@@ -78,15 +78,76 @@
78
78
  }
79
79
  return target;
80
80
  };
81
- const index$3 = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-7e8f98a5"]]);
82
- const _hoisted_1$2 = { class: "hlw-empty" };
83
- const _hoisted_2$2 = ["src"];
84
- const _hoisted_3$1 = {
81
+ const index$6 = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-7e8f98a5"]]);
82
+ const _hoisted_1$5 = { class: "hlw-card" };
83
+ const _hoisted_2$5 = {
84
+ key: 0,
85
+ class: "hlw-card-header"
86
+ };
87
+ const _hoisted_3$3 = { class: "flex items-center justify-between px-5 py-4 border-0 border-b border-dashed border-slate-200 bg-slate-50/30" };
88
+ const _hoisted_4$2 = { key: 0 };
89
+ const _hoisted_5$1 = { class: "text-sm font-bold text-slate-800 flex items-center gap-2 tracking-wide" };
90
+ const _hoisted_6$1 = { key: 1 };
91
+ const _hoisted_7$1 = {
92
+ key: 0,
93
+ class: "text-[10px] text-slate-400 bg-slate-50 px-2 py-1 rounded border border-slate-100 tracking-wide"
94
+ };
95
+ const _hoisted_8 = { class: "hlw-card-body" };
96
+ const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
97
+ ...{
98
+ options: {
99
+ styleIsolation: "shared",
100
+ virtualHost: true
101
+ }
102
+ },
103
+ __name: "index",
104
+ props: {
105
+ title: { default: "" },
106
+ icon: { default: "" },
107
+ iconColor: { default: "" },
108
+ extra: { default: "" }
109
+ },
110
+ setup(__props) {
111
+ return (_ctx, _cache) => {
112
+ return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$5, [
113
+ _ctx.$slots.header || __props.title || __props.icon || _ctx.$slots["header-left"] || _ctx.$slots["header-right"] ? (vue.openBlock(), vue.createElementBlock("view", _hoisted_2$5, [
114
+ vue.renderSlot(_ctx.$slots, "header", {}, () => [
115
+ vue.createElementVNode("view", _hoisted_3$3, [
116
+ _ctx.$slots["header-left"] || __props.title || __props.icon ? (vue.openBlock(), vue.createElementBlock("view", _hoisted_4$2, [
117
+ vue.renderSlot(_ctx.$slots, "header-left", {}, () => [
118
+ vue.createElementVNode("view", _hoisted_5$1, [
119
+ __props.icon ? (vue.openBlock(), vue.createElementBlock("text", {
120
+ key: 0,
121
+ class: vue.normalizeClass([__props.icon, __props.iconColor])
122
+ }, null, 2)) : vue.createCommentVNode("", true),
123
+ vue.createElementVNode("text", null, vue.toDisplayString(__props.title), 1)
124
+ ])
125
+ ], true)
126
+ ])) : vue.createCommentVNode("", true),
127
+ _ctx.$slots["header-right"] || __props.extra ? (vue.openBlock(), vue.createElementBlock("view", _hoisted_6$1, [
128
+ vue.renderSlot(_ctx.$slots, "header-right", {}, () => [
129
+ __props.extra ? (vue.openBlock(), vue.createElementBlock("text", _hoisted_7$1, vue.toDisplayString(__props.extra), 1)) : vue.createCommentVNode("", true)
130
+ ], true)
131
+ ])) : vue.createCommentVNode("", true)
132
+ ])
133
+ ], true)
134
+ ])) : vue.createCommentVNode("", true),
135
+ vue.createElementVNode("view", _hoisted_8, [
136
+ vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
137
+ ])
138
+ ]);
139
+ };
140
+ }
141
+ });
142
+ const index$5 = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-787fc3a7"]]);
143
+ const _hoisted_1$4 = { class: "hlw-empty" };
144
+ const _hoisted_2$4 = ["src"];
145
+ const _hoisted_3$2 = {
85
146
  key: 1,
86
147
  class: "hlw-empty__icon"
87
148
  };
88
149
  const _hoisted_4$1 = { class: "hlw-empty__text" };
89
- const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
150
+ const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
90
151
  __name: "index",
91
152
  props: {
92
153
  text: {},
@@ -94,43 +155,125 @@
94
155
  },
95
156
  setup(__props) {
96
157
  return (_ctx, _cache) => {
97
- return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$2, [
158
+ return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$4, [
98
159
  __props.image ? (vue.openBlock(), vue.createElementBlock("image", {
99
160
  key: 0,
100
161
  class: "hlw-empty__image",
101
162
  src: __props.image,
102
163
  mode: "aspectFit"
103
- }, null, 8, _hoisted_2$2)) : (vue.openBlock(), vue.createElementBlock("text", _hoisted_3$1, "📦")),
164
+ }, null, 8, _hoisted_2$4)) : (vue.openBlock(), vue.createElementBlock("text", _hoisted_3$2, "📦")),
104
165
  vue.createElementVNode("text", _hoisted_4$1, vue.toDisplayString(__props.text || "暂无数据"), 1),
105
166
  vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
106
167
  ]);
107
168
  };
108
169
  }
109
170
  });
110
- const index$2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-72364322"]]);
111
- const _hoisted_1$1 = { class: "hlw-loading" };
112
- const _hoisted_2$1 = {
171
+ const index$4 = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-72364322"]]);
172
+ const _hoisted_1$3 = { class: "header-title" };
173
+ const _hoisted_2$3 = {
174
+ key: 0,
175
+ class: "header-title"
176
+ };
177
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
178
+ __name: "index",
179
+ props: {
180
+ extraHeight: { default: 0 },
181
+ bgClass: { default: "" },
182
+ isBack: { type: Boolean, default: false },
183
+ title: { default: "" }
184
+ },
185
+ emits: ["back"],
186
+ setup(__props, { emit: __emit }) {
187
+ const getNavBarContentHeight = () => {
188
+ var _a;
189
+ try {
190
+ const menuInfo = (_a = uni.getMenuButtonBoundingClientRect) == null ? void 0 : _a.call(uni);
191
+ if (!menuInfo)
192
+ return 44;
193
+ const systemInfo = uni.getSystemInfoSync();
194
+ return (menuInfo.top - systemInfo.statusBarHeight) * 2 + menuInfo.height;
195
+ } catch {
196
+ return 44;
197
+ }
198
+ };
199
+ const getStatusBarHeight = () => {
200
+ try {
201
+ const systemInfo = uni.getSystemInfoSync();
202
+ return systemInfo.statusBarHeight || 20;
203
+ } catch {
204
+ return 20;
205
+ }
206
+ };
207
+ const NAV_BAR_CONTENT_HEIGHT = getNavBarContentHeight();
208
+ const props = __props;
209
+ const emit = __emit;
210
+ const handleBack = () => {
211
+ emit("back");
212
+ uni.navigateBack({ delta: 1 });
213
+ };
214
+ const slots = vue.useSlots();
215
+ const hasBgSlot = vue.computed(() => !props.isBack && !!slots.bg);
216
+ const statusBarHeight = vue.ref(getStatusBarHeight());
217
+ const totalNavBarHeight = vue.computed(() => statusBarHeight.value + NAV_BAR_CONTENT_HEIGHT + props.extraHeight);
218
+ return (_ctx, _cache) => {
219
+ return vue.openBlock(), vue.createElementBlock("view", {
220
+ class: "hlw-header",
221
+ style: vue.normalizeStyle({ height: totalNavBarHeight.value + "px" })
222
+ }, [
223
+ vue.createElementVNode("view", {
224
+ class: vue.normalizeClass(["header-bg-layer", hasBgSlot.value ? "" : props.bgClass])
225
+ }, [
226
+ !props.isBack ? vue.renderSlot(_ctx.$slots, "bg", { key: 0 }, void 0, true) : vue.createCommentVNode("", true)
227
+ ], 2),
228
+ vue.createElementVNode("view", {
229
+ class: "status-bar-spacer",
230
+ style: vue.normalizeStyle({ height: statusBarHeight.value + "px" })
231
+ }, null, 4),
232
+ vue.createElementVNode("view", {
233
+ class: "header-content-area",
234
+ style: vue.normalizeStyle({ height: vue.unref(NAV_BAR_CONTENT_HEIGHT) + "px" })
235
+ }, [
236
+ props.isBack ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
237
+ vue.createElementVNode("view", {
238
+ class: "header-back",
239
+ onClick: handleBack
240
+ }, [..._cache[0] || (_cache[0] = [
241
+ vue.createElementVNode("text", { class: "iconfont icon-back" }, null, -1)
242
+ ])]),
243
+ vue.createElementVNode("view", _hoisted_1$3, vue.toDisplayString(props.title), 1),
244
+ _cache[1] || (_cache[1] = vue.createElementVNode("view", { class: "header-placeholder" }, null, -1))
245
+ ], 64)) : vue.renderSlot(_ctx.$slots, "default", { key: 1 }, () => [
246
+ props.title ? (vue.openBlock(), vue.createElementBlock("view", _hoisted_2$3, vue.toDisplayString(props.title), 1)) : vue.createCommentVNode("", true)
247
+ ], true)
248
+ ], 4)
249
+ ], 4);
250
+ };
251
+ }
252
+ });
253
+ const index$3 = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-6f338046"]]);
254
+ const _hoisted_1$2 = { class: "hlw-loading" };
255
+ const _hoisted_2$2 = {
113
256
  key: 0,
114
257
  class: "hlw-loading__text"
115
258
  };
116
- const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
259
+ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
117
260
  __name: "index",
118
261
  props: {
119
262
  text: {}
120
263
  },
121
264
  setup(__props) {
122
265
  return (_ctx, _cache) => {
123
- return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$1, [
266
+ return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$2, [
124
267
  _cache[0] || (_cache[0] = vue.createElementVNode("view", { class: "hlw-loading__spinner" }, null, -1)),
125
- __props.text ? (vue.openBlock(), vue.createElementBlock("text", _hoisted_2$1, vue.toDisplayString(__props.text), 1)) : vue.createCommentVNode("", true)
268
+ __props.text ? (vue.openBlock(), vue.createElementBlock("text", _hoisted_2$2, vue.toDisplayString(__props.text), 1)) : vue.createCommentVNode("", true)
126
269
  ]);
127
270
  };
128
271
  }
129
272
  });
130
- const index$1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-14242381"]]);
131
- const _hoisted_1 = { class: "hlw-menu-list" };
132
- const _hoisted_2 = ["onTap"];
133
- const _hoisted_3 = { class: "hlw-menu-list__left" };
273
+ const index$2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-14242381"]]);
274
+ const _hoisted_1$1 = { class: "hlw-menu-list" };
275
+ const _hoisted_2$1 = ["onTap"];
276
+ const _hoisted_3$1 = { class: "hlw-menu-list__left" };
134
277
  const _hoisted_4 = {
135
278
  key: 0,
136
279
  class: "hlw-menu-list__icon"
@@ -141,7 +284,7 @@
141
284
  key: 0,
142
285
  class: "hlw-menu-list__value"
143
286
  };
144
- const _sfc_main = /* @__PURE__ */ vue.defineComponent({
287
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
145
288
  __name: "index",
146
289
  props: {
147
290
  items: {}
@@ -158,14 +301,14 @@
158
301
  emit("click", item);
159
302
  }
160
303
  return (_ctx, _cache) => {
161
- return vue.openBlock(), vue.createElementBlock("view", _hoisted_1, [
304
+ return vue.openBlock(), vue.createElementBlock("view", _hoisted_1$1, [
162
305
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.items, (item) => {
163
306
  return vue.openBlock(), vue.createElementBlock("view", {
164
307
  key: item.key,
165
308
  class: "hlw-menu-list__item",
166
309
  onTap: ($event) => onTap(item)
167
310
  }, [
168
- vue.createElementVNode("view", _hoisted_3, [
311
+ vue.createElementVNode("view", _hoisted_3$1, [
169
312
  item.icon ? (vue.openBlock(), vue.createElementBlock("text", _hoisted_4, vue.toDisplayString(item.icon), 1)) : vue.createCommentVNode("", true),
170
313
  vue.createElementVNode("text", _hoisted_5, vue.toDisplayString(item.label), 1)
171
314
  ]),
@@ -173,17 +316,65 @@
173
316
  item.value ? (vue.openBlock(), vue.createElementBlock("text", _hoisted_7, vue.toDisplayString(item.value), 1)) : vue.createCommentVNode("", true),
174
317
  _cache[0] || (_cache[0] = vue.createElementVNode("text", { class: "hlw-menu-list__arrow" }, "›", -1))
175
318
  ])
176
- ], 40, _hoisted_2);
319
+ ], 40, _hoisted_2$1);
177
320
  }), 128))
178
321
  ]);
179
322
  };
180
323
  }
181
324
  });
182
- const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e465b0b4"]]);
183
- exports2.HlwAd = _sfc_main$4;
184
- exports2.HlwAvatar = index$3;
185
- exports2.HlwEmpty = index$2;
186
- exports2.HlwLoading = index$1;
187
- exports2.HlwMenuList = index;
325
+ const index$1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e465b0b4"]]);
326
+ const _hoisted_1 = { class: "hlw-page" };
327
+ const _hoisted_2 = { class: "hlw-page-header" };
328
+ const _hoisted_3 = { class: "hlw-page-footer" };
329
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
330
+ __name: "index",
331
+ props: {
332
+ title: { default: "" },
333
+ isBack: { type: Boolean, default: false },
334
+ bgClass: { default: "" }
335
+ },
336
+ setup(__props) {
337
+ return (_ctx, _cache) => {
338
+ const _component_hlw_header = vue.resolveComponent("hlw-header");
339
+ const _component_scroll_view = vue.resolveComponent("scroll-view");
340
+ return vue.openBlock(), vue.createElementBlock("view", _hoisted_1, [
341
+ vue.createElementVNode("view", _hoisted_2, [
342
+ vue.renderSlot(_ctx.$slots, "header", {}, () => [
343
+ __props.title || __props.isBack ? (vue.openBlock(), vue.createBlock(_component_hlw_header, {
344
+ key: 0,
345
+ title: __props.title,
346
+ "is-back": __props.isBack,
347
+ "bg-class": __props.bgClass
348
+ }, null, 8, ["title", "is-back", "bg-class"])) : vue.createCommentVNode("", true)
349
+ ], true)
350
+ ]),
351
+ vue.createVNode(_component_scroll_view, {
352
+ class: "hlw-page-content",
353
+ "scroll-y": true,
354
+ "enable-flex": true,
355
+ enhanced: true,
356
+ "show-scrollbar": true
357
+ }, {
358
+ default: vue.withCtx(() => [
359
+ vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
360
+ ]),
361
+ _: 3
362
+ }),
363
+ vue.createElementVNode("view", _hoisted_3, [
364
+ vue.renderSlot(_ctx.$slots, "footer", {}, void 0, true)
365
+ ])
366
+ ]);
367
+ };
368
+ }
369
+ });
370
+ const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-155bc02a"]]);
371
+ exports2.HlwAd = _sfc_main$7;
372
+ exports2.HlwAvatar = index$6;
373
+ exports2.HlwCard = index$5;
374
+ exports2.HlwEmpty = index$4;
375
+ exports2.HlwHeader = index$3;
376
+ exports2.HlwLoading = index$2;
377
+ exports2.HlwMenuList = index$1;
378
+ exports2.HlwPage = index;
188
379
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
189
380
  });
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { defineComponent, resolveComponent, openBlock, createBlock, ref, computed, createElementBlock, normalizeClass, createElementVNode, toDisplayString, renderSlot, createCommentVNode, Fragment, renderList } from "vue";
2
- const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1
+ import { defineComponent, resolveComponent, openBlock, createBlock, ref, computed, createElementBlock, normalizeClass, createElementVNode, toDisplayString, renderSlot, createCommentVNode, useSlots, normalizeStyle, unref, Fragment, renderList, createVNode, withCtx } from "vue";
2
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
3
3
  ...{ name: "HlwAd" },
4
4
  __name: "index",
5
5
  props: {
@@ -30,13 +30,13 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
30
30
  };
31
31
  }
32
32
  });
33
- const _hoisted_1$3 = ["src"];
34
- const _hoisted_2$3 = {
33
+ const _hoisted_1$6 = ["src"];
34
+ const _hoisted_2$6 = {
35
35
  key: 1,
36
36
  class: "hlw-avatar__placeholder"
37
37
  };
38
- const _hoisted_3$2 = { class: "hlw-avatar__initial" };
39
- const _sfc_main$3 = /* @__PURE__ */ defineComponent({
38
+ const _hoisted_3$4 = { class: "hlw-avatar__initial" };
39
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
40
40
  __name: "index",
41
41
  props: {
42
42
  src: {},
@@ -61,8 +61,8 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
61
61
  src: __props.src,
62
62
  mode: "aspectFill",
63
63
  onError: _cache[0] || (_cache[0] = ($event) => loadError.value = true)
64
- }, null, 40, _hoisted_1$3)) : (openBlock(), createElementBlock("view", _hoisted_2$3, [
65
- createElementVNode("text", _hoisted_3$2, toDisplayString(initial.value), 1)
64
+ }, null, 40, _hoisted_1$6)) : (openBlock(), createElementBlock("view", _hoisted_2$6, [
65
+ createElementVNode("text", _hoisted_3$4, toDisplayString(initial.value), 1)
66
66
  ]))
67
67
  ], 2);
68
68
  };
@@ -75,15 +75,76 @@ const _export_sfc = (sfc, props) => {
75
75
  }
76
76
  return target;
77
77
  };
78
- const index$3 = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-7e8f98a5"]]);
79
- const _hoisted_1$2 = { class: "hlw-empty" };
80
- const _hoisted_2$2 = ["src"];
81
- const _hoisted_3$1 = {
78
+ const index$6 = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-7e8f98a5"]]);
79
+ const _hoisted_1$5 = { class: "hlw-card" };
80
+ const _hoisted_2$5 = {
81
+ key: 0,
82
+ class: "hlw-card-header"
83
+ };
84
+ const _hoisted_3$3 = { class: "flex items-center justify-between px-5 py-4 border-0 border-b border-dashed border-slate-200 bg-slate-50/30" };
85
+ const _hoisted_4$2 = { key: 0 };
86
+ const _hoisted_5$1 = { class: "text-sm font-bold text-slate-800 flex items-center gap-2 tracking-wide" };
87
+ const _hoisted_6$1 = { key: 1 };
88
+ const _hoisted_7$1 = {
89
+ key: 0,
90
+ class: "text-[10px] text-slate-400 bg-slate-50 px-2 py-1 rounded border border-slate-100 tracking-wide"
91
+ };
92
+ const _hoisted_8 = { class: "hlw-card-body" };
93
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
94
+ ...{
95
+ options: {
96
+ styleIsolation: "shared",
97
+ virtualHost: true
98
+ }
99
+ },
100
+ __name: "index",
101
+ props: {
102
+ title: { default: "" },
103
+ icon: { default: "" },
104
+ iconColor: { default: "" },
105
+ extra: { default: "" }
106
+ },
107
+ setup(__props) {
108
+ return (_ctx, _cache) => {
109
+ return openBlock(), createElementBlock("view", _hoisted_1$5, [
110
+ _ctx.$slots.header || __props.title || __props.icon || _ctx.$slots["header-left"] || _ctx.$slots["header-right"] ? (openBlock(), createElementBlock("view", _hoisted_2$5, [
111
+ renderSlot(_ctx.$slots, "header", {}, () => [
112
+ createElementVNode("view", _hoisted_3$3, [
113
+ _ctx.$slots["header-left"] || __props.title || __props.icon ? (openBlock(), createElementBlock("view", _hoisted_4$2, [
114
+ renderSlot(_ctx.$slots, "header-left", {}, () => [
115
+ createElementVNode("view", _hoisted_5$1, [
116
+ __props.icon ? (openBlock(), createElementBlock("text", {
117
+ key: 0,
118
+ class: normalizeClass([__props.icon, __props.iconColor])
119
+ }, null, 2)) : createCommentVNode("", true),
120
+ createElementVNode("text", null, toDisplayString(__props.title), 1)
121
+ ])
122
+ ], true)
123
+ ])) : createCommentVNode("", true),
124
+ _ctx.$slots["header-right"] || __props.extra ? (openBlock(), createElementBlock("view", _hoisted_6$1, [
125
+ renderSlot(_ctx.$slots, "header-right", {}, () => [
126
+ __props.extra ? (openBlock(), createElementBlock("text", _hoisted_7$1, toDisplayString(__props.extra), 1)) : createCommentVNode("", true)
127
+ ], true)
128
+ ])) : createCommentVNode("", true)
129
+ ])
130
+ ], true)
131
+ ])) : createCommentVNode("", true),
132
+ createElementVNode("view", _hoisted_8, [
133
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
134
+ ])
135
+ ]);
136
+ };
137
+ }
138
+ });
139
+ const index$5 = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-787fc3a7"]]);
140
+ const _hoisted_1$4 = { class: "hlw-empty" };
141
+ const _hoisted_2$4 = ["src"];
142
+ const _hoisted_3$2 = {
82
143
  key: 1,
83
144
  class: "hlw-empty__icon"
84
145
  };
85
146
  const _hoisted_4$1 = { class: "hlw-empty__text" };
86
- const _sfc_main$2 = /* @__PURE__ */ defineComponent({
147
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
87
148
  __name: "index",
88
149
  props: {
89
150
  text: {},
@@ -91,43 +152,125 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
91
152
  },
92
153
  setup(__props) {
93
154
  return (_ctx, _cache) => {
94
- return openBlock(), createElementBlock("view", _hoisted_1$2, [
155
+ return openBlock(), createElementBlock("view", _hoisted_1$4, [
95
156
  __props.image ? (openBlock(), createElementBlock("image", {
96
157
  key: 0,
97
158
  class: "hlw-empty__image",
98
159
  src: __props.image,
99
160
  mode: "aspectFit"
100
- }, null, 8, _hoisted_2$2)) : (openBlock(), createElementBlock("text", _hoisted_3$1, "📦")),
161
+ }, null, 8, _hoisted_2$4)) : (openBlock(), createElementBlock("text", _hoisted_3$2, "📦")),
101
162
  createElementVNode("text", _hoisted_4$1, toDisplayString(__props.text || "暂无数据"), 1),
102
163
  renderSlot(_ctx.$slots, "default", {}, void 0, true)
103
164
  ]);
104
165
  };
105
166
  }
106
167
  });
107
- const index$2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-72364322"]]);
108
- const _hoisted_1$1 = { class: "hlw-loading" };
109
- const _hoisted_2$1 = {
168
+ const index$4 = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-72364322"]]);
169
+ const _hoisted_1$3 = { class: "header-title" };
170
+ const _hoisted_2$3 = {
171
+ key: 0,
172
+ class: "header-title"
173
+ };
174
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
175
+ __name: "index",
176
+ props: {
177
+ extraHeight: { default: 0 },
178
+ bgClass: { default: "" },
179
+ isBack: { type: Boolean, default: false },
180
+ title: { default: "" }
181
+ },
182
+ emits: ["back"],
183
+ setup(__props, { emit: __emit }) {
184
+ const getNavBarContentHeight = () => {
185
+ var _a;
186
+ try {
187
+ const menuInfo = (_a = uni.getMenuButtonBoundingClientRect) == null ? void 0 : _a.call(uni);
188
+ if (!menuInfo)
189
+ return 44;
190
+ const systemInfo = uni.getSystemInfoSync();
191
+ return (menuInfo.top - systemInfo.statusBarHeight) * 2 + menuInfo.height;
192
+ } catch {
193
+ return 44;
194
+ }
195
+ };
196
+ const getStatusBarHeight = () => {
197
+ try {
198
+ const systemInfo = uni.getSystemInfoSync();
199
+ return systemInfo.statusBarHeight || 20;
200
+ } catch {
201
+ return 20;
202
+ }
203
+ };
204
+ const NAV_BAR_CONTENT_HEIGHT = getNavBarContentHeight();
205
+ const props = __props;
206
+ const emit = __emit;
207
+ const handleBack = () => {
208
+ emit("back");
209
+ uni.navigateBack({ delta: 1 });
210
+ };
211
+ const slots = useSlots();
212
+ const hasBgSlot = computed(() => !props.isBack && !!slots.bg);
213
+ const statusBarHeight = ref(getStatusBarHeight());
214
+ const totalNavBarHeight = computed(() => statusBarHeight.value + NAV_BAR_CONTENT_HEIGHT + props.extraHeight);
215
+ return (_ctx, _cache) => {
216
+ return openBlock(), createElementBlock("view", {
217
+ class: "hlw-header",
218
+ style: normalizeStyle({ height: totalNavBarHeight.value + "px" })
219
+ }, [
220
+ createElementVNode("view", {
221
+ class: normalizeClass(["header-bg-layer", hasBgSlot.value ? "" : props.bgClass])
222
+ }, [
223
+ !props.isBack ? renderSlot(_ctx.$slots, "bg", { key: 0 }, void 0, true) : createCommentVNode("", true)
224
+ ], 2),
225
+ createElementVNode("view", {
226
+ class: "status-bar-spacer",
227
+ style: normalizeStyle({ height: statusBarHeight.value + "px" })
228
+ }, null, 4),
229
+ createElementVNode("view", {
230
+ class: "header-content-area",
231
+ style: normalizeStyle({ height: unref(NAV_BAR_CONTENT_HEIGHT) + "px" })
232
+ }, [
233
+ props.isBack ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
234
+ createElementVNode("view", {
235
+ class: "header-back",
236
+ onClick: handleBack
237
+ }, [..._cache[0] || (_cache[0] = [
238
+ createElementVNode("text", { class: "iconfont icon-back" }, null, -1)
239
+ ])]),
240
+ createElementVNode("view", _hoisted_1$3, toDisplayString(props.title), 1),
241
+ _cache[1] || (_cache[1] = createElementVNode("view", { class: "header-placeholder" }, null, -1))
242
+ ], 64)) : renderSlot(_ctx.$slots, "default", { key: 1 }, () => [
243
+ props.title ? (openBlock(), createElementBlock("view", _hoisted_2$3, toDisplayString(props.title), 1)) : createCommentVNode("", true)
244
+ ], true)
245
+ ], 4)
246
+ ], 4);
247
+ };
248
+ }
249
+ });
250
+ const index$3 = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-6f338046"]]);
251
+ const _hoisted_1$2 = { class: "hlw-loading" };
252
+ const _hoisted_2$2 = {
110
253
  key: 0,
111
254
  class: "hlw-loading__text"
112
255
  };
113
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
256
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
114
257
  __name: "index",
115
258
  props: {
116
259
  text: {}
117
260
  },
118
261
  setup(__props) {
119
262
  return (_ctx, _cache) => {
120
- return openBlock(), createElementBlock("view", _hoisted_1$1, [
263
+ return openBlock(), createElementBlock("view", _hoisted_1$2, [
121
264
  _cache[0] || (_cache[0] = createElementVNode("view", { class: "hlw-loading__spinner" }, null, -1)),
122
- __props.text ? (openBlock(), createElementBlock("text", _hoisted_2$1, toDisplayString(__props.text), 1)) : createCommentVNode("", true)
265
+ __props.text ? (openBlock(), createElementBlock("text", _hoisted_2$2, toDisplayString(__props.text), 1)) : createCommentVNode("", true)
123
266
  ]);
124
267
  };
125
268
  }
126
269
  });
127
- const index$1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-14242381"]]);
128
- const _hoisted_1 = { class: "hlw-menu-list" };
129
- const _hoisted_2 = ["onTap"];
130
- const _hoisted_3 = { class: "hlw-menu-list__left" };
270
+ const index$2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-14242381"]]);
271
+ const _hoisted_1$1 = { class: "hlw-menu-list" };
272
+ const _hoisted_2$1 = ["onTap"];
273
+ const _hoisted_3$1 = { class: "hlw-menu-list__left" };
131
274
  const _hoisted_4 = {
132
275
  key: 0,
133
276
  class: "hlw-menu-list__icon"
@@ -138,7 +281,7 @@ const _hoisted_7 = {
138
281
  key: 0,
139
282
  class: "hlw-menu-list__value"
140
283
  };
141
- const _sfc_main = /* @__PURE__ */ defineComponent({
284
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
142
285
  __name: "index",
143
286
  props: {
144
287
  items: {}
@@ -155,14 +298,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
155
298
  emit("click", item);
156
299
  }
157
300
  return (_ctx, _cache) => {
158
- return openBlock(), createElementBlock("view", _hoisted_1, [
301
+ return openBlock(), createElementBlock("view", _hoisted_1$1, [
159
302
  (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
160
303
  return openBlock(), createElementBlock("view", {
161
304
  key: item.key,
162
305
  class: "hlw-menu-list__item",
163
306
  onTap: ($event) => onTap(item)
164
307
  }, [
165
- createElementVNode("view", _hoisted_3, [
308
+ createElementVNode("view", _hoisted_3$1, [
166
309
  item.icon ? (openBlock(), createElementBlock("text", _hoisted_4, toDisplayString(item.icon), 1)) : createCommentVNode("", true),
167
310
  createElementVNode("text", _hoisted_5, toDisplayString(item.label), 1)
168
311
  ]),
@@ -170,17 +313,65 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
170
313
  item.value ? (openBlock(), createElementBlock("text", _hoisted_7, toDisplayString(item.value), 1)) : createCommentVNode("", true),
171
314
  _cache[0] || (_cache[0] = createElementVNode("text", { class: "hlw-menu-list__arrow" }, "›", -1))
172
315
  ])
173
- ], 40, _hoisted_2);
316
+ ], 40, _hoisted_2$1);
174
317
  }), 128))
175
318
  ]);
176
319
  };
177
320
  }
178
321
  });
179
- const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e465b0b4"]]);
322
+ const index$1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e465b0b4"]]);
323
+ const _hoisted_1 = { class: "hlw-page" };
324
+ const _hoisted_2 = { class: "hlw-page-header" };
325
+ const _hoisted_3 = { class: "hlw-page-footer" };
326
+ const _sfc_main = /* @__PURE__ */ defineComponent({
327
+ __name: "index",
328
+ props: {
329
+ title: { default: "" },
330
+ isBack: { type: Boolean, default: false },
331
+ bgClass: { default: "" }
332
+ },
333
+ setup(__props) {
334
+ return (_ctx, _cache) => {
335
+ const _component_hlw_header = resolveComponent("hlw-header");
336
+ const _component_scroll_view = resolveComponent("scroll-view");
337
+ return openBlock(), createElementBlock("view", _hoisted_1, [
338
+ createElementVNode("view", _hoisted_2, [
339
+ renderSlot(_ctx.$slots, "header", {}, () => [
340
+ __props.title || __props.isBack ? (openBlock(), createBlock(_component_hlw_header, {
341
+ key: 0,
342
+ title: __props.title,
343
+ "is-back": __props.isBack,
344
+ "bg-class": __props.bgClass
345
+ }, null, 8, ["title", "is-back", "bg-class"])) : createCommentVNode("", true)
346
+ ], true)
347
+ ]),
348
+ createVNode(_component_scroll_view, {
349
+ class: "hlw-page-content",
350
+ "scroll-y": true,
351
+ "enable-flex": true,
352
+ enhanced: true,
353
+ "show-scrollbar": true
354
+ }, {
355
+ default: withCtx(() => [
356
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
357
+ ]),
358
+ _: 3
359
+ }),
360
+ createElementVNode("view", _hoisted_3, [
361
+ renderSlot(_ctx.$slots, "footer", {}, void 0, true)
362
+ ])
363
+ ]);
364
+ };
365
+ }
366
+ });
367
+ const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-155bc02a"]]);
180
368
  export {
181
- _sfc_main$4 as HlwAd,
182
- index$3 as HlwAvatar,
183
- index$2 as HlwEmpty,
184
- index$1 as HlwLoading,
185
- index as HlwMenuList
369
+ _sfc_main$7 as HlwAd,
370
+ index$6 as HlwAvatar,
371
+ index$5 as HlwCard,
372
+ index$4 as HlwEmpty,
373
+ index$3 as HlwHeader,
374
+ index$2 as HlwLoading,
375
+ index$1 as HlwMenuList,
376
+ index as HlwPage
186
377
  };
package/dist/style.css CHANGED
@@ -33,6 +33,10 @@
33
33
  .hlw-avatar--large .hlw-avatar__initial[data-v-7e8f98a5] { font-size: 46rpx;
34
34
  }
35
35
 
36
+ .hlw-card[data-v-787fc3a7] {
37
+ @apply bg-white rounded-xl border border-solid border-slate-200 overflow-hidden w-full;
38
+ }
39
+
36
40
  .hlw-empty[data-v-72364322] {
37
41
  display: flex;
38
42
  flex-direction: column;
@@ -53,7 +57,61 @@
53
57
  font-size: 28rpx;
54
58
  color: #bbb;
55
59
  }
56
-
60
+ .hlw-header[data-v-6f338046] {
61
+ position: sticky;
62
+ top: 0;
63
+ z-index: 999;
64
+ display: flex;
65
+ flex-direction: column;
66
+ overflow: hidden;
67
+ }
68
+ .header-bg-layer[data-v-6f338046] {
69
+ position: absolute;
70
+ top: 0;
71
+ left: 0;
72
+ right: 0;
73
+ bottom: 0;
74
+ z-index: 0;
75
+ }
76
+ .status-bar-spacer[data-v-6f338046] {
77
+ flex-shrink: 0;
78
+ width: 100%;
79
+ position: relative;
80
+ z-index: 1;
81
+ }
82
+ .header-content-area[data-v-6f338046] {
83
+ flex-shrink: 0;
84
+ width: 100%;
85
+ display: flex;
86
+ align-items: center;
87
+ position: relative;
88
+ z-index: 1;
89
+ }
90
+ .header-back[data-v-6f338046] {
91
+ width: 88rpx;
92
+ height: 100%;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ flex-shrink: 0;
97
+ }
98
+ .header-back .iconfont[data-v-6f338046] {
99
+ font-size: 40rpx;
100
+ }
101
+ .header-title[data-v-6f338046] {
102
+ flex: 1;
103
+ text-align: center;
104
+ font-size: 26rpx;
105
+ font-weight: 500;
106
+ overflow: hidden;
107
+ text-overflow: ellipsis;
108
+ white-space: nowrap;
109
+ letter-spacing: 1rpx;
110
+ }
111
+ .header-placeholder[data-v-6f338046] {
112
+ width: 88rpx;
113
+ flex-shrink: 0;
114
+ }
57
115
  .hlw-loading[data-v-14242381] {
58
116
  display: flex;
59
117
  flex-direction: column;
@@ -122,3 +180,21 @@ to { transform: rotate(360deg);
122
180
  color: #ccc;
123
181
  line-height: 1;
124
182
  }
183
+ .hlw-page[data-v-155bc02a] {
184
+ width: 100%;
185
+ height: 100vh;
186
+ display: flex;
187
+ flex-direction: column;
188
+ overflow: hidden;
189
+ }
190
+ .hlw-page-header[data-v-155bc02a] {
191
+ flex-shrink: 0;
192
+ }
193
+ .hlw-page-content[data-v-155bc02a] {
194
+ flex: 1;
195
+ height: 0;
196
+ width: 100%;
197
+ }
198
+ .hlw-page-footer[data-v-155bc02a] {
199
+ flex-shrink: 0;
200
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlw-uni/mp-vue",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "hlw-uni Vue 组件库 — 供小程序业务方使用的 UI 组件集合",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -20,7 +20,8 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "build": "vite build",
23
- "dev": "vite build --watch"
23
+ "dev": "vite build --watch",
24
+ "publish:npm": "pnpm build && npm publish --access public"
24
25
  },
25
26
  "publishConfig": {
26
27
  "access": "public"
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <view class="hlw-card">
3
+ <view
4
+ v-if="$slots.header || title || icon || $slots['header-left'] || $slots['header-right']"
5
+ class="hlw-card-header"
6
+ >
7
+ <slot name="header">
8
+ <view class="flex items-center justify-between px-5 py-4 border-0 border-b border-dashed border-slate-200 bg-slate-50/30">
9
+ <view v-if="$slots['header-left'] || title || icon">
10
+ <slot name="header-left">
11
+ <view class="text-sm font-bold text-slate-800 flex items-center gap-2 tracking-wide">
12
+ <text v-if="icon" :class="[icon, iconColor]"></text>
13
+ <text>{{ title }}</text>
14
+ </view>
15
+ </slot>
16
+ </view>
17
+ <view v-if="$slots['header-right'] || extra">
18
+ <slot name="header-right">
19
+ <text
20
+ v-if="extra"
21
+ class="text-[10px] text-slate-400 bg-slate-50 px-2 py-1 rounded border border-slate-100 tracking-wide"
22
+ >{{ extra }}</text>
23
+ </slot>
24
+ </view>
25
+ </view>
26
+ </slot>
27
+ </view>
28
+ <view class="hlw-card-body">
29
+ <slot></slot>
30
+ </view>
31
+ </view>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ interface Props {
36
+ title?: string;
37
+ icon?: string;
38
+ iconColor?: string;
39
+ extra?: string;
40
+ }
41
+
42
+ withDefaults(defineProps<Props>(), {
43
+ title: '',
44
+ icon: '',
45
+ iconColor: '',
46
+ extra: '',
47
+ });
48
+
49
+ defineOptions({
50
+ options: {
51
+ styleIsolation: 'shared',
52
+ virtualHost: true,
53
+ },
54
+ });
55
+ </script>
56
+
57
+ <style scoped>
58
+ .hlw-card {
59
+ @apply bg-white rounded-xl border border-solid border-slate-200 overflow-hidden w-full;
60
+ }
61
+ </style>
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <view class="hlw-header" :style="{ height: totalNavBarHeight + 'px' }">
3
+ <view class="header-bg-layer" :class="hasBgSlot ? '' : props.bgClass">
4
+ <slot v-if="!props.isBack" name="bg"></slot>
5
+ </view>
6
+ <view class="status-bar-spacer" :style="{ height: statusBarHeight + 'px' }"></view>
7
+ <view class="header-content-area" :style="{ height: NAV_BAR_CONTENT_HEIGHT + 'px' }">
8
+ <template v-if="props.isBack">
9
+ <view class="header-back" @click="handleBack">
10
+ <text class="iconfont icon-back"></text>
11
+ </view>
12
+ <view class="header-title">{{ props.title }}</view>
13
+ <view class="header-placeholder"></view>
14
+ </template>
15
+ <slot v-else>
16
+ <view v-if="props.title" class="header-title">{{ props.title }}</view>
17
+ </slot>
18
+ </view>
19
+ </view>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import { ref, computed, useSlots } from "vue";
24
+
25
+ const getNavBarContentHeight = (): number => {
26
+ try {
27
+ const menuInfo = uni.getMenuButtonBoundingClientRect?.();
28
+ if (!menuInfo) return 44;
29
+ const systemInfo = uni.getSystemInfoSync();
30
+ return (menuInfo.top - systemInfo.statusBarHeight!) * 2 + menuInfo.height;
31
+ } catch {
32
+ return 44;
33
+ }
34
+ };
35
+
36
+ const getStatusBarHeight = (): number => {
37
+ try {
38
+ const systemInfo = uni.getSystemInfoSync();
39
+ return systemInfo.statusBarHeight || 20;
40
+ } catch {
41
+ return 20;
42
+ }
43
+ };
44
+
45
+ const NAV_BAR_CONTENT_HEIGHT = getNavBarContentHeight();
46
+
47
+ interface Props {
48
+ extraHeight?: number;
49
+ bgClass?: string;
50
+ isBack?: boolean;
51
+ title?: string;
52
+ }
53
+
54
+ const props = withDefaults(defineProps<Props>(), {
55
+ extraHeight: 0,
56
+ bgClass: "",
57
+ isBack: false,
58
+ title: "",
59
+ });
60
+
61
+ const emit = defineEmits<{
62
+ back: [];
63
+ }>();
64
+
65
+ const handleBack = () => {
66
+ emit("back");
67
+ uni.navigateBack({ delta: 1 });
68
+ };
69
+
70
+ const slots = useSlots();
71
+ const hasBgSlot = computed(() => !props.isBack && !!slots.bg);
72
+ const statusBarHeight = ref(getStatusBarHeight());
73
+ const totalNavBarHeight = computed(() => statusBarHeight.value + NAV_BAR_CONTENT_HEIGHT + props.extraHeight);
74
+ </script>
75
+
76
+ <style lang="scss" scoped>
77
+ .hlw-header {
78
+ position: sticky;
79
+ top: 0;
80
+ z-index: 999;
81
+ display: flex;
82
+ flex-direction: column;
83
+ overflow: hidden;
84
+ }
85
+
86
+ .header-bg-layer {
87
+ position: absolute;
88
+ top: 0;
89
+ left: 0;
90
+ right: 0;
91
+ bottom: 0;
92
+ z-index: 0;
93
+ }
94
+
95
+ .status-bar-spacer {
96
+ flex-shrink: 0;
97
+ width: 100%;
98
+ position: relative;
99
+ z-index: 1;
100
+ }
101
+
102
+ .header-content-area {
103
+ flex-shrink: 0;
104
+ width: 100%;
105
+ display: flex;
106
+ align-items: center;
107
+ position: relative;
108
+ z-index: 1;
109
+ }
110
+
111
+ .header-back {
112
+ width: 88rpx;
113
+ height: 100%;
114
+ display: flex;
115
+ align-items: center;
116
+ justify-content: center;
117
+ flex-shrink: 0;
118
+
119
+ .iconfont {
120
+ font-size: 40rpx;
121
+ }
122
+ }
123
+
124
+ .header-title {
125
+ flex: 1;
126
+ text-align: center;
127
+ font-size: 26rpx;
128
+ font-weight: 500;
129
+ overflow: hidden;
130
+ text-overflow: ellipsis;
131
+ white-space: nowrap;
132
+ letter-spacing: 1rpx;
133
+ }
134
+
135
+ .header-placeholder {
136
+ width: 88rpx;
137
+ flex-shrink: 0;
138
+ }
139
+ </style>
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <view class="hlw-page">
3
+ <view class="hlw-page-header">
4
+ <slot name="header">
5
+ <hlw-header
6
+ v-if="title || isBack"
7
+ :title="title"
8
+ :is-back="isBack"
9
+ :bg-class="bgClass"
10
+ />
11
+ </slot>
12
+ </view>
13
+ <scroll-view
14
+ class="hlw-page-content"
15
+ :scroll-y="true"
16
+ :enable-flex="true"
17
+ :enhanced="true"
18
+ :show-scrollbar="true"
19
+ >
20
+ <slot></slot>
21
+ </scroll-view>
22
+ <view class="hlw-page-footer">
23
+ <slot name="footer"></slot>
24
+ </view>
25
+ </view>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ interface Props {
30
+ title?: string;
31
+ isBack?: boolean;
32
+ bgClass?: string;
33
+ }
34
+
35
+ withDefaults(defineProps<Props>(), {
36
+ title: '',
37
+ isBack: false,
38
+ bgClass: '',
39
+ });
40
+ </script>
41
+
42
+ <style lang="scss" scoped>
43
+ .hlw-page {
44
+ width: 100%;
45
+ height: 100vh;
46
+ display: flex;
47
+ flex-direction: column;
48
+ overflow: hidden;
49
+ }
50
+
51
+ .hlw-page-header {
52
+ flex-shrink: 0;
53
+ }
54
+
55
+ .hlw-page-content {
56
+ flex: 1;
57
+ height: 0;
58
+ width: 100%;
59
+ }
60
+
61
+ .hlw-page-footer {
62
+ flex-shrink: 0;
63
+ }
64
+ </style>
package/src/index.ts CHANGED
@@ -4,7 +4,10 @@
4
4
 
5
5
  export { default as HlwAd } from './components/hlw-ad/index.vue';
6
6
  export { default as HlwAvatar } from './components/hlw-avatar/index.vue';
7
+ export { default as HlwCard } from './components/hlw-card/index.vue';
7
8
  export { default as HlwEmpty } from './components/hlw-empty/index.vue';
9
+ export { default as HlwHeader } from './components/hlw-header/index.vue';
8
10
  export { default as HlwLoading } from './components/hlw-loading/index.vue';
9
11
  export { default as HlwMenuList } from './components/hlw-menu-list/index.vue';
12
+ export { default as HlwPage } from './components/hlw-page/index.vue';
10
13
  export type { MenuItem } from './components/hlw-menu-list/types';
@@ -1,7 +0,0 @@
1
- export interface AvatarProps {
2
- src?: string;
3
- name?: string;
4
- size?: 'small' | 'medium' | 'large';
5
- }
6
- declare const _default: any;
7
- export default _default;
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,52 +0,0 @@
1
- import { defineComponent, ref, computed, h } from 'vue';
2
-
3
- export interface AvatarProps {
4
- src?: string;
5
- name?: string;
6
- size?: 'small' | 'medium' | 'large';
7
- }
8
-
9
- export default defineComponent({
10
- name: 'Avatar',
11
- props: {
12
- src: { type: String },
13
- name: { type: String },
14
- size: { type: String as () => 'small' | 'medium' | 'large', default: 'medium' },
15
- },
16
- setup(props) {
17
- const loadError = ref(false);
18
-
19
- const initial = computed(() => {
20
- if (!props.name) return '?';
21
- return props.name.charAt(0).toUpperCase();
22
- });
23
-
24
- function onError() { loadError.value = true; }
25
-
26
- return () => {
27
- const sizeClass = `hlw-avatar--${props.size}`;
28
- return (
29
- // @ts-ignore - uni app nodes
30
- h('view', { class: `hlw-avatar ${sizeClass}` }, [
31
- props.src && !loadError.value
32
- ? (
33
- // @ts-ignore
34
- h('image', {
35
- class: 'hlw-avatar__image',
36
- src: props.src,
37
- mode: 'aspectFill',
38
- onError,
39
- })
40
- )
41
- : (
42
- // @ts-ignore
43
- h('view', { class: 'hlw-avatar__placeholder' }, [
44
- // @ts-ignore
45
- h('text', { class: 'hlw-avatar__initial' }, initial.value),
46
- ])
47
- ),
48
- ])
49
- );
50
- };
51
- },
52
- });
@@ -1,34 +0,0 @@
1
- import { defineComponent, useSlots, h } from 'vue';
2
-
3
- export default defineComponent({
4
- name: 'Empty',
5
- props: {
6
- text: { type: String },
7
- image: { type: String },
8
- },
9
- setup(props) {
10
- const slots = useSlots();
11
- return () => {
12
- return (
13
- // @ts-ignore
14
- h('view', { class: 'hlw-empty' }, [
15
- props.image
16
- ? (
17
- // @ts-ignore
18
- h('image', { class: 'hlw-empty__image', src: props.image, mode: 'aspectFit' })
19
- )
20
- : (
21
- // @ts-ignore
22
- h('view', { class: 'hlw-empty__icon' }, [
23
- // @ts-ignore
24
- h('text', '📦'),
25
- ])
26
- ),
27
- // @ts-ignore
28
- h('text', { class: 'hlw-empty__text' }, props.text || '暂无数据'),
29
- slots.default?.(),
30
- ])
31
- );
32
- };
33
- },
34
- });
@@ -1,29 +0,0 @@
1
- import { defineComponent, h } from 'vue';
2
-
3
- export default defineComponent({
4
- name: 'Loading',
5
- props: {
6
- text: { type: String },
7
- },
8
- setup(props) {
9
- return () => {
10
- const dots = Array.from({ length: 12 }, (_, i) =>
11
- // @ts-ignore
12
- h('view', { key: i + 1, class: 'hlw-loading__dot' }),
13
- );
14
- return (
15
- // @ts-ignore
16
- h('view', { class: 'hlw-loading' }, [
17
- // @ts-ignore
18
- h('view', { class: 'hlw-loading__spinner' }, dots),
19
- props.text
20
- ? (
21
- // @ts-ignore
22
- h('text', { class: 'hlw-loading__text' }, props.text)
23
- )
24
- : null,
25
- ])
26
- );
27
- };
28
- },
29
- });