提交 e3b2f59d 编写于 作者: fxy060608's avatar fxy060608

chore: merge

......@@ -12,7 +12,7 @@
"@dcloudio/uni-app": "../../uni-app",
"@dcloudio/uni-components": "../../uni-components",
"@dcloudio/uni-h5": "../../uni-h5",
"vue": "3.2.30",
"vue": "3.2.31",
"vue-router": "^4.0.12",
"vuex": "^4.0.2"
},
......
......@@ -34,9 +34,9 @@
"@dcloudio/uni-i18n": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-shared": "0.0.1-nvue3.3040020220217001",
"@types/pako": "1.0.2",
"@vue/compiler-sfc": "3.2.30",
"@vue/compiler-sfc": "3.2.31",
"pako": "^1.0.11",
"vue": "3.2.30"
"vue": "3.2.31"
},
"dependencies": {
"@dcloudio/uni-app-vite": "0.0.1-nvue3.3040020220217001",
......
......@@ -25,7 +25,7 @@
"@dcloudio/uni-shared": "0.0.1-nvue3.3040020220217001",
"@rollup/pluginutils": "^4.1.2",
"@vitejs/plugin-vue": "^2.2.0",
"@vue/compiler-sfc": "3.2.30",
"@vue/compiler-sfc": "3.2.31",
"debug": "^4.3.3",
"fs-extra": "^10.0.0",
"picocolors": "^1.0.0",
......@@ -34,7 +34,7 @@
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/fs-extra": "^9.0.13",
"@vue/compiler-core": "3.2.30",
"@vue/compiler-core": "3.2.31",
"esbuild": "^0.14.14",
"postcss": "^8.4.5"
}
......
......@@ -30,6 +30,6 @@
"@dcloudio/uni-push": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-shared": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-stat": "0.0.1-nvue3.3040020220217001",
"@vue/shared": "3.2.30"
"@vue/shared": "3.2.31"
}
}
......@@ -24,11 +24,11 @@
"@dcloudio/uni-i18n": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-shared": "0.0.1-nvue3.3040020220217001",
"@rollup/pluginutils": "^4.1.2",
"@vue/compiler-core": "3.2.30",
"@vue/compiler-dom": "3.2.30",
"@vue/compiler-sfc": "3.2.30",
"@vue/server-renderer": "3.2.30",
"@vue/shared": "3.2.30",
"@vue/compiler-core": "3.2.31",
"@vue/compiler-dom": "3.2.31",
"@vue/compiler-sfc": "3.2.31",
"@vue/server-renderer": "3.2.31",
"@vue/shared": "3.2.31",
"autoprefixer": "^10.4.2",
"base64url": "^3.0.1",
"chokidar": "^3.5.3",
......
const _adDataCache: Record<string, any> = {}
export function getAdData(
adpid: string | number,
width: any,
height: any,
onsuccess: Function,
onerror: Function
) {
const key = adpid + '-' + width
const adDataList = _adDataCache[key]
if (adDataList && adDataList.length > 0) {
onsuccess(adDataList.splice(0, 1)[0])
return
}
// TODO 缺少语法提示 getDrawAds
plus.ad.getAds(
{
adpid: String(adpid),
count: 3,
width,
},
(res: any) => {
const list = res.ads
onsuccess(list.splice(0, 1)[0])
_adDataCache[key] = adDataList ? adDataList.concat(list) : list
},
(err: any) => {
onerror({
errCode: err.code,
errMsg: err.message,
})
}
)
}
export const adDrawProps = {
adpid: {
type: [Number, String],
default: '',
},
data: {
type: String,
default: '',
},
width: {
type: String,
default: '',
},
}
const _adDataCache: Record<string, any> = {}
export function getAdData(data: any, onsuccess: Function, onerror: Function) {
const { adpid, width } = data
const key = adpid + '-' + width
const adDataList = _adDataCache[key]
if (adDataList && adDataList.length > 0) {
onsuccess(adDataList.splice(0, 1)[0])
return
}
plus.ad.getAds(
data,
(res) => {
const list = res.ads
onsuccess(list.splice(0, 1)[0])
_adDataCache[key] = adDataList ? adDataList.concat(list) : list
},
(err) => {
onerror({
errCode: err.code,
errMsg: err.message,
})
}
)
}
export const adProps = {
adpid: {
type: [Number, String],
default: '',
},
data: {
type: String,
default: '',
},
width: {
type: String,
default: '',
},
channel: {
type: String,
default: '',
},
}
import { PolySymbol } from '@dcloudio/uni-core'
export const uniCheckGroupKey = PolySymbol(__DEV__ ? 'uniCheckGroup' : 'ucg')
export const checkboxProps = {
checked: {
type: [Boolean, String],
default: false,
},
id: {
type: String,
default: '',
},
disabled: {
type: [Boolean, String],
default: false,
},
color: {
type: String,
default: '#007aff',
},
value: {
type: String,
default: '',
},
}
import { PolySymbol } from '@dcloudio/uni-core'
export const uniFormKey = PolySymbol(__DEV__ ? 'uniForm' : 'uf')
export interface UniFormCtx {
addField: (field: UniFormFieldCtx) => void
removeField: (field: UniFormFieldCtx) => void
submit: (evt: Event) => void
reset: (evt: Event) => void
}
export interface UniFormFieldCtx {
submit?: () => [string, any]
reset?: () => void
}
export const iconProps = {
type: {
type: String,
default: '',
},
size: {
type: [String, Number],
default: 23,
},
color: {
type: String,
default: '',
},
}
export const iconColors: Record<string, string> = {
success: '#09bb07',
info: '#10aeff',
warn: '#f76260',
waiting: '#10aeff',
safe_success: '#09bb07',
safe_warn: '#ffbe00',
success_circle: '#09bb07',
success_no_circle: '#09bb07',
waiting_circle: '#10aeff',
circle: '#c9c9c9',
download: '#09bb07',
info_circle: '#09bb07',
cancel: '#f43530',
search: '#b2b2b2',
clear: '#b2b2b2',
}
import { PolySymbol } from '@dcloudio/uni-core'
export const uniRadioGroupKey = PolySymbol(__DEV__ ? 'uniRadioGroup' : 'ucg')
export const radioProps = {
checked: {
type: [Boolean, String],
default: false,
},
id: {
type: String,
default: '',
},
disabled: {
type: [Boolean, String],
default: false,
},
color: {
type: String,
default: '#007aff',
},
value: {
type: String,
default: '',
},
}
import parseHtml from './html-parser'
const props = {
nodes: {
type: [Array, String],
default: function () {
return []
},
},
}
export { props, parseHtml }
export const sliderProps = {
name: {
type: String,
default: '',
},
min: {
type: [Number, String],
default: 0,
},
max: {
type: [Number, String],
default: 100,
},
value: {
type: [Number, String],
default: 0,
},
step: {
type: [Number, String],
default: 1,
},
disabled: {
type: [Boolean, String],
default: false,
},
color: {
type: String,
default: '#e9e9e9',
},
backgroundColor: {
type: String,
default: '#e9e9e9',
},
activeColor: {
type: String,
default: '#007aff',
},
selectedColor: {
type: String,
default: '#007aff',
},
blockColor: {
type: String,
default: '#ffffff',
},
blockSize: {
type: [Number, String],
default: 28,
},
showValue: {
type: [Boolean, String],
default: false,
},
}
export const swiperItemProps = {
itemId: {
type: String,
default: '',
},
}
export const swiperProps = {
indicatorDots: {
type: [Boolean, String],
default: false,
},
vertical: {
type: [Boolean, String],
default: false,
},
autoplay: {
type: [Boolean, String],
default: false,
},
circular: {
type: [Boolean, String],
default: false,
},
interval: {
type: [Number, String],
default: 5e3,
},
duration: {
type: [Number, String],
default: 500,
},
current: {
type: [Number, String],
default: 0,
},
indicatorColor: {
type: String,
default: 'rgba(0,0,0,.3)',
},
indicatorActiveColor: {
type: String,
default: '#000000',
},
previousMargin: {
type: String,
default: '',
},
nextMargin: {
type: String,
default: '',
},
currentItemId: {
type: String,
default: '',
},
skipHiddenItemLayout: {
type: [Boolean, String],
default: false,
},
displayMultipleItems: {
type: [Number, String],
default: 1,
},
disableTouch: {
type: [Boolean, String],
default: false,
},
}
export const switchProps = {
name: {
type: String,
default: '',
},
checked: {
type: [Boolean, String],
default: false,
},
type: {
type: String,
default: 'switch',
},
id: {
type: String,
default: '',
},
disabled: {
type: [Boolean, String],
default: false,
},
color: {
type: String,
default: '#007aff',
},
}
import {
defineComponent,
Ref,
ref,
reactive,
watch,
onMounted,
ExtractPropTypes,
} from 'vue'
import {
useCustomEvent,
EmitEvent,
CustomEventTrigger,
} from '../../helpers/useNVueEvent'
import { getComponentSize } from '../helpers'
import { adDrawProps, getAdData } from '../../components/ad-draw'
type AdDrawProps = ExtractPropTypes<typeof adDrawProps>
type AdDrawState = ReturnType<typeof useAdDrawState>
const AdEventType = {
load: 'load',
close: 'close',
error: 'error',
}
export default defineComponent({
name: 'AdDraw',
props: adDrawProps,
emits: [AdEventType.load, AdEventType.close, AdEventType.error],
setup(props, { emit }) {
const adRef: Ref<HTMLElement | null> = ref(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(adRef, emit)
const state = useAdDrawState(props)
watch(
() => props.adpid,
(value) => {
_loadAdData(state, props, trigger)
}
)
watch(
() => props.data,
(value) => {
state.data = value
}
)
const listeners = {
dislike(e: Event) {
trigger(AdEventType.close, e)
},
}
onMounted(() => {
setTimeout(() => {
getComponentSize(adRef.value!).then(({ width, height }) => {
state.width = width === 0 ? -1 : width
state.height = height === 0 ? -1 : height
_loadAdData(state, props, trigger)
})
}, 50)
})
return () => {
const { data } = state
return (
<u-ad-draw
ref="ad"
{...{ data, rendering: true }}
{...listeners}
></u-ad-draw>
)
}
},
})
function useAdDrawState(props: AdDrawProps) {
const data = ref('')
const state = reactive({
width: 0,
height: 0,
data,
})
return state
}
function _loadAdData(
state: AdDrawState,
props: AdDrawProps,
trigger: CustomEventTrigger
) {
getAdData(
props.adpid,
state.width,
state.height,
(res: any) => {
state.data = res.data
trigger(AdEventType.load, {})
},
(err: any) => {
trigger(AdEventType.error, err)
}
)
}
import {
defineComponent,
Ref,
ref,
reactive,
watch,
onMounted,
ExtractPropTypes,
} from 'vue'
import {
useCustomEvent,
EmitEvent,
CustomEventTrigger,
} from '../../helpers/useNVueEvent'
import { getComponentSize } from '../helpers'
import { adProps, getAdData } from '../../components/ad'
type AdProps = ExtractPropTypes<typeof adProps>
type AdState = ReturnType<typeof useAdState>
const AdEventType = {
load: 'load',
close: 'close',
error: 'error',
downloadchange: 'downloadchange',
}
export default defineComponent({
name: 'Ad',
props: adProps,
emits: [
AdEventType.load,
AdEventType.close,
AdEventType.error,
AdEventType.downloadchange,
],
setup(props, { emit }) {
const adRef: Ref<HTMLElement | null> = ref(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(adRef, emit)
const state = useAdState(props)
watch(
() => props.adpid,
(value) => {
_loadAdData(state, props, trigger)
}
)
watch(
() => props.data,
(value) => {
state.data = value
}
)
onMounted(() => {
setTimeout(() => {
getComponentSize(adRef.value!).then(({ width }) => {
state.width = width === 0 ? -1 : width
_loadAdData(state, props, trigger)
})
}, 50)
})
const listeners = {
downloadchange(e: Event) {
trigger(AdEventType.downloadchange, e)
},
dislike(e: Event) {
trigger(AdEventType.close, e)
},
}
return () => {
const { data } = state
return <u-ad ref="ad" {...{ data, rendering: true }} {...listeners} />
}
},
})
function useAdState(props: AdProps) {
const data = ref('')
const state = reactive({
width: 0,
data,
})
return state
}
function _loadAdData(
state: AdState,
props: AdProps,
trigger: CustomEventTrigger
) {
getAdData(
{
adpid: props.adpid,
width: state.width,
},
(res: any) => {
state.data = res.data
trigger(AdEventType.load, {})
},
(err: any) => {
trigger(AdEventType.error, err)
}
)
}
......@@ -16,6 +16,7 @@ import {
} from '../utils'
import { buttonProps } from '../../components/button'
import { extend } from '@vue/shared'
import { uniFormKey, UniFormCtx } from '../../components/form'
const buttonStyle: NVueComponentStyles = [
{
......@@ -306,13 +307,17 @@ export default defineComponent({
})
const type = props.type as keyof typeof TYPES
const rootRef = ref<HTMLElement | null>(null)
const uniForm = inject<UniFormCtx>(
uniFormKey,
false as unknown as UniFormCtx
)
const onClick = (e: Event, isLabelClick?: boolean) => {
const _onClick = ($listeners.value as any).onClick || (() => {})
if (props.disabled) {
return
}
_onClick(e)
/* const formType = props.formType
const formType = props.formType
if (formType) {
if (!uniForm) {
return
......@@ -322,7 +327,7 @@ export default defineComponent({
} else if (formType === 'reset') {
uniForm.reset(e)
}
} */
}
}
const _getClass = (t: string) => {
......
import {
defineComponent,
inject,
provide,
ComputedRef,
ref,
ExtractPropTypes,
} from 'vue'
import { uniCheckGroupKey } from '../../components/checkbox-group'
import { UniFormCtx, uniFormKey } from '../../components/form'
import {
CustomEventTrigger,
useCustomEvent,
EmitEvent,
} from '../../helpers/useEvent'
type UniCheckGroupFieldCtx = ComputedRef<{
checkboxChecked: boolean
value: string
}>
const props = {
name: {
type: String,
default: '',
},
}
type CheckBoxGroupProps = ExtractPropTypes<typeof props>
export interface UniCheckGroupCtx {
addField: (field: UniCheckGroupFieldCtx) => void
removeField: (field: UniCheckGroupFieldCtx) => void
checkboxChange: ($event: Event) => void
}
export default defineComponent({
name: 'CheckboxGroup',
props,
emits: ['change'],
setup(props, { slots, emit }) {
const rootRef = ref<HTMLElement | null>(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
useProvideCheckGroup(props, trigger)
return () => {
return (
<div ref={rootRef} class="uni-checkbox-group">
{slots.default && slots.default()}
</div>
)
}
},
})
function useProvideCheckGroup(
props: CheckBoxGroupProps,
trigger: CustomEventTrigger
) {
const fields: UniCheckGroupFieldCtx[] = []
const getFieldsValue = () =>
fields.reduce((res, field) => {
if (field.value.checkboxChecked) {
res.push(field.value.value)
}
return res
}, new Array())
provide<UniCheckGroupCtx>(uniCheckGroupKey, {
addField(field: UniCheckGroupFieldCtx) {
fields.push(field)
},
removeField(field: UniCheckGroupFieldCtx) {
fields.splice(fields.indexOf(field), 1)
},
checkboxChange($event) {
trigger('change', $event, {
value: getFieldsValue(),
})
},
})
const uniForm = inject<UniFormCtx>(uniFormKey, false as unknown as UniFormCtx)
if (uniForm) {
uniForm.addField({
submit: () => {
let data: [string, any] = ['', null]
if (props.name !== '') {
data[0] = props.name
data[1] = getFieldsValue()
}
return data
},
})
}
return getFieldsValue
}
import {
defineComponent,
inject,
onBeforeUnmount,
ref,
computed,
watch,
} from 'vue'
import { uniLabelKey, UniLabelCtx } from '../label'
import { useListeners } from '../../helpers/useListeners'
import { NVueComponentStyles, createNVueTextVNode } from '../utils'
import { checkboxProps } from '../../components/checkbox'
const checkboxStyles: NVueComponentStyles = [
{
'uni-checkbox': {
'': {
flexDirection: 'row',
alignItems: 'center',
},
},
'uni-checkbox-input': {
'': {
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
borderWidth: '1',
borderColor: '#d1d1d1',
borderStyle: 'solid',
backgroundColor: '#ffffff',
borderRadius: '3',
width: '22',
height: '22',
},
},
'uni-icon': {
'': {
fontFamily: 'unincomponents',
fontSize: '16',
marginLeft: '2',
marginTop: '2',
color: '#007aff',
},
},
'uni-checkbox-input-disabled': {
'': {
backgroundColor: '#e1e1e1',
},
},
'uni-checkbox-input-disabled-before': {
'': {
color: '#adadad',
},
},
'uni-checkbox-slot': {
'': {
fontSize: '16',
marginLeft: '5',
},
},
},
]
export default defineComponent({
name: 'Checkbox',
props: checkboxProps,
styles: checkboxStyles,
setup(props, { slots }) {
const rootRef = ref<HTMLElement | null>(null)
const checkboxChecked = ref(props.checked)
const checkboxValue = ref(props.value)
const onClick = (e: Event, isLabelClick?: boolean) => {
if (props.disabled) {
return
}
if (isLabelClick) {
rootRef.value!.click()
}
checkboxChecked.value = !checkboxChecked.value
}
const checkboxColor = computed(() =>
props.disabled ? '#adadad' : props.color
)
watch(
[() => props.checked, () => props.value],
([newChecked, newModelValue]) => {
checkboxChecked.value = newChecked
checkboxValue.value = newModelValue
}
)
const uniLabel = inject<UniLabelCtx>(
uniLabelKey,
false as unknown as UniLabelCtx
)
if (uniLabel) {
uniLabel.addHandler(onClick)
onBeforeUnmount(() => {
uniLabel.removeHandler(onClick)
})
}
useListeners(props, { 'label-click': onClick })
const wrapSlots = () => {
if (!slots.default) return []
const vnodes = slots.default()
if (vnodes.length === 1 && vnodes[0].type === Text) {
return [
createNVueTextVNode(vnodes[0].children as string, {
class: 'uni-checkbox-slot',
}),
]
}
return vnodes
}
return () => {
return (
<div
ref={rootRef}
{...{ dataUncType: 'uni-checkbox' }}
onClick={onClick}
class="uni-checkbox"
>
<div
class="uni-checkbox-input"
// @ts-expect-error
class={{ 'uni-checkbox-input-disabled': props.disabled }}
>
{checkboxChecked.value
? createNVueTextVNode('\uEA08', {
class: 'uni-icon',
style: {
color: checkboxColor.value,
},
})
: null}
</div>
{...wrapSlots()}
</div>
)
}
},
})
......@@ -4,6 +4,20 @@ import Button from './button'
import MovableArea from './movable-area'
import MovableView from './movable-view'
import Progress from './progress'
import PickerView from './picker-view'
import PickerViewColumn from './picker-view-column'
import Picker from './picker'
import USlider from './slider'
import Switch from './switch'
import Checkbox from './checkbox'
import CheckboxGroup from './checkbox-group'
import Radio from './radio'
import RadioGroup from './radio-group'
import Form from './form'
import Icon from './icon'
import Swiper from './swiper'
import SwiperItem from './swiper-item'
import RichText from './rich-text'
export default {
Navigator,
Label,
......@@ -11,4 +25,18 @@ export default {
MovableArea,
MovableView,
Progress,
PickerView,
PickerViewColumn,
Picker,
USlider,
Switch,
Checkbox,
CheckboxGroup,
Radio,
RadioGroup,
Form,
Icon,
Swiper,
SwiperItem,
RichText,
}
import { defineComponent, provide, ref } from 'vue'
import {
useCustomEvent,
EmitEvent,
CustomEventTrigger,
} from '../../helpers/useNVueEvent'
import { uniFormKey, UniFormCtx, UniFormFieldCtx } from '../../components/form'
const NATIVE_COMPONENTS = ['u-input', 'u-textarea']
export default defineComponent({
name: 'Form',
emits: ['submit', 'reset'],
setup({}, { slots, emit }) {
const rootRef = ref<HTMLElement | null>(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
const vnodes = slots.default && slots.default()
provideForm(trigger, vnodes)
return () => {
return <view ref={rootRef}>{vnodes}</view>
}
},
})
function provideForm(trigger: CustomEventTrigger, children: any) {
const modulePlus = weex.requireModule('plus')
const fields: UniFormFieldCtx[] = []
const getOrClearNativeValue = (nodes: any, outResult: any): void => {
nodes.forEach(function (node: any) {
if (
NATIVE_COMPONENTS.indexOf(node.type) >= 0 &&
node.el.attr &&
node.el.attr.name
) {
if (outResult) {
outResult[node.el.attr.name] = modulePlus.getValue(node.el.nodeId)
} else {
node.el.setValue('')
}
}
if (
Array.isArray(node.children) &&
node.children &&
node.children.length
) {
getOrClearNativeValue(node.children, outResult)
}
})
}
provide<UniFormCtx>(uniFormKey, {
addField(field: UniFormFieldCtx) {
fields.push(field)
},
removeField(field: UniFormFieldCtx) {
fields.splice(fields.indexOf(field), 1)
},
submit(evt: Event) {
// 获取原生组件值
let outFormData: any = {}
getOrClearNativeValue(children, outFormData)
let formData = fields.reduce((res, field) => {
if (field.submit) {
const [name, value] = field.submit()
name && (res[name] = value)
}
return res
}, Object.create(null))
Object.assign(outFormData, formData)
trigger('submit', {
value: outFormData,
})
},
reset(evt: Event) {
// 清空原生组件值
getOrClearNativeValue(children, null)
fields.forEach((field) => field.reset && field.reset())
trigger('reset', evt)
},
})
return fields
}
import { defineComponent } from 'vue'
import { iconProps, iconColors } from '../../components/icon'
import { NVueComponentStyles, createNVueTextVNode } from '../utils'
const iconChars: Record<string, string> = {
success: '\uEA06',
info: '\uEA03',
warn: '\uEA0B',
waiting: '\uEA09',
safe_success: '\uEA04',
safe_warn: '\uEA05',
success_circle: '\uEA07',
success_no_circle: '\uEA08',
waiting_circle: '\uEA0A',
circle: '\uEA01',
download: '\uEA02',
info_circle: '\uEA0C',
cancel: '\uEA0D',
search: '\uEA0E',
clear: '\uEA0F',
}
const iconStyles: NVueComponentStyles = [
{
'uni-icon': {
'': {
fontFamily: 'unincomponents',
},
},
},
]
export default defineComponent({
name: 'Icon',
props: iconProps,
styles: iconStyles,
setup(props, {}) {
return () => {
return createNVueTextVNode(iconChars[props.type] as string, {
class: 'uni-icon',
style: {
color: props.color || iconColors[props.type],
fontSize: props.size,
},
})
}
},
})
......@@ -32,8 +32,7 @@ export default defineComponent({
styles: [
{
'uni-movable-area': {
width: '10px',
height: '10px',
'': { width: '10px', height: '10px' },
},
},
],
......
......@@ -113,11 +113,13 @@ export default defineComponent({
styles: [
{
'uni-movable-view': {
position: 'absolute',
top: '0px',
left: '0px',
width: '10px',
height: '10px',
'': {
position: 'absolute',
top: '0px',
left: '0px',
width: '10px',
height: '10px',
},
},
},
],
......
......@@ -47,18 +47,19 @@ export default defineComponent({
const indicatorRef: Ref<HTMLElement | null> = ref(null)
const pickerViewProps = inject<Props>('pickerViewProps')!
const getPickerViewColumn = inject<GetPickerViewColumn>(
'getPickerViewColumn',
() => computed({ set: () => {}, get: () => 0 })
)
const getPickerViewColumn = inject(
'getPickerViewColumn'
) as GetPickerViewColumn
const current = getPickerViewColumn(instance)
const indicatorStyle = computed(() =>
getStyle(pickerViewProps.indicatorStyle)
)
const maskStyle = computed(() => getStyle(pickerViewProps.maskStyle))
let indicatorHeight = getHeight(indicatorStyle)
let pickerViewHeight = parseFloat(pickerViewProps.height as string)
let indicatorHeight = ref(0)
indicatorHeight.value = getHeight(indicatorStyle.value)
let pickerViewHeight = ref(0)
pickerViewHeight.value = parseFloat(pickerViewProps.height as string)
watch(
() => props.length,
......@@ -75,7 +76,7 @@ export default defineComponent({
return
}
dom.scrollToElement(contentRef.value, {
offset: _current * indicatorHeight,
offset: _current * indicatorHeight.value,
animated,
})
current.value = _current
......@@ -83,13 +84,15 @@ export default defineComponent({
scrollToElementTime = Date.now()
}
}
const onScrollend = (event: { detail: Record<string, any> }) => {
const onScrollend = (event: {
contentOffset: { x: number; y: number }
}) => {
if (Date.now() - scrollToElementTime < 340) {
return
}
const y = event.detail.contentOffset.y
const _current = Math.round(y / indicatorHeight)
if (y % indicatorHeight) {
const y = event.contentOffset.y
const _current = Math.round(y / indicatorHeight.value)
if (y % indicatorHeight.value) {
setCurrent(_current, true, true)
} else {
current.value = _current
......@@ -101,15 +104,15 @@ export default defineComponent({
setTimeout(() => {
Promise.all([
getComponentSize(rootRef.value!).then(({ height }) => {
height_ = pickerViewHeight = height
height_ = pickerViewHeight.value = height
}),
isAndroid && props.length
? getComponentSize(scrollViewItemRef.value!).then(({ height }) => {
indicatorHeight_ = indicatorHeight =
indicatorHeight_ = indicatorHeight.value =
height / parseFloat(props.length as string)
})
: getComponentSize(indicatorRef.value!).then(({ height }) => {
indicatorHeight_ = indicatorHeight = height
indicatorHeight_ = indicatorHeight.value = height
}),
]).then(() => {
if (height_ && indicatorHeight_) {
......@@ -140,8 +143,8 @@ export default defineComponent({
return () => {
const children = slots.default && slots.default()
let padding = (pickerViewHeight - indicatorHeight) / 2
const maskPosition = `${pickerViewHeight - padding}px`
let padding = (pickerViewHeight.value - indicatorHeight.value) / 2
const maskPosition = `${pickerViewHeight.value - padding}px`
const scrollOptions: ScrollOptions = {
showScrollbar: false,
scrollToBegin: false,
......@@ -149,7 +152,7 @@ export default defineComponent({
scrollY: true,
}
if (!isAndroid) {
scrollOptions.scrollTop = current.value * indicatorHeight
scrollOptions.scrollTop = current.value * indicatorHeight.value
}
return (
......@@ -172,7 +175,7 @@ export default defineComponent({
{createScrollViewChild(children)}
</view>
</scroll-view>
<u-scalable class="uni-picker-view-mask" style={maskStyle}>
<u-scalable class="uni-picker-view-mask" style={maskStyle.value}>
<u-scalable
class="uni-picker-view-mask uni-picker-view-mask-top"
style={{
......@@ -200,52 +203,60 @@ export default defineComponent({
styles: [
{
'uni-picker-view-column': {
flex: 1,
position: 'relative',
alignItems: 'stretch',
overflow: 'hidden',
'': {
flex: 1,
position: 'relative',
alignItems: 'stretch',
overflow: 'hidden',
},
},
'uni-picker-view-mask': {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
pointerEvents: 'none',
'': {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
pointerEvents: 'none',
},
},
'uni-picker-view-mask-top': {
bottom: 0,
backgroundImage:
'linear-gradient(to bottom,rgba(255, 255, 255, 0.95),rgba(255, 255, 255, 0.6))',
'': {
bottom: 0,
backgroundImage:
'linear-gradient(to bottom,rgba(255, 255, 255, 0.95),rgba(255, 255, 255, 0.6))',
},
},
'uni-picker-view-mask-bottom': {
top: 0,
backgroundImage:
'linear-gradient(to top,rgba(255, 255, 255, 0.95),rgba(255, 255, 255, 0.6))',
'': {
top: 0,
backgroundImage:
'linear-gradient(to top,rgba(255, 255, 255, 0.95),rgba(255, 255, 255, 0.6))',
},
},
'uni-picker-view-group': {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
'': { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 },
},
'uni-picker-view-content': {
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
'': {
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
},
},
'uni-picker-view-indicator': {
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '34px',
pointerEvents: 'none',
borderColor: '#e5e5e5',
borderTopWidth: '1px',
borderBottomWidth: '1px',
'': {
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '34px',
pointerEvents: 'none',
borderColor: '#e5e5e5',
borderTopWidth: '1px',
borderBottomWidth: '1px',
},
},
},
],
......
......@@ -17,7 +17,7 @@ import {
import { flatVNode } from '../../helpers/flatVNode'
import { useCustomEvent, EmitEvent } from '../../helpers/useNVueEvent'
export { Props, GetPickerViewColumn }
export type { Props, GetPickerViewColumn }
const nvuePickerViewProps = extend({}, pickerViewProps, {
height: {
type: [Number, String],
......@@ -36,7 +36,7 @@ export default defineComponent({
let columnVNodes: VNode[] = []
const getItemIndex = (vnode: VNode) =>
Array.prototype.indexOf.call(columnVNodes, vnode.el)
Array.prototype.indexOf.call(columnVNodes, vnode)
const getPickerViewColumn: GetPickerViewColumn = (columnInstance) => {
return computed({
get() {
......@@ -85,17 +85,19 @@ export default defineComponent({
styles: [
{
'uni-picker-view': {
position: 'relative',
'': { position: 'relative' },
},
'uni-picker-view-wrapper': {
display: 'flex',
flexDirection: 'row',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
overflow: 'hidden',
'': {
display: 'flex',
flexDirection: 'row',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
overflow: 'hidden',
},
},
},
],
......
import { extend } from '@vue/shared'
import { Ref, ref, watch, ExtractPropTypes, defineComponent } from 'vue'
import { useCustomEvent, EmitEvent } from '../../helpers/useNVueEvent'
import { showPage, Page } from '@dcloudio/uni-core'
type Mode = 'selector' | 'multiSelector' | 'time' | 'date'
type Field = 'year' | 'month' | 'day'
const mode: Record<string, Mode> = {
SELECTOR: 'selector',
MULTISELECTOR: 'multiSelector',
TIME: 'time',
DATE: 'date',
// 暂不支持城市选择
// REGION: 'region'
}
const fields: Record<string, Field> = {
YEAR: 'year',
MONTH: 'month',
DAY: 'day',
}
function padLeft(num: number) {
return num > 9 ? num : `0${num}`
}
function getDate(str: Props['value'], _mode: Mode) {
str = String(str || '')
const date = new Date()
if (_mode === mode.TIME) {
const strs = str.split(':')
if (strs.length === 2) {
date.setHours(parseInt(strs[0]), parseInt(strs[1]))
}
} else {
const strs = str.split('-')
if (strs.length === 3) {
date.setFullYear(
parseInt(strs[0]),
parseInt(String(parseFloat(strs[1]) - 1)),
parseInt(strs[2])
)
}
}
return date
}
function getDefaultStartValue(props: any) {
if ((props as Props).mode === mode.TIME) {
return '00:00'
}
if ((props as Props).mode === mode.DATE) {
const year = new Date().getFullYear() - 100
switch ((props as Props).fields) {
case fields.YEAR:
return year
case fields.MONTH:
return year + '-01'
default:
return year + '-01-01'
}
}
return ''
}
function getDefaultEndValue(props: any) {
if ((props as Props).mode === mode.TIME) {
return '23:59'
}
if ((props as Props).mode === mode.DATE) {
const year = new Date().getFullYear() + 100
switch ((props as Props).fields) {
case fields.YEAR:
return year
case fields.MONTH:
return year + '-12'
default:
return year + '-12-31'
}
}
return ''
}
const props = {
name: {
type: String,
default: '',
},
range: {
type: Array,
default() {
return []
},
},
rangeKey: {
type: String,
default: '',
},
value: {
type: [Number, String, Array],
default: 0,
},
mode: {
type: String,
default: mode.SELECTOR,
validator(val: string) {
return Object.values(mode).indexOf(val as Mode) >= 0
},
},
fields: {
type: String,
default: '',
},
start: {
type: String,
default: getDefaultStartValue,
},
end: {
type: String,
default: getDefaultEndValue,
},
disabled: {
type: [Boolean, String],
default: false,
},
}
type Props = ExtractPropTypes<typeof props>
export default /*#__PURE__*/ defineComponent({
name: 'Picker',
props,
emits: ['change', 'cancel', 'columnchange'],
setup(props, { slots, emit }) {
const rootRef: Ref<HTMLElement | null> = ref(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
const valueSync: Ref<Array<number> | number | string | null> = ref(null)
const page: Ref<Page | null> = ref(null)
type ShowPickerData = Props & {
value: typeof valueSync.value
locale: string
// messages: {
// done: string
// cancel: string
// }
}
const _setValueSync = () => {
let val = props.value
switch (props.mode) {
case mode.MULTISELECTOR:
{
if (!Array.isArray(val)) {
val = []
}
if (!Array.isArray(valueSync.value)) {
valueSync.value = []
}
const length = (valueSync.value.length = Math.max(
val.length,
props.range.length
))
for (let index = 0; index < length; index++) {
const val0 = Number(val[index])
const val1 = Number(valueSync.value[index])
const val2 = isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0
valueSync.value.splice(index, 1, val2 < 0 ? 0 : val2)
}
}
break
case mode.TIME:
case mode.DATE:
valueSync.value = String(val)
break
default: {
const _valueSync = Number(val)
valueSync.value = _valueSync < 0 ? 0 : _valueSync
break
}
}
}
const _updatePicker = (data: ShowPickerData) => {
page.value && page.value.sendMessage(data)
}
const _showWeexPicker = (data: ShowPickerData) => {
let res: { event?: Parameters<typeof emit>[0] } = { event: 'cancel' }
page.value = showPage({
url: '__uniapppicker',
data,
style: {
// @ts-expect-error
titleNView: false,
animationType: 'none',
animationDuration: 0,
background: 'rgba(0,0,0,0)',
popGesture: 'none',
},
onMessage: (message) => {
const event = message.event
if (event === 'created') {
_updatePicker(data)
return
}
if (event === 'columnchange') {
delete message.event
trigger(event, message)
return
}
res = message
},
onClose: () => {
page.value = null
const event = res.event
delete res.event
event && trigger(event, res)
},
})
}
const _showNativePicker = (data: ShowPickerData) => {
plus.nativeUI[props.mode === mode.TIME ? 'pickTime' : 'pickDate'](
(res) => {
const date = res.date
trigger('change', {
value:
props.mode === mode.TIME
? `${padLeft(date.getHours())}:${padLeft(date.getMinutes())}`
: `${date.getFullYear()}-${padLeft(
date.getMonth() + 1
)}-${padLeft(date.getDate())}`,
})
},
() => {
trigger('cancel', {})
},
props.mode === mode.TIME
? {
time: getDate(props.value, mode.TIME),
}
: {
date: getDate(props.value, mode.DATE),
minDate: getDate(props.start, mode.DATE),
maxDate: getDate(props.end, mode.DATE),
}
)
}
const _showPicker = (data: ShowPickerData) => {
if (
(data.mode === mode.TIME || data.mode === mode.DATE) &&
!data.fields
) {
_showNativePicker(data)
} else {
data.fields = Object.values(fields).includes(data.fields as Field)
? data.fields
: fields.DAY
_showWeexPicker(data)
}
}
const _show = (event: MouseEvent) => {
if (props.disabled) {
return
}
_showPicker(
extend({}, props, {
value: valueSync.value,
locale: uni.getLocale(),
})
)
}
/* const uniForm = inject<UniFormCtx>(
uniFormKey,
false as unknown as UniFormCtx
)
const formField = {
submit: (): [string, any] => [props.name, valueSync.value],
reset: () => {
switch (props.mode) {
case mode.SELECTOR:
valueSync.value = 0
break
case mode.MULTISELECTOR:
Array.isArray(props.value) &&
(valueSync.value = props.value.map((val) => 0))
break
case mode.DATE:
case mode.TIME:
valueSync.value = ''
break
default:
break
}
},
}
if (uniForm) {
uniForm.addField(formField)
onBeforeUnmount(() => uniForm.removeField(formField))
} */
Object.keys(props).forEach((key) => {
watch(
() => (props as any)[key],
(val) => {
const data = {}
;(data as any)[key] = val
_updatePicker(data as any)
},
{ deep: true }
)
})
watch(() => props.value, _setValueSync, { deep: true })
_setValueSync()
return () => {
return (
<uni-picker ref={rootRef} onClick={_show}>
{slots.default && slots.default()}
</uni-picker>
)
}
},
})
......@@ -14,24 +14,32 @@ import {
CustomEventTrigger,
} from '../../helpers/useNVueEvent'
import { getComponentSize } from '../helpers'
import { createNVueTextVNode } from '../utils'
import { NVueComponentStyles, createNVueTextVNode } from '../utils'
import { PROGRESS_VALUES, progressProps } from '../../components/progress'
const progressStyles: Record<string, Record<string, string | number>>[] = [
const progressStyles: NVueComponentStyles = [
{
'uni-progress': {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
'': {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
},
'uni-progress-bar': {
flex: 1,
'': {
flex: 1,
},
},
'uni-progress-inner-bar': {
position: 'absolute',
'': {
position: 'absolute',
},
},
'uni-progress-info': {
marginLeft: '15px',
'': {
marginLeft: '15px',
},
},
},
]
......
import {
defineComponent,
inject,
provide,
ComputedRef,
ref,
ExtractPropTypes,
} from 'vue'
import { uniRadioGroupKey } from '../../components/radio-group'
import { UniFormCtx, uniFormKey } from '../../components/form'
import {
CustomEventTrigger,
useCustomEvent,
EmitEvent,
} from '../../helpers/useEvent'
type UniRadioGroupFieldCtx = ComputedRef<{
radioChecked: boolean
value: string
}>
const props = {
name: {
type: String,
default: '',
},
}
type RadioGroupProps = ExtractPropTypes<typeof props>
export interface UniRadioGroupCtx {
addField: (field: UniRadioGroupFieldCtx) => void
removeField: (field: UniRadioGroupFieldCtx) => void
radioChange: ($event: Event) => void
}
export default defineComponent({
name: 'RadioGroup',
props,
emits: ['change'],
setup(props, { slots, emit }) {
const rootRef = ref<HTMLElement | null>(null)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
useProvideRadioGroup(props, trigger)
return () => {
return <div ref={rootRef}>{slots.default && slots.default()}</div>
}
},
})
function useProvideRadioGroup(
props: RadioGroupProps,
trigger: CustomEventTrigger
) {
const fields: UniRadioGroupFieldCtx[] = []
const getFieldsValue = () =>
fields.reduce((res, field) => {
if (field.value.radioChecked) {
res.push(field.value.value)
}
return res
}, new Array())
provide<UniRadioGroupCtx>(uniRadioGroupKey, {
addField(field: UniRadioGroupFieldCtx) {
fields.push(field)
},
removeField(field: UniRadioGroupFieldCtx) {
fields.splice(fields.indexOf(field), 1)
},
radioChange($event) {
trigger('change', $event, {
value: getFieldsValue(),
})
},
})
const uniForm = inject<UniFormCtx>(uniFormKey, false as unknown as UniFormCtx)
if (uniForm) {
uniForm.addField({
submit: () => {
let data: [string, any] = ['', null]
if (props.name !== '') {
data[0] = props.name
data[1] = getFieldsValue()
}
return data
},
})
}
return getFieldsValue
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
import { defineComponent } from 'vue'
import { swiperItemProps } from '../../components/swiper-item'
export default defineComponent({
name: 'SwiperItem',
props: swiperItemProps,
setup(props, { slots }) {
return () => {
return (
<div
class="uni-swiper-item"
style={{
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
overflow: 'hidden',
}}
>
{slots.default && slots.default()}
</div>
)
}
},
})
此差异已折叠。
import {
defineComponent,
Ref,
ref,
onBeforeUnmount,
onUnmounted,
watch,
inject,
ExtractPropTypes,
} from 'vue'
import { useCustomEvent, EmitEvent } from '../../helpers/useNVueEvent'
import { uniFormKey, UniFormCtx } from '../../components/form'
import { uniLabelKey, UniLabelCtx } from '../label'
import { useListeners } from '../../helpers/useListeners'
import { switchProps } from '../../components/switch'
const SwitchType = {
switch: 'switch',
checkbox: 'checkbox',
}
const DCSwitchSize = {
width: 52,
height: 32,
}
type SwitchProps = ExtractPropTypes<typeof switchProps>
export default defineComponent({
name: 'Switch',
props: switchProps,
emits: ['change'],
setup(props, { emit }) {
const rootRef = ref<HTMLElement | null>(null)
const switchChecked = ref(props.checked)
const uniLabel = useSwitchInject(props, switchChecked)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
watch(
() => props.checked,
(val) => {
switchChecked.value = val
}
)
const listeners = {
onChange(e: CustomEvent) {
switchChecked.value = e.detail.value
trigger('change', {
value: switchChecked.value,
})
},
}
const _onClick = ($event: Event) => {
if (props.disabled) {
return
}
switchChecked.value = !switchChecked.value
trigger('change', {
value: switchChecked.value,
})
}
if (!!uniLabel) {
uniLabel.addHandler(_onClick)
onBeforeUnmount(() => {
uniLabel.removeHandler(_onClick)
})
}
useListeners(props, { 'label-click': _onClick })
return () => {
const { color, type } = props
return (
<div ref={rootRef}>
{type === SwitchType.switch ? (
<dc-switch
{...{ dataUncType: 'uni-switch' }}
{...listeners}
{...{ checked: switchChecked.value }}
style={DCSwitchSize}
/>
) : null}
{type === SwitchType.checkbox ? (
<checkbox
style={{ color: color }}
{...{ checked: switchChecked.value }}
{...listeners}
/>
) : null}
</div>
)
}
},
})
function useSwitchInject(
props: SwitchProps,
switchChecked: Ref<string | boolean>
) {
const uniForm = inject<UniFormCtx>(uniFormKey, false as unknown as UniFormCtx)
const uniLabel = inject<UniLabelCtx>(
uniLabelKey,
false as unknown as UniLabelCtx
)
const formField = {
submit: () => {
const data: [string, any] = ['', null]
if (props.name) {
data[0] = props.name
data[1] = switchChecked.value
}
return data
},
reset: () => {
switchChecked.value = false
},
}
if (!!uniForm) {
uniForm.addField(formField)
onUnmounted(() => {
uniForm.removeField(formField)
})
}
return uniLabel
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -25,7 +25,7 @@
"@dcloudio/uni-cli-shared": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-mp-vite": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-mp-vue": "0.0.1-nvue3.3040020220217001",
"@vue/compiler-core": "3.2.30",
"@vue/shared": "3.2.30"
"@vue/compiler-core": "3.2.31",
"@vue/shared": "3.2.31"
}
}
此差异已折叠。
......@@ -30,6 +30,6 @@
"@dcloudio/uni-mp-vite": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-mp-vue": "0.0.1-nvue3.3040020220217001",
"@dcloudio/uni-shared": "0.0.1-nvue3.3040020220217001",
"@vue/compiler-core": "3.2.30"
"@vue/compiler-core": "3.2.31"
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册