papayaui 0.2.18 → 0.2.19

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.
@@ -1,5 +1,7 @@
1
1
  @import '../../styles/vars.scss';
2
2
  .#{$prefix}-collapse {
3
+ position: relative;
4
+
3
5
  &--border::after {
4
6
  position: absolute;
5
7
  box-sizing: border-box;
@@ -5,42 +5,45 @@
5
5
  </template>
6
6
 
7
7
  <script setup lang="ts">
8
- import { provide, ref, watch, type Ref } from 'vue'
8
+ import { computed, ref, watch } from 'vue'
9
9
  import useNamespace from '../../core/useNamespace'
10
- import type { CollapseItemInstance } from '../collapse-item/collapse-item.vue'
11
- import type { CollapseItemValue } from '../collapse-item/props'
10
+ import type { CollapseItemInstance, CollapseItemValue } from '../collapse-item/props'
12
11
  import { collapseEmits, collapseProps } from './props'
13
12
 
14
- export interface CollapseProvideData {
15
- modelValue: Ref<CollapseItemValue[]>
16
- setChildren: (node: CollapseItemInstance) => void
17
- onChildExpand: (name: CollapseItemValue, expanded: boolean) => void
18
- }
19
-
20
13
  const ns = useNamespace('collapse')
21
14
 
22
15
  const props = defineProps(collapseProps)
23
16
  const emit = defineEmits(collapseEmits)
24
17
 
25
18
  const children = ref<CollapseItemInstance[]>([])
26
- const expandedValues = ref<CollapseItemValue[]>([])
19
+ const expandedValue = ref<CollapseItemValue | CollapseItemValue[]>('')
20
+
21
+ const _modelValue = computed({
22
+ get() {
23
+ return props.modelValue ?? expandedValue.value
24
+ },
25
+ set(val) {
26
+ expandedValue.value = val
27
+ emit('update:modelValue', val)
28
+ },
29
+ })
27
30
 
28
- const setChildren = (node: CollapseItemInstance) => {
29
- node.index.value = children.value.length
30
- children.value.push(node as any)
31
+ const updateExpanded = () => {
32
+ children.value.forEach((child) => {
33
+ child.updateExpanded()
34
+ })
31
35
  }
32
36
 
33
- const onChildExpand = (name: CollapseItemValue, expanded: boolean) => {
34
- const values = props.accordion
35
- ? name
36
- : children.value.flatMap((node) => {
37
- const nodeId = node.name ?? node.index
38
- const nodeExpanded = nodeId === name ? expanded : node.expanded
39
- return nodeExpanded ? nodeId : []
37
+ const onChange = (name: CollapseItemValue, expanded: boolean) => {
38
+ const newModelValue = props.accordion
39
+ ? expanded
40
+ ? name
41
+ : ''
42
+ : children.value.flatMap((child) => {
43
+ const nodeExpanded = child.name === name ? expanded : child.expanded
44
+ return nodeExpanded ? child.name : []
40
45
  })
41
- const newModelValue = values
42
- expandedValues.value = Array.isArray(newModelValue) ? newModelValue : [newModelValue]
43
- emit('update:modelValue', newModelValue)
46
+ _modelValue.value = newModelValue
44
47
  emit('change', newModelValue)
45
48
 
46
49
  if (expanded) {
@@ -50,39 +53,20 @@ const onChildExpand = (name: CollapseItemValue, expanded: boolean) => {
50
53
  }
51
54
  }
52
55
 
53
- /**
54
- * 切换所有面板展开状态,传 true 为全部展开,false 为全部收起,不传参为全部切换
55
- */
56
- const toggleAll = (options: boolean | { expanded: boolean; skipDisabled: boolean }) => {
57
- children.value.forEach((node) => {
58
- if (typeof options === 'boolean') {
59
- node?.toggle(options)
60
- } else {
61
- // 跳过禁用的复选框
62
- if (options.skipDisabled && node.disabled) return
63
- node?.toggle(options.expanded)
64
- }
65
- })
66
- }
67
-
68
56
  watch(
69
- () => props.modelValue,
70
- (value) => {
71
- expandedValues.value = Array.isArray(value) ? value : value ? [value] : []
57
+ _modelValue,
58
+ () => {
59
+ updateExpanded()
72
60
  },
73
61
  {
74
62
  immediate: true,
75
63
  },
76
64
  )
77
65
 
78
- provide<CollapseProvideData>(`${ns.b()}-provide`, {
79
- modelValue: expandedValues,
80
- setChildren,
81
- onChildExpand,
82
- })
83
-
84
66
  defineExpose({
85
- toggleAll,
67
+ children,
68
+ modelValue: _modelValue,
69
+ onChange,
86
70
  })
87
71
  </script>
88
72
 
@@ -1,6 +1,6 @@
1
- import type { ExtractPropTypes, PropType } from 'vue'
1
+ import type { ExtractPropTypes, PropType, Ref } from 'vue'
2
2
  import { isUndefined } from '../../utils'
3
- import type { CollapseItemValue } from '../collapse-item/props'
3
+ import type { CollapseItemInstance, CollapseItemValue } from '../collapse-item/props'
4
4
 
5
5
  export const collapseProps = {
6
6
  /**
@@ -29,3 +29,9 @@ export const collapseEmits = {
29
29
 
30
30
  export type CollapseProps = ExtractPropTypes<typeof collapseProps>
31
31
  export type CollapseEmits = typeof collapseEmits
32
+
33
+ export type CollapseExpose = {
34
+ children: Ref<CollapseItemInstance[]>
35
+ modelValue: Ref<CollapseItemValue | CollapseItemValue[] | undefined>
36
+ onChange: (name: CollapseItemValue, expanded: boolean) => void
37
+ }
@@ -33,7 +33,7 @@
33
33
  transform: scaleY(0.5);
34
34
  }
35
35
 
36
- &--expanded &__title {
36
+ &--expanded > &__title {
37
37
  @include _setVar(cell-icon-right-rotate, -90deg);
38
38
  }
39
39
 
@@ -2,7 +2,7 @@
2
2
  <view
3
3
  :class="[
4
4
  ns.b(),
5
- ns.is('border', _index !== 0 && props.border),
5
+ ns.is('border', index !== 0 && props.border),
6
6
  ns.is('expanded', expanded),
7
7
  ns.is('disabled', disabled),
8
8
  ns.is('readonly', readonly),
@@ -14,8 +14,8 @@
14
14
  :title="title"
15
15
  :icon="icon"
16
16
  :value="value"
17
- :is-link="isLink"
18
- :border="props.border"
17
+ :is-link="isLink && !disabled"
18
+ :border="border"
19
19
  @click.stop="onClick"
20
20
  >
21
21
  <template #title>
@@ -36,94 +36,100 @@
36
36
  </template>
37
37
 
38
38
  <script setup lang="ts">
39
- import { computed, watch, type CSSProperties, type Ref } from 'vue'
40
- import { getCurrentInstance, inject, onMounted, ref, toRefs } from 'vue'
41
- import useNamespace, { defaultNamespace } from '../../core/useNamespace'
39
+ import { computed, getCurrentInstance, onMounted, ref, type CSSProperties } from 'vue'
40
+ import useNamespace from '../../core/useNamespace'
42
41
  import { useRect } from '../../hooks'
43
- import { noop } from '../../utils'
42
+ import { getParentInstance } from '../../utils/component'
44
43
  import Cell from '../cell/cell.vue'
45
- import type { CollapseProvideData } from '../collapse/collapse.vue'
46
- import type { CollapseItemProps } from './props'
47
- import { collapseItemProps } from './props'
48
-
49
- export interface CollapseItemInstance {
50
- index: Ref<number>
51
- /** 唯一标识符 */
52
- name?: Ref<CollapseItemProps['name']>
53
- /** 打开状态 */
54
- expanded: Ref<boolean>
55
- /** 禁用状态 */
56
- disabled: Ref<boolean>
57
- /** 切换打开状态 */
58
- toggle: (show?: boolean) => void
59
- }
44
+ import { CollapseExpose, CollapseProps } from '../collapse'
45
+ import { collapseItemProps, CollapseItemValue } from './props'
60
46
 
61
47
  const ns = useNamespace('collapse-item')
62
48
 
63
- const instance = getCurrentInstance()
64
-
65
49
  const props = defineProps(collapseItemProps)
66
50
 
67
- const { name, disabled } = toRefs(props)
68
- const _index = ref<number>(0)
69
-
70
- const collapseProvide = inject<CollapseProvideData>(`${defaultNamespace}-collapse-provide`, {
71
- modelValue: ref([]),
72
- setChildren: noop,
73
- onChildExpand: noop,
74
- })
51
+ const instance = getCurrentInstance()
52
+ const parent = getParentInstance<CollapseProps, CollapseExpose>(instance, 'collapse')
75
53
 
76
- const itemId = computed(() => name?.value ?? _index.value)
77
- const expanded = computed(() => collapseProvide.modelValue.value.includes(itemId.value))
54
+ const index = ref<number | undefined>()
55
+ const name = computed(() => props.name ?? index.value ?? 0)
56
+ const expanded = ref(false)
78
57
  const wrapperAnimation = ref<CSSProperties>()
58
+ let animating = false
79
59
 
80
60
  const getRect = () => {
81
61
  if (!instance) return Promise.resolve(null)
82
62
  return useRect(instance, `.${ns.e('content')}`)
83
63
  }
84
64
 
85
- const toggle = async (show = !expanded.value) => {
65
+ const updateExpanded = () => {
66
+ if (!parent || animating) return
67
+
68
+ const parentVal = parent.exposed.modelValue.value
69
+ const newExpanded = parent.props.accordion
70
+ ? parentVal === name.value
71
+ : (parentVal as CollapseItemValue[]).includes(name.value)
72
+ if (newExpanded !== expanded.value) {
73
+ setContentAnimate(newExpanded)
74
+ }
75
+ expanded.value = newExpanded
76
+ }
77
+
78
+ const setContentAnimate = async (show: boolean, duration = 300) => {
86
79
  const rect = await getRect()
87
80
  if (!rect) return
88
- const height = show ? rect.height : 0
89
81
 
82
+ animating = true
90
83
  const animation = uni.createAnimation({
84
+ duration: 0,
91
85
  timingFunction: 'ease-in-out',
92
86
  })
93
- animation.height(height).step({
94
- duration: 300,
95
- })
87
+ if (show) {
88
+ animation.height(rect.height).step({
89
+ duration,
90
+ })
91
+ animation.height('auto').step()
92
+ } else {
93
+ animation.height(rect.height).step()
94
+ // TODO: 这里第二步动画需要延迟执行,否则执行后无效果
95
+ setTimeout(() => {
96
+ animation.height(0).step({
97
+ duration,
98
+ })
99
+ wrapperAnimation.value = animation.export()
100
+ }, 16)
101
+ }
96
102
  wrapperAnimation.value = animation.export()
103
+ setTimeout(() => {
104
+ animating = false
105
+ }, duration)
97
106
  }
98
107
 
99
108
  const onClick = () => {
100
109
  if (props.disabled || props.readonly) return
101
- collapseProvide.onChildExpand(itemId.value, !expanded.value)
102
- toggle()
110
+ parent?.exposed.onChange(name.value, !expanded.value)
103
111
  }
104
112
 
105
- onMounted(() => {
106
- // 将自身组件实例添加到父组件
107
- if (instance) {
108
- collapseProvide.setChildren({
109
- index: _index,
113
+ const init = () => {
114
+ if (parent && parent.exposed) {
115
+ // 操作父组件的children对象,按照添加顺序记录子组件的index
116
+ index.value = parent.exposed.children.value.length
117
+ parent.exposed.children.value.push({
110
118
  name,
111
119
  expanded,
112
- disabled,
113
- toggle,
120
+ updateExpanded,
114
121
  })
115
- toggle(expanded.value)
116
122
  }
117
- })
123
+ }
118
124
 
119
- watch(expanded, (newVal, oldVal) => {
120
- if (newVal !== oldVal) {
121
- toggle(newVal)
122
- }
125
+ onMounted(() => {
126
+ init()
127
+ updateExpanded()
123
128
  })
124
129
 
125
130
  defineExpose({
126
- toggle,
131
+ updateExpanded,
132
+ setContentAnimate,
127
133
  })
128
134
  </script>
129
135
 
@@ -1,4 +1,4 @@
1
- import type { ExtractPropTypes, PropType } from 'vue'
1
+ import type { ExtractPropTypes, PropType, Ref } from 'vue'
2
2
 
3
3
  export const collapseItemProps = {
4
4
  /**
@@ -50,3 +50,12 @@ export const collapseItemProps = {
50
50
  export type CollapseItemValue = string | number
51
51
 
52
52
  export type CollapseItemProps = ExtractPropTypes<typeof collapseItemProps>
53
+
54
+ export interface CollapseItemInstance {
55
+ /** 唯一标识符 */
56
+ name: Ref<NonNullable<CollapseItemProps['name']>>
57
+ /** 打开状态 */
58
+ expanded: Ref<boolean>
59
+ /** 切换打开状态 */
60
+ updateExpanded: () => void
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papayaui",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "适用于uniapp的ui扩展库",
5
5
  "packageManager": "pnpm@8.6.0",
6
6
  "dependencies": {
package/.DS_Store DELETED
Binary file