papayaui 0.0.53 → 0.1.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 (97) hide show
  1. package/.DS_Store +0 -0
  2. package/components/badge/badge.vue +9 -14
  3. package/components/badge/demo.vue +11 -6
  4. package/components/bottom-popup/bottom-popup.vue +30 -16
  5. package/components/button/button.vue +81 -30
  6. package/components/button/demo.vue +2 -4
  7. package/components/calendar/calendar-wrapper.vue +52 -37
  8. package/components/calendar/calendar.vue +9 -5
  9. package/components/cascader/cascader.vue +105 -54
  10. package/components/cascader/search-view.vue +28 -14
  11. package/components/cell/cell.vue +26 -23
  12. package/components/cell-group/cell-group.vue +4 -2
  13. package/components/checkbox/checkbox.vue +12 -11
  14. package/components/checkbox-btns/checkbox-btns.vue +8 -5
  15. package/components/checkbox-group/checkbox-group.vue +4 -2
  16. package/components/container/container.vue +14 -7
  17. package/components/count-to/count-to.vue +4 -6
  18. package/components/date-picker/date-picker.vue +42 -22
  19. package/components/empty/empty.vue +6 -4
  20. package/components/env-view/env-view.vue +3 -1
  21. package/components/field/field.vue +15 -12
  22. package/components/form/demo.vue +10 -10
  23. package/components/form/form.vue +5 -3
  24. package/components/form-item/form-item.vue +5 -8
  25. package/components/icon/icon.vue +5 -3
  26. package/components/image/demo.vue +1 -2
  27. package/components/image/image.vue +8 -6
  28. package/components/input-number/input-number.vue +25 -33
  29. package/components/list/list.vue +10 -3
  30. package/components/list-item/list-item.vue +71 -0
  31. package/components/loading-icon/loading-icon.vue +7 -5
  32. package/components/loadmore/loadmore.vue +6 -4
  33. package/components/menu/menu.vue +18 -19
  34. package/components/menu-item/menu-item.vue +42 -38
  35. package/components/nav-bar/demo.vue +1 -1
  36. package/components/nav-bar/nav-bar.vue +12 -7
  37. package/components/number-input/number-input.vue +5 -3
  38. package/components/overlay/overlay.vue +4 -2
  39. package/components/picker-popup/picker-popup.vue +38 -27
  40. package/components/picker-view/picker-view.vue +12 -15
  41. package/components/popover/popover.vue +13 -18
  42. package/components/popup/popup.vue +8 -6
  43. package/components/radio/radio.vue +12 -11
  44. package/components/radio-group/radio-group.vue +4 -2
  45. package/components/safe-bottom/safe-bottom.vue +4 -2
  46. package/components/search/search.vue +7 -5
  47. package/components/section/section.vue +7 -5
  48. package/components/sidebar/sidebar.vue +4 -2
  49. package/components/sidebar-item/sidebar-item.vue +7 -6
  50. package/components/sort-label/sort-label.vue +9 -7
  51. package/components/steps/steps.vue +13 -18
  52. package/components/sticky/demo.vue +1 -1
  53. package/components/sticky/sticky.vue +148 -255
  54. package/components/swipe-cell/swipe-cell.vue +12 -10
  55. package/components/switch/switch.vue +6 -12
  56. package/components/tabs/tabs.vue +12 -10
  57. package/components/tag/tag.vue +5 -5
  58. package/components/textarea/textarea.vue +7 -11
  59. package/components/tooltip/tooltip.vue +11 -16
  60. package/components/transition/transition.vue +5 -3
  61. package/components/watermark/watermark.vue +7 -5
  62. package/core/{useCalendar.ts → useCalendar/index.ts} +1 -1
  63. package/core/useCascader/index.ts +51 -0
  64. package/core/{tests/useCountTo.test.ts → useCountTo/index.test.ts} +1 -1
  65. package/core/{useCountTo.ts → useCountTo/index.ts} +1 -1
  66. package/core/{tests/useDatePicker.test.ts → useDatePicker/index.test.ts} +1 -1
  67. package/core/{useDatePicker.ts → useDatePicker/index.ts} +2 -2
  68. package/{hooks/form → core/useForm}/useFormValidate.ts +4 -2
  69. package/core/{useInputNumber.ts → useInputNumber/index.ts} +1 -1
  70. package/core/useNamespace/index.ts +106 -0
  71. package/core/{useSelect.ts → useSelect/index.ts} +1 -1
  72. package/core/{useSwitch.ts → useSwitch/index.ts} +1 -1
  73. package/core/useTree/index.test.ts +38 -0
  74. package/core/useTree/index.ts +160 -0
  75. package/core/useVirtualList/demo.vue +48 -0
  76. package/core/useVirtualList/index.ts +374 -0
  77. package/fonts/.DS_Store +0 -0
  78. package/hooks/index.ts +1 -3
  79. package/hooks/useRect.ts +17 -0
  80. package/images/.DS_Store +0 -0
  81. package/images/demo.jpeg +0 -0
  82. package/package.json +1 -1
  83. package/request/utils.ts +1 -12
  84. package/styles/color.scss +3 -0
  85. package/styles/index.scss +1 -0
  86. package/types/index.ts +5 -2
  87. package/utils/common.ts +2 -2
  88. package/utils/lang.ts +12 -0
  89. package/components/cascader/list-item.vue +0 -51
  90. package/components/popup/popup.bak.vue +0 -224
  91. package/core/useTree.ts +0 -156
  92. package/utils/style.ts +0 -30
  93. /package/{hooks/form → core/useForm}/index.ts +0 -0
  94. /package/{hooks/form → core/useForm}/message.ts +0 -0
  95. /package/core/{demo/useList.vue → useList/demo.vue} +0 -0
  96. /package/core/{useList.ts → useList/index.ts} +0 -0
  97. /package/core/{tests/useSwitch.test.ts → useSwitch/index.test.ts} +0 -0
