@mdui/shared 1.0.6 → 1.0.8

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.
@@ -27,7 +27,7 @@ export function defaultValue(propertyName = 'value') {
27
27
  const converter = options.converter || defaultConverter;
28
28
  const fromAttribute = isFunction(converter)
29
29
  ? converter
30
- : converter?.fromAttribute ?? defaultConverter.fromAttribute;
30
+ : (converter?.fromAttribute ?? defaultConverter.fromAttribute);
31
31
  const newValue = fromAttribute(value, options.type);
32
32
  if (this[propertyName] !== newValue) {
33
33
  this[key] = newValue;
@@ -8,6 +8,9 @@
8
8
  * 但在 vue 的服务端渲染(ssr)时,不存在 DOM 对象,所以会把 attribute 属性设置成 attr="true" 或 attr="false"
9
9
  * 所以在 attribute 属性 attr="false" 时,需要把属性值转换为布尔值 false
10
10
  *
11
+ * 在 CSS 中选择布尔属性时,必须排除掉属性值为 false 的情况。i 表示不区分大小写。仅 public 属性需要这样处理,private 和 protected 属性不需要
12
+ * 例如::host([hide]:not([hide="false" i])) { ... }
13
+ *
11
14
  * 这段代码不能封装成函数,否则生成 custom-elements.json 会识别不了
12
15
  * 这段注释仅在这里写一次,其他地方不再重复
13
16
  *
@@ -8,11 +8,14 @@
8
8
  * 但在 vue 的服务端渲染(ssr)时,不存在 DOM 对象,所以会把 attribute 属性设置成 attr="true" 或 attr="false"
9
9
  * 所以在 attribute 属性 attr="false" 时,需要把属性值转换为布尔值 false
10
10
  *
11
+ * 在 CSS 中选择布尔属性时,必须排除掉属性值为 false 的情况。i 表示不区分大小写。仅 public 属性需要这样处理,private 和 protected 属性不需要
12
+ * 例如::host([hide]:not([hide="false" i])) { ... }
13
+ *
11
14
  * 这段代码不能封装成函数,否则生成 custom-elements.json 会识别不了
12
15
  * 这段注释仅在这里写一次,其他地方不再重复
13
16
  *
14
17
  * @see https://v3-migration.vuejs.org/zh/breaking-changes/attribute-coercion.html
15
18
  */
16
19
  export const booleanConverter = (value) => {
17
- return value !== null && value !== 'false';
20
+ return value !== null && value.toLowerCase() !== 'false';
18
21
  };
package/mixin.less CHANGED
@@ -348,21 +348,21 @@
348
348
  // @duration 为 short1、short2 等
349
349
  // @timing-function 为 standard、standard-accelerate、emphasized 等
350
350
  // @delay 可以为整数,表示毫秒;也可以为 short1、short2 等
351
- .transition(@property, @duration, @timing-function, @delay: 0) {
351
+ .transition(@prop, @duration, @timing-function, @delay: 0) {
352
352
  @durationVariable: "--mdui-motion-duration-@{duration}";
353
353
  @timingFunctionVariable: "--mdui-motion-easing-@{timing-function}";
354
354
 
355
- & when (@delay =0) {
356
- transition: ~"@{property} var(@{durationVariable}) var(@{timingFunctionVariable})";
355
+ & when (@delay = 0) {
356
+ transition: ~"@{prop} var(@{durationVariable}) var(@{timingFunctionVariable})";
357
357
  }
358
358
 
359
- & when not (@delay =0) {
359
+ & when not (@delay = 0) {
360
360
  & when (isnumber(@delay)) {
361
- transition: ~"@{property} var(@{durationVariable}) var(@{timingFunctionVariable}) @{delay}ms";
361
+ transition: ~"@{prop} var(@{durationVariable}) var(@{timingFunctionVariable}) @{delay}ms";
362
362
  }
363
363
 
364
364
  & when not (isnumber(@delay)) {
365
- transition: ~"@{property} var(@{durationVariable}) var(@{timingFunctionVariable}) var(--mdui-motion-duration-@{delay})";
365
+ transition: ~"@{prop} var(@{durationVariable}) var(@{timingFunctionVariable}) var(--mdui-motion-duration-@{delay})";
366
366
  }
367
367
  }
368
368
  }
@@ -10,7 +10,7 @@ export declare class ScrollBehaviorMixinInterface {
10
10
  scrollBehavior?: ScrollBehavior;
11
11
  scrollThreshold?: number;
12
12
  protected scrollBehaviorDefinedController: DefinedController;
13
- protected updateContainerPadding(): void;
13
+ protected setContainerPadding(action: 'add' | 'update' | 'remove', scrollTarget?: string | HTMLElement | JQ<HTMLElement>): void;
14
14
  protected hasScrollBehavior(behavior: ScrollBehavior | ScrollBehavior[]): boolean;
15
15
  }
16
16
  /**
@@ -5,6 +5,11 @@ import '@mdui/jq/methods/css.js';
5
5
  import { isNodeName } from '@mdui/jq/shared/helper.js';
6
6
  import { DefinedController } from '../controllers/defined.js';
7
7
  import { watch } from '../decorators/watch.js';
8
+ /**
9
+ * 如果同时有多个组件在同一个元素上设置了 padding-top 或 padding-bottom,则移除其中一个组件时,不移除 padding-top 或 padding-bottom
10
+ * 键为添加 padding 的目标元素,值为在分别在 top 和 bottom 上添加的组件数组
11
+ */
12
+ const weakMap = new WeakMap();
8
13
  /**
9
14
  * 滚动行为
10
15
  *
@@ -43,10 +48,12 @@ export const ScrollBehaviorMixin = (superclass) => {
43
48
  throw new Error('Must implement scrollPaddingPosition getter');
44
49
  }
45
50
  async onScrollTargetChange(oldValue, newValue) {
51
+ const hasUpdated = this.hasUpdated;
46
52
  await this.scrollBehaviorDefinedController.whenDefined();
47
- // 仅在有值切换到无值、或无值切换到有值时,更新
48
- if ((oldValue && !newValue) || (!oldValue && newValue)) {
49
- this.updateContainerPadding();
53
+ // 旧元素移除 padding,新元素添加 padding
54
+ if (hasUpdated) {
55
+ this.setContainerPadding('remove', oldValue);
56
+ this.setContainerPadding('add', newValue);
50
57
  }
51
58
  if (!this.scrollBehavior) {
52
59
  return;
@@ -61,12 +68,8 @@ export const ScrollBehaviorMixin = (superclass) => {
61
68
  newListening.addEventListener('scroll', this.onListeningScroll);
62
69
  }
63
70
  }
64
- async onScrollBehaviorChange(oldValue, newValue) {
71
+ async onScrollBehaviorChange() {
65
72
  await this.scrollBehaviorDefinedController.whenDefined();
66
- // 仅在有值切换到无值、或无值切换到有值时,更新
67
- if ((oldValue && !newValue) || (!oldValue && newValue)) {
68
- this.updateContainerPadding();
69
- }
70
73
  const listening = this.getListening(this.scrollTarget);
71
74
  if (!listening) {
72
75
  return;
@@ -83,13 +86,13 @@ export const ScrollBehaviorMixin = (superclass) => {
83
86
  super.connectedCallback();
84
87
  this.scrollBehaviorDefinedController.whenDefined().then(() => {
85
88
  this.isParentLayout = isNodeName(this.parentElement, 'mdui-layout');
86
- this.updateContainerPadding();
89
+ this.setContainerPadding('add', this.scrollTarget);
87
90
  });
88
91
  }
89
92
  disconnectedCallback() {
90
93
  super.disconnectedCallback();
91
94
  this.scrollBehaviorDefinedController.whenDefined().then(() => {
92
- this.updateContainerPadding(false);
95
+ this.setContainerPadding('remove', this.scrollTarget);
93
96
  });
94
97
  }
95
98
  /**
@@ -110,42 +113,58 @@ export const ScrollBehaviorMixin = (superclass) => {
110
113
  /**
111
114
  * 执行滚动事件,在滚动距离超过 scrollThreshold 时才会执行
112
115
  * Note: 父类可以按需实现该方法
113
- * @param isScrollingUp 是否向上滚动
114
- * @param scrollTop 距离 scrollTarget 顶部的距离
116
+ * @param _isScrollingUp 是否向上滚动
117
+ * @param _scrollTop 距离 scrollTarget 顶部的距离
115
118
  */
116
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
117
- runScrollThreshold(isScrollingUp, scrollTop) {
119
+ runScrollThreshold(_isScrollingUp, _scrollTop) {
118
120
  return;
119
121
  }
120
122
  /**
121
123
  * 执行滚动事件,会无视 scrollThreshold,始终会执行
122
- * @param isScrollingUp 是否向上滚动
123
- * @param scrollTop 距离 scrollTarget 顶部的距离
124
+ * @param _isScrollingUp 是否向上滚动
125
+ * @param _scrollTop 距离 scrollTarget 顶部的距离
124
126
  */
125
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
126
- runScrollNoThreshold(isScrollingUp, scrollTop) {
127
+ runScrollNoThreshold(_isScrollingUp, _scrollTop) {
127
128
  return;
128
129
  }
129
130
  /**
130
131
  * 更新滚动容器的 padding,避免内容被 navigation-bar 覆盖
131
- * scrollBehavior 包含 hide、shrink 时,添加 padding
132
- * @param withPadding 该值为 false 时,为移除 padding
132
+ * @param action 新增、更新、移除 padding
133
+ * @param scrollTarget 在该元素上添加、更新或移除 padding
133
134
  */
134
- updateContainerPadding(withPadding = true) {
135
- const container = this.getContainer(this.scrollTarget);
135
+ setContainerPadding(action, scrollTarget) {
136
+ const container = this.getContainer(scrollTarget);
136
137
  if (!container || this.isParentLayout) {
137
138
  return;
138
139
  }
139
- const propName = this.scrollPaddingPosition === 'top' ? 'paddingTop' : 'paddingBottom';
140
- if (withPadding) {
141
- const propValue = this.getListening(this.scrollTarget) &&
142
- ['fixed', 'absolute'].includes($(this).css('position'))
140
+ const position = this.scrollPaddingPosition;
141
+ const propName = position === 'top' ? 'paddingTop' : 'paddingBottom';
142
+ if (action === 'add' || action === 'update') {
143
+ const propValue = ['fixed', 'absolute'].includes($(this).css('position'))
143
144
  ? this.offsetHeight
144
145
  : null;
145
146
  $(container).css({ [propName]: propValue });
147
+ // 添加 padding 时,weakMap 中添加指定元素
148
+ if (action === 'add' && propValue !== null) {
149
+ const options = weakMap.get(container) ?? { top: [], bottom: [] };
150
+ options[position].push(this);
151
+ weakMap.set(container, options);
152
+ }
146
153
  }
147
- else {
148
- $(container).css({ [propName]: null });
154
+ // 如果 weakMap 中指定元素的计数为 0,则移除 padding
155
+ if (action === 'remove') {
156
+ const options = weakMap.get(container);
157
+ if (!options) {
158
+ return;
159
+ }
160
+ const index = options[position].indexOf(this);
161
+ if (index > -1) {
162
+ options[position].splice(index, 1);
163
+ weakMap.set(container, options);
164
+ }
165
+ if (!options[position].length) {
166
+ $(container).css({ [propName]: null });
167
+ }
149
168
  }
150
169
  }
151
170
  onListeningScroll() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mdui/shared",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "mdui 项目的公共部分",
5
5
  "type": "module",
6
6
  "files": [
@@ -27,10 +27,10 @@
27
27
  },
28
28
  "homepage": "https://github.com/zdhxiong/mdui#readme",
29
29
  "dependencies": {
30
- "@lit/reactive-element": "^2.0.4",
31
- "lit": "^3.1.4",
32
- "ssr-window": "^4.0.2",
33
- "tslib": "^2.6.3",
34
- "@mdui/jq": "^3.0.2"
30
+ "@lit/reactive-element": "^2.1.0",
31
+ "lit": "^3.3.0",
32
+ "ssr-window": "^5.0.0",
33
+ "tslib": "^2.8.1",
34
+ "@mdui/jq": "^3.0.3"
35
35
  }
36
36
  }