From 4bb463a549ae7a43a0c5bca3fff804770f1cd128 Mon Sep 17 00:00:00 2001 From: --global Date: Mon, 26 Aug 2024 10:28:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=9F=8E?= =?UTF-8?q?=E5=B8=82=E9=80=89=E6=8B=A9=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/CitySelector/CitySelector.less | 121 ++ .../src/CitySelector/CitySelector.miniapp.tsx | 72 ++ .../src/CitySelector/CitySelector.tsx | 41 + .../src/CitySelector/CitySelector.types.ts | 59 + .../src/CitySelector/CitySelectorCore.tsx | 234 ++++ .../src/CitySelector/Selector/index.less | 13 + .../src/CitySelector/Selector/index.tsx | 24 + .../__tests__/CitySelector.snapshot.test.tsx | 5 + .../__tests__/CitySelector.test.tsx | 150 +++ packages/bui-core/src/CitySelector/index.md | 375 ++++++ packages/bui-core/src/CitySelector/index.ts | 2 + .../bui-core/src/CitySelector/miniapp.less | 4 + packages/bui-core/src/CitySelector/mock.ts | 1040 +++++++++++++++++ packages/bui-core/src/index.ts | 1 + 14 files changed, 2141 insertions(+) create mode 100644 packages/bui-core/src/CitySelector/CitySelector.less create mode 100644 packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx create mode 100644 packages/bui-core/src/CitySelector/CitySelector.tsx create mode 100644 packages/bui-core/src/CitySelector/CitySelector.types.ts create mode 100644 packages/bui-core/src/CitySelector/CitySelectorCore.tsx create mode 100644 packages/bui-core/src/CitySelector/Selector/index.less create mode 100644 packages/bui-core/src/CitySelector/Selector/index.tsx create mode 100644 packages/bui-core/src/CitySelector/__tests__/CitySelector.snapshot.test.tsx create mode 100644 packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx create mode 100644 packages/bui-core/src/CitySelector/index.md create mode 100644 packages/bui-core/src/CitySelector/index.ts create mode 100644 packages/bui-core/src/CitySelector/miniapp.less create mode 100644 packages/bui-core/src/CitySelector/mock.ts diff --git a/packages/bui-core/src/CitySelector/CitySelector.less b/packages/bui-core/src/CitySelector/CitySelector.less new file mode 100644 index 0000000..3d50c2d --- /dev/null +++ b/packages/bui-core/src/CitySelector/CitySelector.less @@ -0,0 +1,121 @@ +@import '~@bifrostui/styles/mixins/index.less'; + +.bui-city-selector { + height: 100%; + + &-title { + width: 100%; + height: 45px; + color: var(--bui-color-fg-default); + font-size: var(--bui-title-size-3); + line-height: 45px; + text-align: center; + position: sticky; + top: 0; + z-index: 1004; + border-bottom: solid 1px var(--bui-color-border-default); + background-color: var(--bui-color-bg-view); + } + + &-btn-close { + position: absolute; + top: 0; + right: 0; + width: 45px; + height: 45px; + color: var(--bui-color-fg-muted); + text-align: center; + font-size: 20px; + } + + &-scroll-view-container { + height: 100%; + display: flex; + + &.container-has-title { + height: calc(100% - 45px); + } + } + + &-all-city { + min-height: 500px; + font-size: var(--bui-text-size-2); + width: 100%; + background: var(--bui-color-bg-view); + align-self: flex-start; + + .select-city-buttons { + display: flex; + flex-flow: wrap; + padding-left: 3px; + padding-top: 7.5px; + } + + .select-city-title { + font-size: var(--bui-title-size-4); + line-height: 15px; + font-weight: 600; + padding-left: 12px; + padding-top: 9px; + } + } + + &-list { + padding-left: 12px; + list-style-type: none; + } + + &-list-item { + height: 45px; + font-size: var(--bui-title-size-4); + display: flex; + align-items: center; + + &:not(:last-child) { + border-bottom: 0.5px solid var(--bui-color-border-default); + } + } + + &-index-container { + z-index: 1001; + position: absolute; + white-space: nowrap; + right: 0; + top: 50%; + width: 40px; + will-change: transform; + // transform: translate(100%, -50%); + transform: translate(0, -50%); + transition: + opacity 0.2s ease-out, + transform 0.2s ease-out; + + &.left-in { + opacity: 1; + transform: translate(0, -50%); + } + + &.city-index-has-title { + top: calc(50% + 22.5px); + } + + ul { + margin: 0; + padding: 0; + float: left; + width: 100%; + touch-action: none; + } + + li { + list-style: none; + height: 20px; + text-align: center; + font-size: var(--bui-text-size-3); + color: var(--bui-color-info, --bui-color-info); + display: flex; + align-items: center; + justify-content: center; + } + } +} diff --git a/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx b/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx new file mode 100644 index 0000000..9dc219c --- /dev/null +++ b/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx @@ -0,0 +1,72 @@ +import React, { useEffect, useRef, useState } from 'react'; +import Taro from '@tarojs/taro'; +import { CitySelectorProps } from './CitySelector.types'; +import CitySelectorCore from './CitySelectorCore'; +import './miniapp.less'; + +const CitySelector = React.forwardRef( + (props, ref) => { + const { cities } = props; + const containerTop = useRef(0); + const codeHeight = useRef(0); + const [height, setHeight] = useState(''); + + useEffect(() => { + if (cities?.length === 0 || codeHeight.current) return; + Taro.createSelectorQuery() + .select('.bui-city-selector-index-list') + .boundingClientRect((rect: any) => { + containerTop.current = rect?.top; + }) + .exec(); + Taro.createSelectorQuery() + .select('.bui-city-selector-index-item') + .boundingClientRect((codeRect: any) => { + codeHeight.current = codeRect?.height; + }) + .exec(); + }, [cities, height]); + + useEffect(() => { + if (!cities?.length || height) return; + const { screenHeight } = Taro.getSystemInfoSync(); + + Taro.createSelectorQuery() + .select('.bui-city-selector-scroll-view-container') + .boundingClientRect((codeRect: any) => { + const domHeight = codeRect?.height; + setHeight(`${(domHeight / screenHeight) * 100}vh`); + }) + .exec(); + }, [cities]); + + const parseIndex = (length, index) => { + if (index <= 0) return 0; + if (index >= length - 1) return length - 1; + return index; + }; + + const touchHandler = (event, scrollToCode, codeGroup) => { + const { clientY } = event.changedTouches[0]; + let index = Math.floor( + (clientY - containerTop.current) / codeHeight.current, + ); + index = parseIndex(codeGroup.length, index); + const codeItem = codeGroup[index]; + scrollToCode(codeItem.code || codeItem); + }; + + return ( + + ); + }, +); + +CitySelector.displayName = 'BuiCitySelector'; + +export default CitySelector; diff --git a/packages/bui-core/src/CitySelector/CitySelector.tsx b/packages/bui-core/src/CitySelector/CitySelector.tsx new file mode 100644 index 0000000..16a947c --- /dev/null +++ b/packages/bui-core/src/CitySelector/CitySelector.tsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from 'react'; +import { CitySelectorProps } from './CitySelector.types'; +import CitySelectorCore from './CitySelectorCore'; + +const CitySelector = React.forwardRef( + (props, ref) => { + const { cities } = props; + const [height, setHeight] = useState(''); + const touchHandler = (e, scrollToCode) => { + const t: any = document.elementFromPoint( + e.changedTouches[0].clientX, + e.changedTouches[0].clientY, + ); + const code = t?.dataset?.code; + scrollToCode(code); + }; + + useEffect(() => { + if (!cities?.length || height) return; + const screenHeight = + window.innerHeight || document.documentElement.clientHeight; + const domHeight = document + .querySelector('.bui-city-selector-scroll-view-container') + ?.getBoundingClientRect().height; + + setHeight(`${(domHeight / screenHeight) * 100}vh`); + }, [cities]); + + return ( + + ); + }, +); + +CitySelector.displayName = 'BuiCitySelector'; +export default CitySelector; diff --git a/packages/bui-core/src/CitySelector/CitySelector.types.ts b/packages/bui-core/src/CitySelector/CitySelector.types.ts new file mode 100644 index 0000000..2bf0c68 --- /dev/null +++ b/packages/bui-core/src/CitySelector/CitySelector.types.ts @@ -0,0 +1,59 @@ +import { OverrideProps } from '@bifrostui/types'; + +export type cityType = { + /** 城市名 */ + name: string; + /** 城市名id */ + code: string; +}; + +export type allCityItemType = { + /** 城市列表 */ + cities: cityType[]; + /** 索引字母 */ + groupName: string; +}; + +export type CitySelectorProps< + D extends React.ElementType = 'div', + P = {}, +> = OverrideProps< + { + props: P & { + /** 当前城市信息 */ + selectedCity?: cityType; + /** 当前城市栏的title */ + selectedCityGroupName?: string; + /** 定位城市信息 */ + currentCity?: cityType; + /** 定位城市栏的title */ + currentCityGroupName?: string; + /** 热门城市信息 */ + hotCities?: cityType[]; + /** 热门城市栏的title */ + hotCitiesGroupName?: string; + /** 城市列表 */ + cities: allCityItemType[]; + /** 禁用展示索引 默认false 即展示索引 */ + disableIndex: boolean; + /** 头部标题 */ + title?: string; + /** 选择城市回调 */ + onSelect: ( + e: React.SyntheticEvent, + data: { + city: cityType; + }, + ) => void; + /** 和title配合使用,头部右侧的关闭回调 */ + onClose?: (e: React.SyntheticEvent) => void; + }; + defaultComponent: D; + }, + D +>; + +export type CitySelectorCoreProps = CitySelectorProps & { + touchHandler: any; + height?: string; +}; diff --git a/packages/bui-core/src/CitySelector/CitySelectorCore.tsx b/packages/bui-core/src/CitySelector/CitySelectorCore.tsx new file mode 100644 index 0000000..8913be1 --- /dev/null +++ b/packages/bui-core/src/CitySelector/CitySelectorCore.tsx @@ -0,0 +1,234 @@ +import React, { useState, useEffect } from 'react'; +import clsx from 'clsx'; +import { throttle, useForkRef } from '@bifrostui/utils'; +import { ScrollView } from '../ScrollView'; +import { CitySelectorCoreProps } from './CitySelector.types'; +import Selector from './Selector'; + +import './CitySelector.less'; + +// 误差偏移量 +const DEVIATION_HEIGHT = '6vmin'; + +const GPS_TYPE = { + title: '定位', + code: 'GPS', +}; +const CURRENT_TYPE = { + title: '当前', + code: 'CRRT', +}; + +const HOT_CITY_TYPE = { + title: '热门', + code: 'HOT', +}; + +const prefixCls = 'bui-city-selector'; + +const CitySelector = React.forwardRef( + (props, ref) => { + const { + className, + title: pageTitle, + selectedCity, + selectedCityGroupName = '当前城市', + currentCity, + currentCityGroupName = '定位城市', + hotCities, + hotCitiesGroupName = '热门城市', + cities, + disableIndex, + touchHandler, + height, + onSelect, + onClose, + ref: propsRef, + ...others + } = props; + const nodeRef = useForkRef(ref, propsRef); + const [codeGroup, setCodeGroup] = useState([]); + const [codeShow, setCodeShow] = useState(false); + const [targetId, setTargetId] = useState(''); + + // 提取字母 + useEffect(() => { + if (cities.length === 0 || codeGroup.length !== 0 || disableIndex) return; + + const newGroup = []; + if (selectedCity) { + newGroup.push(CURRENT_TYPE); + } + if (currentCity) { + newGroup.push(GPS_TYPE); + } + if (hotCities) { + newGroup.push(HOT_CITY_TYPE); + } + cities.forEach((item) => { + newGroup.push(item.groupName.toUpperCase()); + }); + setCodeGroup(newGroup); + }, [cities, selectedCity, currentCity, hotCities]); + + // 计算每个code的top + useEffect(() => { + if (codeGroup.length === 0) return; + setCodeShow(true); + }, [codeGroup]); + + const selectHandler = (e, city) => { + onSelect(e, { city }); + }; + + const scrollToCode = (targetCode) => { + if (!targetCode) return; + setTargetId((oldCode) => { + if (targetCode !== oldCode) return targetCode; + return oldCode; + }); + }; + + const touchCbk = (e: React.SyntheticEvent) => { + e.stopPropagation(); + touchHandler?.(e, scrollToCode, codeGroup); + }; + + const codeClickHandler = (rightCode) => { + setTargetId(rightCode); + }; + + const scrollHandler = throttle(() => { + if (targetId) { + setTargetId(''); + } + }, 500); + + const closeHandler = (e: React.SyntheticEvent) => { + onClose?.(e); + }; + + const renderTitile = (title, titleCode?) => { + const parseTitle = (titleCode || title).toUpperCase(); + return ( +
+ {title.toUpperCase()} +
+ ); + }; + + const renderCity = (citys, title, titleCode?) => { + return ( +
+ {renderTitile(title, titleCode)} +
+ {citys.map((city, index) => { + return ( + + ); + })} +
+
+ ); + }; + + return ( +
+ {pageTitle ? ( +
+ {pageTitle} +
+ ✕ +
+
+ ) : null} + +
+ {/* 当前城市 */} + {selectedCity + ? renderCity( + [selectedCity], + selectedCityGroupName, + CURRENT_TYPE.code, + ) + : null} + {/* 定位城市 */} + {currentCity + ? renderCity([currentCity], currentCityGroupName, GPS_TYPE.code) + : null} + {/* 热门城市 */} + {hotCities?.length > 0 + ? renderCity(hotCities, hotCitiesGroupName, HOT_CITY_TYPE.code) + : null} + {cities?.length > 0 ? ( +
+ {cities.map((item, cityGroupIndex) => { + if (!item?.groupName) return null; + return ( +
+ {renderTitile(item.groupName, item.groupName)} +
    + {item.cities.map((city, cityIndex) => { + return ( +
  • { + selectHandler(e, city); + }} + > + {city.name} +
  • + ); + })} +
+
+ ); + })} +
+ ) : null} +
+
+ {codeGroup?.length > 0 && height ? ( +
+
    + {codeGroup.map((item, chartIndex) => { + return ( +
  • { + codeClickHandler(item.code || item); + }} + style={{ + maxHeight: `calc((${height} - ${DEVIATION_HEIGHT}) / ${codeGroup.length})`, + }} + > + {item.title || item} +
  • + ); + })} +
+
+ ) : null} +
+ ); + }, +); + +CitySelector.displayName = 'BuiCitySelector'; + +export default CitySelector; diff --git a/packages/bui-core/src/CitySelector/Selector/index.less b/packages/bui-core/src/CitySelector/Selector/index.less new file mode 100644 index 0000000..5ab2c74 --- /dev/null +++ b/packages/bui-core/src/CitySelector/Selector/index.less @@ -0,0 +1,13 @@ +@import '~@bifrostui/styles/mixins/index.less'; + +.bui-city-selector-item { + width: 111px; + height: 36px; + display: inline-flex; + justify-content: center; + align-items: center; + border-radius: 20px; + margin: 4.5px 0 4.5px 9px; + background-color: var(--bui-color-bg-default); + font-size: 13px; +} diff --git a/packages/bui-core/src/CitySelector/Selector/index.tsx b/packages/bui-core/src/CitySelector/Selector/index.tsx new file mode 100644 index 0000000..aa0d6c9 --- /dev/null +++ b/packages/bui-core/src/CitySelector/Selector/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { cityType } from '../CitySelector.types'; +import './index.less'; + +type propsType = { + city: cityType; + onSelect: (e: React.SyntheticEvent, city: cityType) => void; +}; + +const Selector = (props: propsType) => { + const { city, onSelect } = props; + return ( + { + onSelect?.(e, city); + }} + > + {city.name} + + ); +}; + +export default Selector; diff --git a/packages/bui-core/src/CitySelector/__tests__/CitySelector.snapshot.test.tsx b/packages/bui-core/src/CitySelector/__tests__/CitySelector.snapshot.test.tsx new file mode 100644 index 0000000..e4db051 --- /dev/null +++ b/packages/bui-core/src/CitySelector/__tests__/CitySelector.snapshot.test.tsx @@ -0,0 +1,5 @@ +import { snapshotTest } from 'testing'; + +describe('CitySelector snapshot', () => { + snapshotTest('CitySelector'); +}); diff --git a/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx b/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx new file mode 100644 index 0000000..8fff063 --- /dev/null +++ b/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { + screen, + isConformant, + render, + userEvent, + fireEvent, + waitFor, +} from 'testing'; +import CitySelector from '../CitySelector'; +import { hotCities, cities } from '../mock'; + +const selectedCity = { code: '310100', name: '上海' }; +const selectedCityGroupName = '当前城市'; +const currentCity = { code: '310100', name: '上海' }; +const currentCityGroupName = '定位城市'; +const hotCitiesGroupName = '热门城市'; +const title = '选择城市'; +const onSelect = jest.fn(); +const onClose = jest.fn(); + +const queryEle = (container, selector) => { + return container.querySelector(selector); +}; + +describe('CitySelector', () => { + isConformant({ + Component: CitySelector, + displayName: 'BuiCitySelector', + className: 'bui-city-selector', + skip: ['component-has-root-ref'], + requiredProps: { + cities, + }, + }); + describe('prop: content', () => { + it('render with citySelector', async () => { + const { container } = render( + , + ); + + expect(queryEle(container, '#CRRT')).toBeInTheDocument(); + expect(queryEle(container, '#GPS')).toBeInTheDocument(); + expect(queryEle(container, '#HOT')).toBeInTheDocument(); + expect( + queryEle(container, '.bui-city-selector-list-container'), + ).toBeInTheDocument(); + expect( + queryEle(container, '.bui-city-selector-title'), + ).toBeInTheDocument(); + userEvent.click(container.querySelector('.bui-city-selector-btn-close')); + expect(onClose).toHaveBeenCalledTimes(1); + userEvent.click( + container.querySelector( + '.bui-city-selector-list-container .bui-city-selector-list-item', + ), + ); + expect(onSelect).toHaveBeenCalledTimes(1); + + userEvent.click(container.querySelector('.bui-city-selector-item')); + expect(onSelect).toHaveBeenCalledTimes(2); + + const $scrollView = container.querySelector( + `.bui-city-selector-scroll-view-container`, + ); + fireEvent.scroll($scrollView, { + target: { scrollTop: 200 }, + }); + expect($scrollView.scrollTop).toBe(200); + + await waitFor(() => { + userEvent.click( + container.querySelector( + '.bui-city-selector-index-item[data-code="D"]', + ), + ); + const cityText = screen.getByText('大连'); + expect(cityText).toBeVisible(); + + const cityCodeS = container.querySelector( + '.bui-city-selector-index-item[data-code="S"]', + ); + const mockElementFromPoint = jest.fn(() => cityCodeS); + // 替换原生函数 + Object.defineProperty(document, 'elementFromPoint', { + value: mockElementFromPoint, + writable: true, + }); + const $codeContainer = queryEle( + container, + '.bui-city-selector-index-list', + ); + fireEvent.touchMove($codeContainer, { + changedTouches: [ + { + clientX: 350, + clientY: 223, + }, + ], + cancelable: true, + bubbles: true, + }); + const citySText = screen.getByText('三门峡'); + expect(citySText).toBeVisible(); + }); + }); + + it('render with citySelector special', async () => { + const { container } = render( + , + ); + + const $listContainer = queryEle( + container, + '.bui-city-selector-list-container', + ); + expect($listContainer).toBe(null); + + const $codeContainer = queryEle( + container, + '.bui-city-selector-index-list', + ); + expect($codeContainer).toBe(null); + }); + }); +}); diff --git a/packages/bui-core/src/CitySelector/index.md b/packages/bui-core/src/CitySelector/index.md new file mode 100644 index 0000000..4045d5c --- /dev/null +++ b/packages/bui-core/src/CitySelector/index.md @@ -0,0 +1,375 @@ +--- +group: 数据展示 +name: CitySelector 城市选择 +--- + +# CitySelector 城市选择 + +城市选择 + +## 代码演示 + +### 基础用法 + +```tsx +import React from 'react'; +import { CitySelector } from '@bifrostui/react'; + +const hotCities = [ + { + code: '110100', + name: '北京', + }, + { + code: '310100', + name: '上海', + }, + { + code: '440100', + name: '广州', + }, +]; + +const cities = [ + { + groupName: 'A', + cities: [ + { + code: '610900', + name: '安康', + }, + { + code: '210300', + name: '鞍山', + }, + ], + }, + { + groupName: 'B', + cities: [ + { + code: '652800', + name: '巴音郭楞', + }, + { + code: '511900', + name: '巴中', + }, + ], + }, + { + groupName: 'C', + cities: [ + { + code: '130900', + name: '沧州', + }, + { + code: '220100', + name: '长春', + }, + ], + }, + { + groupName: 'D', + cities: [ + { + code: '532900', + name: '大理', + }, + { + code: '210200', + name: '大连', + }, + ], + }, +]; + +export default () => { + const selectedCity = { + code: '110100', + name: '北京', + }; + const currentCity = { + code: '310100', + name: '上海', + }; + + const onSelect = (city) => { + console.log(city); + }; + + const onHide = () => { + console.log('onHide'); + }; + + return ( + + ); +}; +``` + +### 不展示导航用法 + +```tsx +import React from 'react'; +import { CitySelector } from '@bifrostui/react'; + +const hotCities = [ + { + code: '110100', + name: '北京', + }, + { + code: '310100', + name: '上海', + }, + { + code: '440100', + name: '广州', + }, +]; + +const cities = [ + { + groupName: 'A', + cities: [ + { + code: '610900', + name: '安康', + }, + { + code: '210300', + name: '鞍山', + }, + ], + }, + { + groupName: 'B', + cities: [ + { + code: '652800', + name: '巴音郭楞', + }, + { + code: '511900', + name: '巴中', + }, + ], + }, + { + groupName: 'C', + cities: [ + { + code: '130900', + name: '沧州', + }, + { + code: '220100', + name: '长春', + }, + ], + }, + { + groupName: 'D', + cities: [ + { + code: '532900', + name: '大理', + }, + { + code: '210200', + name: '大连', + }, + ], + }, +]; + +export default () => { + const selectedCity = { + code: '110100', + name: '北京', + }; + const currentCity = { + code: '310100', + name: '上海', + }; + + const onSelect = (city) => { + console.log(city); + }; + + const onHide = () => { + console.log('onHide'); + }; + + return ( + + ); +}; +``` + +### 不展示title用法 + +```tsx +import React from 'react'; +import { CitySelector } from '@bifrostui/react'; + +const hotCities = [ + { + code: '110100', + name: '北京', + }, + { + code: '310100', + name: '上海', + }, + { + code: '440100', + name: '广州', + }, +]; + +const cities = [ + { + groupName: 'A', + cities: [ + { + code: '610900', + name: '安康', + }, + { + code: '210300', + name: '鞍山', + }, + ], + }, + { + groupName: 'B', + cities: [ + { + code: '652800', + name: '巴音郭楞', + }, + { + code: '511900', + name: '巴中', + }, + ], + }, + { + groupName: 'C', + cities: [ + { + code: '130900', + name: '沧州', + }, + { + code: '220100', + name: '长春', + }, + ], + }, + { + groupName: 'D', + cities: [ + { + code: '532900', + name: '大理', + }, + { + code: '210200', + name: '大连', + }, + ], + }, +]; + +export default () => { + const selectedCity = { + code: '110100', + name: '北京', + }; + const currentCity = { + code: '310100', + name: '上海', + }; + + const onSelect = (city) => { + console.log(city); + }; + + const onHide = () => { + console.log('onHide'); + }; + + return ( + + ); +}; +``` + +### API + +##### CitySelectorProps + +| 属性 | 说明 | 类型 | 默认值 | +| --------------------- | ----------------------------------- | ---------------------------------------------------- | ---------- | +| cities | 城市列表 | CityGroup[] | - | +| onSelect | 选择城市回调 | (e: React.SyntheticEvent,data: {city: City}) => void | - | +| selectedCity | 当前城市信息 | City | - | +| selectedCityGroupName | 当前城市栏的title | string | '当前城市' | +| currentCity | 定位城市信息 | City | - | +| currentCityGroupName | 定位城市栏的title | string | '定位城市' | +| hotCities | 热门城市信息 | City | - | +| hotCitiesGroupName | 热门城市栏的title | string | '热门城市' | +| disableIndex | 禁用展示索引 默认false 即展示索引 | boolean | false | +| title | 头部title,非必传 | string | - | +| onClose | 和title配合使用,头部右侧的关闭回调 | (e: React.SyntheticEvent) => void | - | + +##### CityGroup + +| 属性 | 说明 | 类型 | 默认值 | +| --------- | -------- | ------ | ------ | +| groupName | 分组名 | string | - | +| cities | 城市列表 | City[] | - | + +##### City + +| 属性 | 说明 | 类型 | 默认值 | +| ---- | ------ | ------ | ------ | +| code | 城市id | string | - | +| name | 城市名 | string | - | diff --git a/packages/bui-core/src/CitySelector/index.ts b/packages/bui-core/src/CitySelector/index.ts new file mode 100644 index 0000000..482a275 --- /dev/null +++ b/packages/bui-core/src/CitySelector/index.ts @@ -0,0 +1,2 @@ +export { default as CitySelector, default } from './CitySelector'; +export * from './CitySelector.types'; diff --git a/packages/bui-core/src/CitySelector/miniapp.less b/packages/bui-core/src/CitySelector/miniapp.less new file mode 100644 index 0000000..120abcd --- /dev/null +++ b/packages/bui-core/src/CitySelector/miniapp.less @@ -0,0 +1,4 @@ +.bui-city-scroll-view-container { + height: 100%; + display: block; +} diff --git a/packages/bui-core/src/CitySelector/mock.ts b/packages/bui-core/src/CitySelector/mock.ts new file mode 100644 index 0000000..17cd278 --- /dev/null +++ b/packages/bui-core/src/CitySelector/mock.ts @@ -0,0 +1,1040 @@ +export const cities = [ + { + groupName: '', + cities: [ + { + code: '610900', + name: '错误测试', + }, + ], + }, + { + groupName: 'A', + cities: [ + { + code: '610900', + name: '安康', + }, + { + code: '210300', + name: '鞍山', + }, + { + code: '520400', + name: '安顺', + }, + { + code: '410500', + name: '安阳', + }, + { + code: '820100', + name: '澳门', + }, + ], + }, + { + groupName: 'B', + cities: [ + { + code: '652800', + name: '巴音郭楞', + }, + { + code: '511900', + name: '巴中', + }, + { + code: '130600', + name: '保定', + }, + { + code: '610300', + name: '宝鸡', + }, + { + code: '530500', + name: '保山', + }, + { + code: '150200', + name: '包头', + }, + { + code: '450500', + name: '北海', + }, + { + code: '110100', + name: '北京', + }, + { + code: '210500', + name: '本溪', + }, + { + code: '340300', + name: '蚌埠', + }, + { + code: '522400', + name: '毕节', + }, + { + code: '371600', + name: '滨州', + }, + { + code: '341600', + name: '亳州', + }, + ], + }, + { + groupName: 'C', + cities: [ + { + code: '130900', + name: '沧州', + }, + { + code: '220100', + name: '长春', + }, + { + code: '430100', + name: '长沙', + }, + { + code: '140400', + name: '长治', + }, + { + code: '320400', + name: '常州', + }, + { + code: '445100', + name: '潮州', + }, + { + code: '431000', + name: '郴州', + }, + { + code: '130800', + name: '承德', + }, + { + code: '510100', + name: '成都', + }, + { + code: '150400', + name: '赤峰', + }, + { + code: '500100', + name: '重庆', + }, + { + code: '341100', + name: '滁州', + }, + ], + }, + { + groupName: 'D', + cities: [ + { + code: '532900', + name: '大理', + }, + { + code: '210200', + name: '大连', + }, + { + code: '230600', + name: '大庆', + }, + { + code: '140200', + name: '大同', + }, + { + code: '511700', + name: '达州', + }, + { + code: '371400', + name: '德州', + }, + { + code: '469007', + name: '东方', + }, + { + code: '441900', + name: '东莞', + }, + { + code: '370500', + name: '东营', + }, + ], + }, + { + groupName: 'E', + cities: [ + { + code: '150600', + name: '鄂尔多斯', + }, + ], + }, + { + groupName: 'F', + cities: [ + { + code: '440600', + name: '佛山', + }, + { + code: '210400', + name: '抚顺', + }, + { + code: '210900', + name: '阜新', + }, + { + code: '341200', + name: '阜阳', + }, + { + code: '350100', + name: '福州', + }, + ], + }, + { + groupName: 'G', + cities: [ + { + code: '360700', + name: '赣州', + }, + { + code: '510800', + name: '广元', + }, + { + code: '440100', + name: '广州', + }, + { + code: '450300', + name: '桂林', + }, + { + code: '520100', + name: '贵阳', + }, + ], + }, + { + groupName: 'H', + cities: [ + { + code: '230100', + name: '哈尔滨', + }, + { + code: '460100', + name: '海口', + }, + { + code: '990990', + name: '海外', + }, + { + code: '130400', + name: '邯郸', + }, + { + code: '610700', + name: '汉中', + }, + { + code: '330100', + name: '杭州', + }, + { + code: '410600', + name: '鹤壁', + }, + { + code: '340100', + name: '合肥', + }, + { + code: '230400', + name: '鹤岗', + }, + { + code: '441600', + name: '河源', + }, + { + code: '371700', + name: '菏泽', + }, + { + code: '131100', + name: '衡水', + }, + { + code: '532500', + name: '红河', + }, + { + code: '150100', + name: '呼和浩特', + }, + { + code: '211400', + name: '葫芦岛', + }, + { + code: '330500', + name: '湖州', + }, + { + code: '320800', + name: '淮安', + }, + { + code: '421100', + name: '黄冈', + }, + { + code: '341000', + name: '黄山', + }, + { + code: '420200', + name: '黄石', + }, + { + code: '441300', + name: '惠州', + }, + ], + }, + { + groupName: 'J', + cities: [ + { + code: '360800', + name: '吉安', + }, + { + code: '220200', + name: '吉林', + }, + { + code: '370100', + name: '济南', + }, + { + code: '370800', + name: '济宁', + }, + { + code: '410894', + name: '济源', + }, + { + code: '330400', + name: '嘉兴', + }, + { + code: '440700', + name: '江门', + }, + { + code: '445200', + name: '揭阳', + }, + { + code: '140500', + name: '晋城', + }, + { + code: '330700', + name: '金华', + }, + { + code: '210700', + name: '锦州', + }, + { + code: '360200', + name: '景德镇', + }, + { + code: '420800', + name: '荆门', + }, + { + code: '421000', + name: '荆州', + }, + { + code: '360400', + name: '九江', + }, + { + code: '620900', + name: '酒泉', + }, + ], + }, + { + groupName: 'K', + cities: [ + { + code: '410200', + name: '开封', + }, + { + code: '650200', + name: '克拉玛依', + }, + { + code: '530100', + name: '昆明', + }, + ], + }, + { + groupName: 'L', + cities: [ + { + code: '540100', + name: '拉萨', + }, + { + code: '620100', + name: '兰州', + }, + { + code: '131000', + name: '廊坊', + }, + { + code: '511100', + name: '乐山', + }, + { + code: '530700', + name: '丽江', + }, + { + code: '331100', + name: '丽水', + }, + { + code: '320700', + name: '连云港', + }, + { + code: '371500', + name: '聊城', + }, + { + code: '211000', + name: '辽阳', + }, + { + code: '371300', + name: '临沂', + }, + { + code: '520200', + name: '六盘水', + }, + { + code: '450200', + name: '柳州', + }, + { + code: '341500', + name: '六安', + }, + { + code: '510500', + name: '泸州', + }, + { + code: '411100', + name: '漯河', + }, + { + code: '410300', + name: '洛阳', + }, + { + code: '141100', + name: '吕梁', + }, + ], + }, + { + groupName: 'M', + cities: [ + { + code: '340500', + name: '马鞍山', + }, + { + code: '441400', + name: '梅州', + }, + { + code: '510700', + name: '绵阳', + }, + { + code: '231000', + name: '牡丹江', + }, + ], + }, + { + groupName: 'N', + cities: [ + { + code: '360100', + name: '南昌', + }, + { + code: '511300', + name: '南充', + }, + { + code: '320100', + name: '南京', + }, + { + code: '450100', + name: '南宁', + }, + { + code: '350700', + name: '南平', + }, + { + code: '320600', + name: '南通', + }, + { + code: '411300', + name: '南阳', + }, + { + code: '511000', + name: '内江', + }, + { + code: '330200', + name: '宁波', + }, + { + code: '350900', + name: '宁德', + }, + ], + }, + { + groupName: 'P', + cities: [ + { + code: '211100', + name: '盘锦', + }, + { + code: '510400', + name: '攀枝花', + }, + { + code: '410400', + name: '平顶山', + }, + { + code: '360300', + name: '萍乡', + }, + { + code: '350300', + name: '莆田', + }, + { + code: '410900', + name: '濮阳', + }, + ], + }, + { + groupName: 'Q', + cities: [ + { + code: '230200', + name: '齐齐哈尔', + }, + { + code: '429005', + name: '潜江', + }, + { + code: '130300', + name: '秦皇岛', + }, + { + code: '370200', + name: '青岛', + }, + { + code: '441800', + name: '清远', + }, + { + code: '530300', + name: '曲靖', + }, + { + code: '330800', + name: '衢州', + }, + { + code: '350500', + name: '泉州', + }, + ], + }, + { + groupName: 'R', + cities: [ + { + code: '371100', + name: '日照', + }, + ], + }, + { + groupName: 'S', + cities: [ + { + code: '411200', + name: '三门峡', + }, + { + code: '350400', + name: '三明', + }, + { + code: '460200', + name: '三亚', + }, + { + code: '440500', + name: '汕头', + }, + { + code: '310100', + name: '上海', + }, + { + code: '611000', + name: '商洛', + }, + { + code: '411400', + name: '商丘', + }, + { + code: '440200', + name: '韶关', + }, + { + code: '330600', + name: '绍兴', + }, + { + code: '430500', + name: '邵阳', + }, + { + code: '210100', + name: '沈阳', + }, + { + code: '440300', + name: '深圳', + }, + { + code: '130100', + name: '石家庄', + }, + { + code: '220300', + name: '四平', + }, + { + code: '321300', + name: '宿迁', + }, + { + code: '320500', + name: '苏州', + }, + ], + }, + { + groupName: 'T', + cities: [ + { + code: '370900', + name: '泰安', + }, + { + code: '140100', + name: '太原', + }, + { + code: '331000', + name: '台州', + }, + { + code: '321200', + name: '泰州', + }, + { + code: '130200', + name: '唐山', + }, + { + code: '120100', + name: '天津', + }, + { + code: '620500', + name: '天水', + }, + { + code: '211200', + name: '铁岭', + }, + ], + }, + { + groupName: 'W', + cities: [ + { + code: '370700', + name: '潍坊', + }, + { + code: '371000', + name: '威海', + }, + { + code: '610500', + name: '渭南', + }, + { + code: '330300', + name: '温州', + }, + { + code: '420100', + name: '武汉', + }, + { + code: '340200', + name: '芜湖', + }, + { + code: '650100', + name: '乌鲁木齐', + }, + { + code: '320200', + name: '无锡', + }, + ], + }, + { + groupName: 'X', + cities: [ + { + code: '610100', + name: '西安', + }, + { + code: '630100', + name: '西宁', + }, + { + code: '532800', + name: '西双版纳', + }, + { + code: '350200', + name: '厦门', + }, + { + code: '610400', + name: '咸阳', + }, + { + code: '810100', + name: '香港', + }, + { + code: '430300', + name: '湘潭', + }, + { + code: '420600', + name: '襄阳', + }, + { + code: '420900', + name: '孝感', + }, + { + code: '410700', + name: '新乡', + }, + { + code: '140900', + name: '忻州', + }, + { + code: '130500', + name: '邢台', + }, + { + code: '411000', + name: '许昌', + }, + { + code: '320300', + name: '徐州', + }, + ], + }, + { + groupName: 'Y', + cities: [ + { + code: '610600', + name: '延安', + }, + { + code: '320900', + name: '盐城', + }, + { + code: '370600', + name: '烟台', + }, + { + code: '140300', + name: '阳泉', + }, + { + code: '321000', + name: '扬州', + }, + { + code: '511500', + name: '宜宾', + }, + { + code: '420500', + name: '宜昌', + }, + { + code: '360900', + name: '宜春', + }, + { + code: '654000', + name: '伊犁', + }, + { + code: '640100', + name: '银川', + }, + { + code: '210800', + name: '营口', + }, + { + code: '431100', + name: '永州', + }, + { + code: '450900', + name: '玉林', + }, + { + code: '610800', + name: '榆林', + }, + { + code: '530400', + name: '玉溪', + }, + { + code: '140800', + name: '运城', + }, + ], + }, + { + groupName: 'Z', + cities: [ + { + code: '370400', + name: '枣庄', + }, + { + code: '440800', + name: '湛江', + }, + { + code: '130700', + name: '张家口', + }, + { + code: '620700', + name: '张掖', + }, + { + code: '350600', + name: '漳州', + }, + { + code: '441200', + name: '肇庆', + }, + { + code: '321100', + name: '镇江', + }, + { + code: '410100', + name: '郑州', + }, + { + code: '442000', + name: '中山', + }, + { + code: '411600', + name: '周口', + }, + { + code: '330900', + name: '舟山', + }, + { + code: '440400', + name: '珠海', + }, + { + code: '411700', + name: '驻马店', + }, + { + code: '430200', + name: '株洲', + }, + { + code: '370300', + name: '淄博', + }, + { + code: '510300', + name: '自贡', + }, + { + code: '520300', + name: '遵义', + }, + ], + }, +]; + +export const hotCities = [ + { + code: '110100', + name: '北京', + }, + { + code: '310100', + name: '上海', + }, + { + code: '440100', + name: '广州', + }, + { + code: '440300', + name: '深圳', + }, + { + code: '330100', + name: '杭州', + }, + { + code: '320100', + name: '南京', + }, + { + code: '510100', + name: '成都', + }, + { + code: '420100', + name: '武汉', + }, + { + code: '120100', + name: '天津', + }, + { + code: '210100', + name: '沈阳', + }, + { + code: '610100', + name: '西安', + }, + { + code: '330200', + name: '宁波', + }, + { + code: '0', + name: '海外', + }, + { + code: '350600', + name: '漳州', + }, +]; diff --git a/packages/bui-core/src/index.ts b/packages/bui-core/src/index.ts index b987ce0..d836734 100644 --- a/packages/bui-core/src/index.ts +++ b/packages/bui-core/src/index.ts @@ -36,3 +36,4 @@ export * from './NavBar'; export * from './Loading'; export * from './TabBar'; export * from './Countdown'; +export * from './CitySelector'; From dd9f3deb3c95ad855627437c3369c4ed81ec56dc Mon Sep 17 00:00:00 2001 From: --global Date: Tue, 27 Aug 2024 16:25:52 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=8F=98=E9=87=8F=E9=80=82?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/CitySelector/CitySelector.less | 7 +- .../src/CitySelector/CitySelector.miniapp.tsx | 53 +- .../src/CitySelector/CitySelector.types.ts | 2 +- .../src/CitySelector/CitySelectorCore.tsx | 20 +- .../src/CitySelector/Selector/index.less | 2 +- .../__tests__/CitySelector.test.tsx | 2 +- .../CitySelector.snapshot.test.tsx.snap | 579 ++++++++++++++++++ .../src/CitySelector/{ => __tests__}/mock.ts | 0 packages/bui-core/src/CitySelector/index.md | 16 +- 9 files changed, 644 insertions(+), 37 deletions(-) create mode 100644 packages/bui-core/src/CitySelector/__tests__/__snapshots__/CitySelector.snapshot.test.tsx.snap rename packages/bui-core/src/CitySelector/{ => __tests__}/mock.ts (100%) diff --git a/packages/bui-core/src/CitySelector/CitySelector.less b/packages/bui-core/src/CitySelector/CitySelector.less index 3d50c2d..1fe21eb 100644 --- a/packages/bui-core/src/CitySelector/CitySelector.less +++ b/packages/bui-core/src/CitySelector/CitySelector.less @@ -1,7 +1,9 @@ @import '~@bifrostui/styles/mixins/index.less'; .bui-city-selector { + font-family: var(--bui-font-family); height: 100%; + position: relative; &-title { width: 100%; @@ -30,7 +32,6 @@ &-scroll-view-container { height: 100%; - display: flex; &.container-has-title { height: calc(100% - 45px); @@ -55,13 +56,13 @@ font-size: var(--bui-title-size-4); line-height: 15px; font-weight: 600; - padding-left: 12px; + padding-left: var(--bui-spacing-lg); padding-top: 9px; } } &-list { - padding-left: 12px; + padding-left: var(--bui-spacing-lg); list-style-type: none; } diff --git a/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx b/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx index 9dc219c..b0115ea 100644 --- a/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx +++ b/packages/bui-core/src/CitySelector/CitySelector.miniapp.tsx @@ -11,33 +11,38 @@ const CitySelector = React.forwardRef( const codeHeight = useRef(0); const [height, setHeight] = useState(''); + const queryContainerTop = (cbk?) => { + const query = Taro.createSelectorQuery(); + query.select('.bui-city-selector-index-container').boundingClientRect(); + query.exec((res) => { + containerTop.current = res[0]?.top; + cbk?.(); + }); + }; + useEffect(() => { if (cities?.length === 0 || codeHeight.current) return; - Taro.createSelectorQuery() - .select('.bui-city-selector-index-list') - .boundingClientRect((rect: any) => { - containerTop.current = rect?.top; - }) - .exec(); - Taro.createSelectorQuery() - .select('.bui-city-selector-index-item') - .boundingClientRect((codeRect: any) => { - codeHeight.current = codeRect?.height; - }) - .exec(); + // 演示获取字母高度 + setTimeout(() => { + const query = Taro.createSelectorQuery(); + query.select('.bui-city-selector-index-item').boundingClientRect(); + query.exec((res) => { + codeHeight.current = res[0]?.height; + }); + }, 300); }, [cities, height]); useEffect(() => { if (!cities?.length || height) return; const { screenHeight } = Taro.getSystemInfoSync(); - - Taro.createSelectorQuery() + const query = Taro.createSelectorQuery(); + query .select('.bui-city-selector-scroll-view-container') - .boundingClientRect((codeRect: any) => { - const domHeight = codeRect?.height; - setHeight(`${(domHeight / screenHeight) * 100}vh`); - }) - .exec(); + .boundingClientRect(); + query.exec((codeRect: any) => { + const domHeight = codeRect?.[0]?.height; + setHeight(`${(domHeight / screenHeight) * 100}vh`); + }); }, [cities]); const parseIndex = (length, index) => { @@ -46,8 +51,7 @@ const CitySelector = React.forwardRef( return index; }; - const touchHandler = (event, scrollToCode, codeGroup) => { - const { clientY } = event.changedTouches[0]; + const pxToCode = (clientY, scrollToCode, codeGroup) => { let index = Math.floor( (clientY - containerTop.current) / codeHeight.current, ); @@ -56,6 +60,13 @@ const CitySelector = React.forwardRef( scrollToCode(codeItem.code || codeItem); }; + const touchHandler = (event, scrollToCode, codeGroup) => { + const { clientY } = event.changedTouches[0]; + queryContainerTop(() => { + pxToCode(clientY, scrollToCode, codeGroup); + }); + }; + return ( ( ref: propsRef, ...others } = props; - const nodeRef = useForkRef(ref, propsRef); + const cityRef = useRef(null); + const nodeRef = useForkRef(ref, propsRef, cityRef); + useTouchEmulator(cityRef.current); const [codeGroup, setCodeGroup] = useState([]); const [codeShow, setCodeShow] = useState(false); const [targetId, setTargetId] = useState(''); // 提取字母 useEffect(() => { - if (cities.length === 0 || codeGroup.length !== 0 || disableIndex) return; + if ( + !cities || + cities?.length === 0 || + codeGroup.length !== 0 || + disableIndex + ) + return; const newGroup = []; if (selectedCity) { @@ -100,7 +108,7 @@ const CitySelector = React.forwardRef( const scrollHandler = throttle(() => { if (targetId) { - setTargetId(''); + setTargetId(undefined); } }, 500); @@ -111,7 +119,7 @@ const CitySelector = React.forwardRef( const renderTitile = (title, titleCode?) => { const parseTitle = (titleCode || title).toUpperCase(); return ( -
+
{title.toUpperCase()}
); diff --git a/packages/bui-core/src/CitySelector/Selector/index.less b/packages/bui-core/src/CitySelector/Selector/index.less index 5ab2c74..fb9262c 100644 --- a/packages/bui-core/src/CitySelector/Selector/index.less +++ b/packages/bui-core/src/CitySelector/Selector/index.less @@ -9,5 +9,5 @@ border-radius: 20px; margin: 4.5px 0 4.5px 9px; background-color: var(--bui-color-bg-default); - font-size: 13px; + font-size: var(--bui-text-size-2); } diff --git a/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx b/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx index 8fff063..0cbaf8a 100644 --- a/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx +++ b/packages/bui-core/src/CitySelector/__tests__/CitySelector.test.tsx @@ -8,7 +8,7 @@ import { waitFor, } from 'testing'; import CitySelector from '../CitySelector'; -import { hotCities, cities } from '../mock'; +import { hotCities, cities } from './mock'; const selectedCity = { code: '310100', name: '上海' }; const selectedCityGroupName = '当前城市'; diff --git a/packages/bui-core/src/CitySelector/__tests__/__snapshots__/CitySelector.snapshot.test.tsx.snap b/packages/bui-core/src/CitySelector/__tests__/__snapshots__/CitySelector.snapshot.test.tsx.snap new file mode 100644 index 0000000..ca93e4b --- /dev/null +++ b/packages/bui-core/src/CitySelector/__tests__/__snapshots__/CitySelector.snapshot.test.tsx.snap @@ -0,0 +1,579 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CitySelector snapshot CitySelector demo snapshot 0 1`] = ` +
+
+
+
+
+ 当前城市 +
+
+ + 北京 + +
+
+
+
+ 定位城市 +
+
+ + 上海 + +
+
+
+
+ 热门城市 +
+
+ + 北京 + + + 上海 + + + 广州 + +
+
+
+
+
+ A +
+
    +
  • + 安康 +
  • +
  • + 鞍山 +
  • +
+
+
+
+ B +
+
    +
  • + 巴音郭楞 +
  • +
  • + 巴中 +
  • +
+
+
+
+ C +
+
    +
  • + 沧州 +
  • +
  • + 长春 +
  • +
+
+
+
+ D +
+
    +
  • + 大理 +
  • +
  • + 大连 +
  • +
+
+
+
+
+
+`; + +exports[`CitySelector snapshot CitySelector demo snapshot 0 2`] = ` +
+
+ 选择城市 +
+ ✕ +
+
+
+
+
+
+ 当前城市 +
+
+ + 北京 + +
+
+
+
+ 定位城市 +
+
+ + 上海 + +
+
+
+
+ 热门城市 +
+
+ + 北京 + + + 上海 + + + 广州 + +
+
+
+
+
+ A +
+
    +
  • + 安康 +
  • +
  • + 鞍山 +
  • +
+
+
+
+ B +
+
    +
  • + 巴音郭楞 +
  • +
  • + 巴中 +
  • +
+
+
+
+ C +
+
    +
  • + 沧州 +
  • +
  • + 长春 +
  • +
+
+
+
+ D +
+
    +
  • + 大理 +
  • +
  • + 大连 +
  • +
+
+
+
+
+
+`; + +exports[`CitySelector snapshot CitySelector demo snapshot 0 3`] = ` +
+
+
+
+
+ 当前城市 +
+
+ + 北京 + +
+
+
+
+ 定位城市 +
+
+ + 上海 + +
+
+
+
+ 热门城市 +
+
+ + 北京 + + + 上海 + + + 广州 + +
+
+
+
+
+ A +
+
    +
  • + 安康 +
  • +
  • + 鞍山 +
  • +
+
+
+
+ B +
+
    +
  • + 巴音郭楞 +
  • +
  • + 巴中 +
  • +
+
+
+
+ C +
+
    +
  • + 沧州 +
  • +
  • + 长春 +
  • +
+
+
+
+ D +
+
    +
  • + 大理 +
  • +
  • + 大连 +
  • +
+
+
+
+
+
+`; diff --git a/packages/bui-core/src/CitySelector/mock.ts b/packages/bui-core/src/CitySelector/__tests__/mock.ts similarity index 100% rename from packages/bui-core/src/CitySelector/mock.ts rename to packages/bui-core/src/CitySelector/__tests__/mock.ts diff --git a/packages/bui-core/src/CitySelector/index.md b/packages/bui-core/src/CitySelector/index.md index 4045d5c..196717e 100644 --- a/packages/bui-core/src/CitySelector/index.md +++ b/packages/bui-core/src/CitySelector/index.md @@ -11,6 +11,8 @@ name: CitySelector 城市选择 ### 基础用法 +城市选择展示当前城市、定位城市、热门城市及所有城市,支持右侧字母导航 + ```tsx import React from 'react'; import { CitySelector } from '@bifrostui/react'; @@ -94,7 +96,6 @@ export default () => { code: '310100', name: '上海', }; - const onSelect = (city) => { console.log(city); }; @@ -113,8 +114,8 @@ export default () => { currentCityGroupName="定位城市" hotCities={hotCities} hotCitiesGroupName="热门城市" - title="选择城市" onClose={onHide} + style={{ height: '500px' }} /> ); }; @@ -122,6 +123,8 @@ export default () => { ### 不展示导航用法 +用户可以设置disableIndex控制右侧字母导航的展示,默认为false,即展示字母导航 + ```tsx import React from 'react'; import { CitySelector } from '@bifrostui/react'; @@ -227,12 +230,15 @@ export default () => { title="选择城市" disableIndex onClose={onHide} + style={{ height: '500px' }} /> ); }; ``` -### 不展示title用法 +### 不展示title和导航用法用法 + +用户可以设置title来控制头部的展示 ```tsx import React from 'react'; @@ -337,6 +343,8 @@ export default () => { hotCities={hotCities} hotCitiesGroupName="热门城市" onClose={onHide} + disableIndex + style={{ height: '500px' }} /> ); }; @@ -354,7 +362,7 @@ export default () => { | selectedCityGroupName | 当前城市栏的title | string | '当前城市' | | currentCity | 定位城市信息 | City | - | | currentCityGroupName | 定位城市栏的title | string | '定位城市' | -| hotCities | 热门城市信息 | City | - | +| hotCities | 热门城市信息 | City[] | - | | hotCitiesGroupName | 热门城市栏的title | string | '热门城市' | | disableIndex | 禁用展示索引 默认false 即展示索引 | boolean | false | | title | 头部title,非必传 | string | - |