package/.DS_Store CHANGED
Binary file
@@ -1,16 +1,9 @@
1
1
  <template>
2
- <view
3
- :class="
4
- computedClass('badge', {
5
- 'badge--dot': dot,
6
- 'badge--fixed': !!$slots.default,
7
- })
8
- "
9
- >
2
+ <view :class="[ns.b(), ns.is('dot', dot), ns.is('fixed', !!$slots.default)]">
10
3
  <slot></slot>
11
4
  <view
12
5
  v-if="visible"
13
- :class="computedClass('badge-content')"
6
+ :class="ns.e('content')"
14
7
  :style="{
15
8
  backgroundColor: color,
16
9
  top: getUnitValue(offset[1].toString()),
@@ -25,8 +18,8 @@
25
18
 
26
19
  <script lang="ts" setup>
27
20
  import { computed, CSSProperties } from 'vue'
21
+ import useNamespace, { defaultNamespace } from '../../core/useNamespace'
28
22
  import { getUnitValue } from '../../utils'
29
- import { computedClass, PREFIX } from '../../utils/style'
30
23
 
31
24
  export interface BadgeProps {
32
25
  /** 徽标内容 */
@@ -45,9 +38,11 @@ export interface BadgeProps {
45
38
  show?: boolean
46
39
  }
47
40
 
41
+ const ns = useNamespace('badge')
42
+
48
43
  const props = withDefaults(defineProps<BadgeProps>(), {
49
44
  content: undefined,
50
- color: `var(--${PREFIX}-color-danger)`,
45
+ color: `var(--${defaultNamespace}-color-danger)`,
51
46
  max: undefined,
52
47
  offset: () => [0, 0],
53
48
  showZero: false,
@@ -75,7 +70,7 @@ const value = computed(() => {
75
70
  .#{$prefix}-badge {
76
71
  position: relative;
77
72
  display: inline-block;
78
- &-content {
73
+ &__content {
79
74
  position: relative;
80
75
  display: flex;
81
76
  flex-direction: row;
@@ -86,12 +81,12 @@ const value = computed(() => {
86
81
  padding: 2px 5px;
87
82
  border-radius: 100px;
88
83
  }
89
- &--dot &-content {
84
+ &--dot &__content {
90
85
  padding: 0;
91
86
  width: 8px;
92
87
  height: 8px;
93
88
  }
94
- &--fixed &-content {
89
+ &--fixed &__content {
95
90
  position: absolute;
96
91
  transform: translate(50%, -50%);
97
92
  transform-origin: 100%;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <DocDemoBlock title="基础用法" card>
3
- <view class="grid grid-cols-4">
3
+ <view class="demo-badge">
4
4
  <pa-badge content="5">
5
5
  <view class="demo-block"></view>
6
6
  </pa-badge>
@@ -16,7 +16,7 @@
16
16
  </view>
17
17
  </DocDemoBlock>
18
18
  <DocDemoBlock title="最大值" card>
19
- <view class="grid grid-cols-4">
19
+ <view class="demo-badge">
20
20
  <pa-badge content="999" :max="9">
21
21
  <view class="demo-block"></view>
22
22
  </pa-badge>
@@ -29,7 +29,7 @@
29
29
  </view>
30
30
  </DocDemoBlock>
31
31
  <DocDemoBlock title="自定义颜色" card>
32
- <view class="grid grid-cols-4">
32
+ <view class="demo-badge">
33
33
  <pa-badge content="5" color="#1989fa">
34
34
  <view class="demo-block"></view>
35
35
  </pa-badge>
@@ -45,7 +45,7 @@
45
45
  </view>
46
46
  </DocDemoBlock>
47
47
  <DocDemoBlock title="自定义内容" card>
48
- <view class="grid grid-cols-4">
48
+ <view class="demo-badge">
49
49
  <pa-badge>
50
50
  <view class="demo-block"></view>
51
51
  <template #content>
@@ -61,7 +61,7 @@
61
61
  </view>
62
62
  </DocDemoBlock>
63
63
  <DocDemoBlock title="自定义位置" card>
64
- <view class="grid grid-cols-4">
64
+ <view class="demo-badge">
65
65
  <pa-badge content="99" :offset="[-10, -10]">
66
66
  <view class="demo-block"></view>
67
67
  </pa-badge>
@@ -71,7 +71,7 @@
71
71
  </view>
72
72
  </DocDemoBlock>
73
73
  <DocDemoBlock title="独立展示" card>
74
- <view class="grid grid-cols-4">
74
+ <view class="demo-badge">
75
75
  <pa-badge content="9" />
76
76
  <pa-badge content="99" />
77
77
  </view>
@@ -84,6 +84,11 @@ import DocDemoBlock from '../../doc/doc-demo-block.vue'
84
84
  </script>
85
85
 
86
86
  <style lang="scss" scoped>
87
+ .demo-badge {
88
+ :deep(.pa-badge) {
89
+ margin-right: 42px;
90
+ }
91
+ }
87
92
  .demo-block {
88
93
  width: 40px;
89
94
  height: 40px;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <Popup
3
- :custom-class="computedClass('bottom-popup')"
3
+ :custom-class="ns.b()"
4
4
  :show="show"
5
5
  position="bottom"
6
6
  :height="height"
@@ -13,28 +13,19 @@
13
13
  :safe-area-inset-bottom="false"
14
14
  @update:show="emit('update:show', !!$event)"
15
15
  >
16
- <view
17
- class="flex flex-col"
18
- :class="[
19
- computedClass('bottom-popup__wrapper'),
20
- { 'safe-bottom-padding': safeAreaInsetBottom },
21
- ]"
22
- >
23
- <view
24
- :class="computedClass('bottom-popup__header')"
25
- class="width-full flex items-center justify-center flex-shrink-0"
26
- >
16
+ <view :class="[ns.e('wrapper'), { 'safe-bottom-padding': safeAreaInsetBottom }]">
17
+ <view :class="ns.e('header')">
27
18
  <slot name="before-title"></slot>
28
- <text class="text-32 leading-40 text-block font-w-500 mr-8">{{ title }}</text>
19
+ <text :class="ns.e('title')">{{ title }}</text>
29
20
  <slot name="after-title"></slot>
30
21
  </view>
31
22
 
32
- <view class="flex flex-col flex-1" style="overflow: hidden">
23
+ <view :class="ns.e('body')">
33
24
  <view class="flex-1" style="overflow: hidden">
34
25
  <slot></slot>
35
26
  </view>
36
27
 
37
- <view v-if="$slots.footer" :class="computedClass('bottom-popup__footer')">
28
+ <view v-if="$slots.footer" :class="ns.e('footer')">
38
29
  <slot name="footer"></slot>
39
30
  </view>
40
31
  </view>
@@ -44,7 +35,7 @@
44
35
 
45
36
  <script lang="ts" setup>
46
37
  import { CSSProperties, toRefs } from 'vue'
47
- import { computedClass } from '../../utils/style'
38
+ import useNamespace from '../../core/useNamespace'
48
39
  import Popup from '../popup/popup.vue'
49
40
 
50
41
  export interface BottomPopupProps {
@@ -70,6 +61,8 @@ export interface BottomPopupProps {
70
61
  safeAreaInsetBottom?: boolean
71
62
  }
72
63
 
64
+ const ns = useNamespace('bottom-popup')
65
+
73
66
  const props = withDefaults(defineProps<BottomPopupProps>(), {
74
67
  show: false,
75
68
  title: undefined,
@@ -95,14 +88,35 @@ const emit = defineEmits<{
95
88
  .#{$prefix}-bottom-popup {
96
89
  &__wrapper {
97
90
  position: relative;
91
+ display: flex;
92
+ flex-direction: column;
98
93
  height: 100%;
99
94
  border-radius: 24rpx 24rpx 0 0;
100
95
  }
101
96
 
102
97
  &__header {
103
98
  position: relative;
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ flex-shrink: 0;
103
+ width: 100%;
104
104
  height: 88rpx;
105
105
  }
106
+ &__title {
107
+ font-size: 32rpx;
108
+ line-height: 40rpx;
109
+ color: _var(color-black);
110
+ font-weight: 500;
111
+ margin-right: 8rpx;
112
+ }
113
+
114
+ &__body {
115
+ display: flex;
116
+ flex-direction: column;
117
+ flex: 1;
118
+ overflow: hidden;
119
+ }
106
120
 
107
121
  &__footer {
108
122
  width: 100%;
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <button
3
- :class="[computedClass('button'), `button--${type}`, plain ? `button--plain` : '']"
3
+ :class="[ns.b(), ns.m(type), ns.m(size), ns.is('block', block), ns.is('plain', plain)]"
4
4
  :style="customStyle"
5
- :hover-class="computedClass('button--hover')"
5
+ :hover-class="ns.m('hover')"
6
6
  :disabled="disabled"
7
7
  :plain="plain"
8
8
  :open-type="openType"
@@ -15,7 +15,7 @@
15
15
  @chooseavatar="emit('chooseavatar', $event)"
16
16
  @tap="onClick"
17
17
  >
18
- <view class="height-full flex items-center justify-center">
18
+ <view :class="ns.e('content')">
19
19
  <Loadmore
20
20
  v-if="localLoading"
21
21
  class="mr-4"
@@ -40,9 +40,9 @@
40
40
  <script lang="ts" setup>
41
41
  import { getUnitValue } from '../../utils/common'
42
42
  import { computed, CSSProperties, ref, StyleValue } from 'vue'
43
- import { computedClass } from '../../utils/style'
44
43
  import Icon from '../icon/icon.vue'
45
44
  import Loadmore from '../loadmore/loadmore.vue'
45
+ import useNamespace from '../../core/useNamespace'
46
46
 
47
47
  export interface ButtonProps {
48
48
  /** 按钮类型 */
@@ -51,6 +51,8 @@ export interface ButtonProps {
51
51
  width?: string
52
52
  /** 按钮高度 */
53
53
  height?: string
54
+ /**尺寸 */
55
+ size?: 'large' | 'normal' | 'small' | 'mini'
54
56
  /** 字体大小 */
55
57
  fontSize?: string
56
58
  /** 是否为块级元素 */
@@ -101,12 +103,15 @@ export interface ButtonProps {
101
103
  showMessageCard?: boolean
102
104
  }
103
105
 
106
+ const ns = useNamespace('button')
107
+
104
108
  const props = withDefaults(defineProps<ButtonProps>(), {
105
109
  type: 'primary',
106
- width: 'auto',
107
- height: '42px',
108
- fontSize: '14px',
109
- round: '3px',
110
+ width: undefined,
111
+ height: undefined,
112
+ size: 'normal',
113
+ fontSize: undefined,
114
+ round: undefined,
110
115
  icon: undefined,
111
116
  syncClick: undefined,
112
117
  customStyle: undefined,
@@ -136,16 +141,24 @@ const clickLoading = ref<boolean>()
136
141
  const localLoading = computed(() => props.loading || clickLoading.value)
137
142
 
138
143
  const customStyle = computed<StyleValue>(() => {
139
- return {
144
+ const style: CSSProperties = {
140
145
  ...props.customStyle,
141
- display: props.block ? 'block' : 'inline-block',
142
- width: props.block
146
+ }
147
+ if (props.width) {
148
+ style.width = props.block
143
149
  ? getUnitValue(props.width === 'auto' ? '100%' : props.width)
144
- : getUnitValue(props.width),
145
- height: getUnitValue(props.height),
146
- fontSize: getUnitValue(props.fontSize),
147
- borderRadius: props.round === true ? getUnitValue(props.height) : getUnitValue(props.round),
150
+ : getUnitValue(props.width)
151
+ }
152
+ if (props.height) {
153
+ style.height = getUnitValue(props.height)
154
+ }
155
+ if (props.fontSize) {
156
+ style.fontSize = getUnitValue(props.fontSize)
157
+ }
158
+ if (props.round) {
159
+ style.borderRadius = props.round === true ? '100px' : getUnitValue(props.round)
148
160
  }
161
+ return style
149
162
  })
150
163
 
151
164
  const onClick = async (event: MouseEvent) => {
@@ -167,9 +180,20 @@ const onClick = async (event: MouseEvent) => {
167
180
  <style lang="scss" scoped>
168
181
  @import '../../styles/vars.scss';
169
182
  .#{$prefix}-button {
170
- padding: _var(button-padding, 12px);
183
+ display: inline-block;
184
+ height: 44px;
185
+ line-height: 1.2;
186
+ margin: _var(button-margin, 0);
171
187
  border: 1px solid transparent;
172
188
  box-sizing: border-box;
189
+
190
+ &__content {
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ height: 100%;
195
+ }
196
+
173
197
  &::before {
174
198
  position: absolute;
175
199
  top: 50%;
@@ -187,42 +211,69 @@ const onClick = async (event: MouseEvent) => {
187
211
  &::after {
188
212
  border: none;
189
213
  }
214
+
190
215
  &--hover {
191
216
  &::before {
192
217
  opacity: 0.1;
193
218
  }
194
219
  }
195
- &.button--default {
220
+
221
+ &--default {
196
222
  color: _var(color-black);
197
223
  background-color: #fff;
198
224
  border-color: #ebedf0;
199
225
  }
200
- &.button--primary {
226
+ &--primary {
201
227
  color: #fff;
202
228
  background-color: _var(color-primary);
203
229
  border-color: _var(color-primary);
204
- &.button--plain {
205
- color: _var(color-primary);
206
- }
207
230
  }
208
- &.button--warning {
231
+ &--warning {
209
232
  color: #fff;
210
233
  background-color: _var(color-warning);
211
234
  border-color: _var(color-warning);
212
- &.button--plain {
213
- color: _var(color-warning);
214
- }
215
235
  }
216
- &.button--danger {
236
+ &--danger {
217
237
  color: #fff;
218
238
  background-color: _var(color-danger);
219
239
  border-color: _var(color-danger);
220
- &.button--plain {
221
- color: _var(color-danger);
222
- }
223
240
  }
224
- &[plain] {
241
+
242
+ &--large {
243
+ width: 100%;
244
+ height: 50px;
245
+ }
246
+ &--normal {
247
+ font-size: 14px;
248
+ padding: _var(button-padding, 0 15px);
249
+ }
250
+ &--small {
251
+ height: 32px;
252
+ font-size: 12px;
253
+ padding: _var(button-padding, 0 8px);
254
+ }
255
+ &--mini {
256
+ height: 24px;
257
+ font-size: 10px;
258
+ padding: _var(button-padding, 0 4px);
259
+ }
260
+
261
+ &--block {
262
+ display: block;
263
+ width: 100%;
264
+ }
265
+
266
+ &--plain {
225
267
  background-color: transparent;
268
+ &.#{$prefix}-button--primary {
269
+ color: _var(color-primary);
270
+ }
271
+ &.#{$prefix}-button--warning {
272
+ color: _var(color-warning);
273
+ }
274
+ &.#{$prefix}-button--danger {
275
+ color: _var(color-danger);
276
+ }
226
277
  }
227
278
  &[disabled]:not([type]) {
228
279
  color: _var(color-black);
@@ -60,10 +60,8 @@ const onClick = () => {
60
60
  }
61
61
  </script>
62
62
 
63
- <style lang="scss">
63
+ <style lang="scss" scoped>
64
64
  .demo-button {
65
- button {
66
- margin: 0 16px 16px 0;
67
- }
65
+ --pa-button-margin: 0 16px 16px 0;
68
66
  }
69
67
  </style>
@@ -1,52 +1,55 @@
1
1
  <template>
2
- <view :class="computedClass('calendar-wrapper')">
3
- <view :class="computedClass('calendar-header')">
4
- <view v-if="showTitle" :class="computedClass('calendar-header__title')">{{ title }}</view>
5
- <view v-if="showSubtitle" :class="computedClass('calendar-header__subtitle')">
2
+ <view :class="ns.b('wrapper')">
3
+ <view :class="ns.b('header')">
4
+ <view v-if="showTitle" :class="ns.be('header', 'title')">{{ title }}</view>
5
+ <view v-if="showSubtitle" :class="ns.be('header', 'subtitle')">
6
6
  {{ months[monthCurrent]?.date.format('YYYY年M月') || '' }}
7
7
  </view>
8
- <view :class="computedClass('calendar__weekdays')">
9
- <view v-for="item in weekdays" :key="item" :class="computedClass('calendar__weekday')">
8
+ <view :class="ns.e('weekdays')">
9
+ <view v-for="item in weekdays" :key="item" :class="ns.e('weekday')">
10
10
  {{ item }}
11
11
  </view>
12
12
  </view>
13
13
  </view>
14
- <scroll-view
15
- scroll-y
16
- :scroll-top="scrollTop"
17
- :class="computedClass('calendar-body')"
18
- @scroll="onScroll"
19
- >
20
- <view
21
- v-for="(monthItem, monthIndex) in months"
22
- :key="monthIndex"
23
- :class="computedClass('calendar__month')"
24
- >
25
- <view v-if="monthIndex !== 0" :class="computedClass('calendar__month-title')">
14
+ <scroll-view scroll-y :scroll-top="scrollTop" :class="ns.b('body')" @scroll="onThrottleScroll">
15
+ <view v-for="(monthItem, monthIndex) in months" :key="monthIndex" :class="ns.e('month')">
16
+ <view v-if="monthIndex !== 0" :class="ns.e('month-title')">
26
17
  {{ monthItem.date.format('YYYY年M月') }}
27
18
  </view>
28
- <view :class="computedClass('calendar__days')">
29
- <view v-if="showMark" :class="computedClass('calendar__month-mark')">
30
- {{ monthItem.date.month() + 1 }}
31
- </view>
32
- <view
33
- v-for="(dayItem, dayIndex) in getDays(monthItem.date)"
34
- :key="dayItem.text"
35
- :class="computedClass('calendar__day', `calendar__day--${dayItem.type}`)"
36
- :style="{ gridColumnStart: dayIndex === 0 ? monthItem.dayOfWeekStart + 1 : 'auto' }"
37
- @tap="onSelect(dayItem)"
38
- >
39
- <view :class="computedClass('calendar__top-info')">{{ dayItem.topInfo }}</view>
40
- <view :class="computedClass('calendar__day__select')">
41
- {{ dayItem.text }}
19
+ <view
20
+ :class="ns.e('days')"
21
+ :style="{
22
+ height: isVisualRange(monthIndex)
23
+ ? 'auto'
24
+ : getUnitValue(
25
+ Math.ceil((monthItem.dayOfWeekStart + monthItem.dayLength) / 7) * 64,
26
+ 'px',
27
+ ),
28
+ }"
29
+ >
30
+ <template v-if="isVisualRange(monthIndex)">
31
+ <view v-if="showMark" :class="ns.e('month-mark')">
32
+ {{ monthItem.date.month() + 1 }}
42
33
  </view>
43
- <view :class="computedClass('calendar__bottom-info')">{{ dayItem.bottomInfo }}</view>
44
- </view>
34
+ <view
35
+ v-for="(dayItem, dayIndex) in getDays(monthItem.date)"
36
+ :key="dayItem.text"
37
+ :class="[ns.e('day'), ns.em('day', dayItem.type)]"
38
+ :style="{ gridColumnStart: dayIndex === 0 ? monthItem.dayOfWeekStart + 1 : 'auto' }"
39
+ @tap="onSelect(dayItem)"
40
+ >
41
+ <view :class="ns.e('top-info')">{{ dayItem.topInfo }}</view>
42
+ <view :class="ns.e('day__select')">
43
+ {{ dayItem.text }}
44
+ </view>
45
+ <view :class="ns.e('bottom-info')">{{ dayItem.bottomInfo }}</view>
46
+ </view>
47
+ </template>
45
48
  </view>
46
49
  </view>
47
50
  <SafeBottom v-if="!showConfirm && safeAreaInsetBottom" />
48
51
  </scroll-view>
49
- <view v-if="showConfirm" :class="computedClass('calendar-footer')" class="px-26 py-15">
52
+ <view v-if="showConfirm" :class="ns.b('footer')" class="px-26 py-15">
50
53
  <ButtonComponent type="primary" block :disabled="!confirmEnabled" @click="onConfirm">
51
54
  {{ confirmEnabled ? confirmText : confirmDisabledText }}
52
55
  </ButtonComponent>
@@ -61,9 +64,10 @@ import { computed, getCurrentInstance, nextTick, ref, toRefs } from 'vue'
61
64
  import useCalendar, { DayItem, FirstDayOfWeekType } from '../../core/useCalendar'
62
65
  import { useRect } from '../../hooks'
63
66
  import { EventDetail } from '../../types'
64
- import { computedClass } from '../../utils/style'
65
67
  import ButtonComponent from '../button/button.vue'
66
68
  import SafeBottom from '../safe-bottom/safe-bottom.vue'
69
+ import { getUnitValue, throttle } from '../../utils'
70
+ import useNamespace from '../../core/useNamespace'
67
71
 
68
72
  export interface CalendarWrapperProps {
69
73
  /** 选择类型: single表示选择单个日期,multiple表示选择多个日期,range表示选择日期区间 */
@@ -103,6 +107,8 @@ export interface CalendarWrapperProps {
103
107
  maxRange?: number
104
108
  }
105
109
 
110
+ const ns = useNamespace('calendar')
111
+
106
112
  const props = withDefaults(defineProps<CalendarWrapperProps>(), {
107
113
  type: 'single',
108
114
  title: '日期选择',
@@ -155,6 +161,14 @@ const confirmEnabled = computed<boolean>(() => {
155
161
  return selectedItems.value.length > 0
156
162
  })
157
163
 
164
+ /**
165
+ * 月份是否在显示范围
166
+ */
167
+ const isVisualRange = (monthIndex: number) => {
168
+ const diff = monthIndex - monthCurrent.value
169
+ return diff >= -1 && diff <= 1
170
+ }
171
+
158
172
  const onScroll = (e: EventDetail<{ scrollTop: number }>) => {
159
173
  let current = 0
160
174
  const scrollTop = e.detail.scrollTop
@@ -165,10 +179,11 @@ const onScroll = (e: EventDetail<{ scrollTop: number }>) => {
165
179
  }
166
180
  monthCurrent.value = current
167
181
  }
182
+ const onThrottleScroll = throttle(onScroll, 100, { trailing: true })
168
183
 
169
184
  const updateMonthTop = () => {
170
185
  if (!instance) return
171
- useRect(instance, '.pa-calendar__month', true).then((nodes) => {
186
+ useRect(instance, `.${ns.e('month')}`, true).then((nodes) => {
172
187
  const tops = (nodes ?? []).reduce((result, node) => {
173
188
  result.push((result[result.length - 1] || 0) + node.height)
174
189
  return result
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <Popup
3
3
  v-if="poppable"
4
- :custom-class="computedClass('calendar')"
4
+ :custom-class="ns.b()"
5
5
  :show="show"
6
6
  :height="getUnitValue(height)"
7
7
  :closeable="showTitle || showSubtitle"
@@ -20,7 +20,7 @@
20
20
  </Popup>
21
21
  <view
22
22
  v-else
23
- :class="computedClass('calendar')"
23
+ :class="ns.b()"
24
24
  :style="{ height: getUnitValue(height), borderRadius: getUnitValue($attrs.round as string ?? '0') }"
25
25
  >
26
26
  <CalendarWrapper
@@ -36,10 +36,10 @@
36
36
 
37
37
  <script lang="ts" setup>
38
38
  import { Dayjs } from 'dayjs'
39
- import { onMounted, ref, watch } from 'vue'
39
+ import { onMounted, ref, watch, nextTick } from 'vue'
40
40
  import { DayItem } from '../../core/useCalendar'
41
+ import useNamespace from '../../core/useNamespace'
41
42
  import { getUnitValue } from '../../utils'
42
- import { computedClass } from '../../utils/style'
43
43
  import CalendarWrapper, { CalendarWrapperProps } from '../calendar/calendar-wrapper.vue'
44
44
  import Popup, { PopupProps } from '../popup/popup.vue'
45
45
 
@@ -62,6 +62,8 @@ export interface CalendarProps
62
62
  showSubtitle?: boolean
63
63
  }
64
64
 
65
+ const ns = useNamespace('calendar')
66
+
65
67
  const props = withDefaults(defineProps<CalendarProps>(), {
66
68
  poppable: true,
67
69
  show: false,
@@ -85,7 +87,9 @@ watch(
85
87
  () => props.show,
86
88
  (newVal, oldVal) => {
87
89
  if (newVal !== oldVal && newVal && props.poppable) {
88
- wrapperRef.value?.updateMonthTop()
90
+ nextTick(() => {
91
+ wrapperRef.value?.updateMonthTop()
92
+ })
89
93
  }
90
94
  },
91
95
  )