diff --git a/.npmignore b/.npmignore index 2be404fcf..3e70cdcd7 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,9 @@ # MIFE dotfiles -# Output files +# npmignore dist/ +docs/ +site/ # Editor generate files .idea/ diff --git a/.sass-lint.yml b/.sass-lint.yml new file mode 100755 index 000000000..cd749591d --- /dev/null +++ b/.sass-lint.yml @@ -0,0 +1,168 @@ +# sass-lint config generated by make-sass-lint-config v0.1.2 +# +# The following scss-lint Linters are not yet supported by sass-lint: +# ChainedClasses, DisableLinterReason, ElsePlacement, PrivateNamingConvention +# PropertyCount, PseudoElement, SelectorDepth, SpaceAfterVariableColon +# SpaceAroundOperator, TrailingWhitespace, UnnecessaryParentReference, VendorPrefixes +# +# The following settings/values are unsupported by sass-lint: +# Linter Indentation, option "allow_non_nested_indentation" +# Linter Indentation, option "character" +# Linter NestingDepth, option "ignore_parent_selectors" +# Linter PropertySortOrder, option "min_properties" +# Linter PropertySortOrder, option "separate_groups" +# Linter SpaceBeforeBrace, option "allow_single_line_padding" + +files: + include: '**/*.scss' +options: + formatter: stylish + merge-default-rules: false +rules: + # class 名称规则 + class-name-format: + - 1 + - convention: hyphenatedbem + bem-depth: + - 0 + - max-depth: 1 + border-zero: + - 1 + - convention: zero + brace-style: + - 1 + - allow-single-line: false + clean-import-paths: + - 1 + - filename-extension: true + leading-underscore: false + empty-line-between-blocks: + - 1 + - ignore-single-line-rulesets: true + extends-before-declarations: 1 + extends-before-mixins: 1 + final-newline: + - 1 + - include: true + force-attribute-nesting: 0 + force-element-nesting: 0 + force-pseudo-nesting: 0 + function-name-format: + - 1 + - allow-leading-underscore: true + convention: hyphenatedlowercase + hex-length: + - 1 + - style: short + hex-notation: + - 1 + - style: lowercase + id-name-format: + - 1 + - convention: hyphenatedlowercase + indentation: + - 1 + - size: 2 + leading-zero: + - 1 + - include: true + mixin-name-format: + - 1 + - allow-leading-underscore: true + convention: hyphenatedlowercase + mixins-before-declarations: 1 + nesting-depth: + - 1 + - max-depth: 3 + no-color-keywords: 1 + no-color-literals: 0 + no-css-comments: 0 + no-debug: 1 + no-duplicate-properties: 0 + no-empty-rulesets: 1 + no-extends: 0 + no-ids: 1 + no-important: 0 + no-invalid-hex: 1 + no-mergeable-selectors: 0 + no-misspelled-properties: + - 1 + - extra-properties: [] + no-qualifying-elements: + - 1 + - allow-element-with-attribute: false + allow-element-with-class: false + allow-element-with-id: false + no-trailing-zero: 1 + no-transition-all: 0 + no-url-protocols: 0 + placeholder-in-extend: 1 + placeholder-name-format: + - 1 + - convention: hyphenatedlowercase + property-sort-order: + - 0 + - ignore-custom-properties: false + property-units: + - 0 + - global: + - ch + - em + - ex + - rem + - cm + - in + - mm + - pc + - pt + - px + - q + - vh + - vw + - vmin + - vmax + - deg + - grad + - rad + - turn + - ms + - s + - Hz + - kHz + - dpi + - dpcm + - dppx + - '%' + per-property: {} + quotes: + - 1 + - style: single + shorthand-values: 1 + single-line-per-selector: 1 + space-after-bang: + - 1 + - include: false + space-after-colon: + - 1 + - include: true + space-after-comma: 1 + space-before-bang: + - 1 + - include: true + space-before-brace: + - 1 + - include: true + space-before-colon: 1 + space-between-parens: + - 1 + - include: false + trailing-semicolon: 1 + url-quotes: 1 + variable-for-property: + - 0 + - properties: [] + variable-name-format: + - 1 + - allow-leading-underscore: true + convention: hyphenatedlowercase + zero-unit: 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 251de5a6c..c035d0767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ > 1. 修订号:当你做了向下兼容的问题修正。 > 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。 +## 1.0.3 +- 新增:级联选择器 `` 组件; +- 新增:进度条 `` 组件; +- 新增:`` 组件增加点击事件; +- 修复:修正 `` 不动态更新的 bug; +- 修复:修改 `` 依赖 date-fns,修改范围选择结束时间; +- 修复:修正文档语言切换的 bug; +- 文档:工作流优化,增加 sass-lint,所有组件无需单独引用样式。 + ## 1.0.2 - 更新:`` 组件,支持主题切换; @@ -18,4 +27,4 @@ ## 1.0.0 - 第一个公开版本,发布基本组件; -- 发布 HIUI 首页和文档。 \ No newline at end of file +- 发布 HIUI 首页和文档。 diff --git a/components/alert/index.js b/components/alert/index.js index 183da95bb..612dcd63f 100755 --- a/components/alert/index.js +++ b/components/alert/index.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' +import './style/index' class Alert extends Component { static propTypes = { diff --git a/components/alert/style/index.js b/components/alert/style/index.js index 63810a681..14dd01250 100644 --- a/components/alert/style/index.js +++ b/components/alert/style/index.js @@ -1 +1,2 @@ import './index.scss' +import '../../style/icon/index.scss' diff --git a/components/alert/style/index.scss b/components/alert/style/index.scss index 0cb89a85a..d7dc76e18 100755 --- a/components/alert/style/index.scss +++ b/components/alert/style/index.scss @@ -1,5 +1,4 @@ @import '../../style/index.scss'; -@import '../../style/icon/index.scss'; .hi-alert { position: relative; diff --git a/components/badge/index.js b/components/badge/index.js index ddc954eb3..7f4adad18 100644 --- a/components/badge/index.js +++ b/components/badge/index.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' +import './style/index' class Badge extends Component { static propTypes = { diff --git a/components/button/index.js b/components/button/index.js index 9ef4811d6..90d973197 100644 --- a/components/button/index.js +++ b/components/button/index.js @@ -1,5 +1,6 @@ import Button from './Button' import ButtonGroup from './ButtonGroup' +import './style/index' Button.Group = ButtonGroup export default Button diff --git a/components/button/style/index.js b/components/button/style/index.js index 63810a681..14dd01250 100644 --- a/components/button/style/index.js +++ b/components/button/style/index.js @@ -1 +1,2 @@ import './index.scss' +import '../../style/icon/index.scss' diff --git a/components/cascader/cascader.js b/components/cascader/cascader.js new file mode 100644 index 000000000..84c221643 --- /dev/null +++ b/components/cascader/cascader.js @@ -0,0 +1,357 @@ +import React, { Component } from 'react' +import ReactDOM from 'react-dom' +import classNames from 'classnames' +import PropTypes from 'prop-types' +import debounce from 'lodash/debounce' +import shallowequal from 'shallowequal' +import Popper from '../popper' +import Menu from './menu' + +class Cascader extends Component { + noHidePopper = false + + static propTypes = { + options: PropTypes.array, + value: PropTypes.oneOfType([ + PropTypes.array + ]), + fieldNames: PropTypes.object, + searchable: PropTypes.bool, + clearable: PropTypes.bool, + disabled: PropTypes.bool, + changeOnSelect: PropTypes.bool, + className: PropTypes.string, + placeholder: PropTypes.string, + noFoundTip: PropTypes.string, + style: PropTypes.object, + onActiveItemChange: PropTypes.func, + onChange: PropTypes.func, + displayRender: PropTypes.func + } + + static defaultProps = { + fieldNames: {}, + options: [], + value: [], + searchable: false, + clearable: true, + disabled: false, + changeOnSelect: false, + placeholder: '请选择', + noFoundTip: '无匹配数据', + onActiveItemChange: () => {}, + onChange: () => {} + } + + constructor (props) { + super(props) + const cascaderValue = this.props.value + const cacheValue = this.props.value + const cascaderLabel = this.getCascaderLabel(cascaderValue) + + this.debouncedKeywordChange = debounce(this.onKeywordChange.bind(this), 300) + this.state = { + filterOptions: false, + cacheValue, + cascaderValue, + cascaderLabel, + popperShow: false, + keyword: '' + } + } + + getChildContext () { + return { + component: this + } + } + + componentWillReceiveProps (props) { + let value = this.state.cacheValue + if (!shallowequal(props.value, this.props.value)) { + value = props.value + } + const cascaderLabel = this.getCascaderLabel(value) + this.setState({ + // cascaderValue: value, + cacheValue: value, // 缓存原始value,用户可能点击option但是没选中,用于恢复初始value + cascaderLabel + }) + } + + componentDidMount () { + window.addEventListener('click', this.hidePopper.bind(this)) + } + + componentWillUnmount () { + window.removeEventListener('click', this.hidePopper.bind(this)) + } + + hidePopper (e) { + !this.noHidePopper && this.setState({ + popperShow: false + }) + this.noHidePopper = false + } + + showPopper () { + this.setState({ + keyword: '', + filterOptions: false, + cascaderValue: this.state.cacheValue, + popperShow: true + }) + this.inputRef.focus() + } + + getCascaderLabel (values) { + if (this.props.displayRender) { + return this.props.displayRender(values) + } + if (!values || values.length === 0) { + return '' + } else { + let labels = [] + let index = 0 + let _options = this.props.options + const labelKey = this.labelKey() + const valueKey = this.valueKey() + const childrenKey = this.childrenKey() + + while (_options && _options.length > 0 && labels.length <= values.length) { + let value = values[index] + index++ + _options.every(option => { + if (option[valueKey] === value) { + labels.push(option[labelKey]) + _options = option[childrenKey] + return false + } else { + _options = [] + return true + } + }) + } + return labels.join(' / ') + } + } + + clearValue (e) { + e.stopPropagation() + this.onChangeValue([], false) + } + + onChangeValue (value, hasChildren) { + const { + onChange, + onActiveItemChange, + changeOnSelect + } = this.props + + this.setState({ + filterOptions: false, + keyword: '', + cascaderValue: value + }, () => { + if (changeOnSelect || !hasChildren) { + onChange(value) + this.setState({ + cacheValue: value, + cascaderLabel: this.getCascaderLabel(value) + }) + } + if (hasChildren) { + onActiveItemChange(value) + } else { + this.hidePopper() + } + }) + } + + onKeywordChange () { + const { + options + } = this.props + const { + keyword + } = this.state + if (!keyword) { + return + } + const labelKey = this.labelKey() + const valueKey = this.valueKey() + const childrenKey = this.childrenKey() + let filterOptions = [] + const initMatchOptions = {options: [], matchCount: 0} + const checkOptions = (options, match) => { + options.map(option => { + let label = option[labelKey] + const value = option[valueKey] + const children = option[childrenKey] + if (label.indexOf(keyword) > -1 || value.indexOf(keyword) > -1) { + match.matchCount++ + } + match.options.push({ + [labelKey]: label, + [valueKey]: value, + disabled: option.disabled + }) + + if (children && children.length > 0) { + checkOptions(children, match) + } else { + if (match.matchCount > 0) { + filterOptions.push(match.options.slice()) + } + } + if (label.indexOf(keyword) > -1 || value.indexOf(keyword) > -1) { + match.matchCount-- + } + match.options.pop() + }) + } + checkOptions(options, initMatchOptions) + filterOptions = this.formatFilterOptions(filterOptions, keyword) + + this.setState({ + filterOptions + }) + } + + formatFilterOptions (filterOptions, keyword) { + const jointOptions = [] + const labelKey = this.labelKey() + const valueKey = this.valueKey() + const { + noFoundTip + } = this.props + + if (filterOptions.length === 0) { + return [{ + [labelKey]: noFoundTip, + [valueKey]: '', + disabled: true + }] + } else { + filterOptions.map(options => { + let jointOption = { + jointOption: true, + [labelKey]: [], + [valueKey]: [] + } + + options.map((option, index) => { + if (index !== 0) { + jointOption[labelKey].push(/) + } + jointOption[labelKey].push(this.hightlightKeyword(option[labelKey], keyword, index)) + jointOption[valueKey].push(option[valueKey]) + option.disabled && (jointOption.disabled = option.disabled) + }) + jointOptions.push(jointOption) + }) + } + + return jointOptions + } + + hightlightKeyword (text, keyword, uniqueKey) { + let parts = text.split(new RegExp(`(${keyword})`, 'gi')) + return ( + + { parts.map((part, i) => + + { part } + + ) + } + + ) + } + + handleClick (e) { + this.noHidePopper = ReactDOM.findDOMNode(this.inputContainer).contains(e.target) + + // e.stopPropagation() + if (!this.props.disabled) { + this.showPopper() + } + } + + labelKey () { + return this.props.fieldNames.label || 'label' + } + + valueKey () { + return this.props.fieldNames.value || 'value' + } + + childrenKey () { + return this.props.fieldNames.children || 'children' + } + + render () { + const { + className, + options, + disabled, + searchable, + clearable, + style + } = this.props + const { + cascaderValue, + cascaderLabel, + keyword, + popperShow, + filterOptions + } = this.state + const extraClass = { + 'hi-cascader--disabled': disabled, + 'hi-cascader--focused': popperShow, + 'hi-cascader--clearable': clearable + } + const expandIcon = popperShow ? 'icon-up' : 'icon-down' + const placeholder = cascaderLabel || this.props.placeholder + + return ( +
+
{ this.inputContainer = node }} onClick={this.handleClick.bind(this)}> + { + this.inputRef = node + }} + className='hi-cascader__input-keyword' + value={(popperShow && keyword) || (!popperShow && cascaderLabel) || ''} + readOnly={!searchable} + disabled={disabled} + placeholder={placeholder} + onChange={e => { this.setState({keyword: e.target.value}) }} + onKeyUp={this.debouncedKeywordChange.bind(this)} + /> + + + { + clearable && + + } + +
+ + this} + onSelect={this.onChangeValue.bind(this)} + /> + +
+ ) + } +} + +Cascader.childContextTypes = { + component: PropTypes.any +} + +export default Cascader diff --git a/components/cascader/index.js b/components/cascader/index.js new file mode 100644 index 000000000..5636337cb --- /dev/null +++ b/components/cascader/index.js @@ -0,0 +1,4 @@ +import Cascader from './Cascader' +import './style/index' + +export default Cascader diff --git a/components/cascader/menu.js b/components/cascader/menu.js new file mode 100644 index 000000000..d2ed60047 --- /dev/null +++ b/components/cascader/menu.js @@ -0,0 +1,99 @@ +import React, { Component } from 'react' +import classNames from 'classnames' +import PropTypes from 'prop-types' +import Loading from '../loading' + +class Menu extends Component { + static propTypes = { + value: PropTypes.array, + options: PropTypes.array, + onSelect: PropTypes.func + } + + root () { + return this.props.root() + } + + getOptionValues (values, optionValue, index) { + if (index === 0) { + return [optionValue] + } else { + return values.slice(0, index).concat([optionValue]) + } + } + + renderMenus () { + const { + value, + options, + onSelect + } = this.props + const root = this.root() + const menus = [] + const valueKey = root.valueKey() + const labelKey = root.labelKey() + const childrenKey = root.childrenKey() + let currentOptions = options.slice() + let deep = 0 + + while (currentOptions) { + let currentValue = value[deep] + const _currentOptions = currentOptions.slice() + currentOptions = false + + menus.push( +
    + { + _currentOptions.length === 0 && + + } + { + _currentOptions.map(option => { + const optionValue = option[valueKey] + const hasChildren = Array.isArray(option[childrenKey]) + const isExpanded = hasChildren && optionValue === currentValue + const expandIcon = isExpanded ? 'icon-right' : 'icon-right' + const optionValues = option.jointOption ? optionValue : this.getOptionValues(value, optionValue, deep) // jointOption为true代表搜索拼接出来的option,直接取value即可 + if (isExpanded) { + currentOptions = option[childrenKey] + } + return ( +
  • { + e.stopPropagation() + !option.disabled && onSelect(optionValues, hasChildren) + }} + key={optionValue} + > + + { option[labelKey] } + + { + hasChildren && + + } +
  • + ) + }) + } +
+ ) + deep++ + } + return menus + } + + render () { + const menus = this.renderMenus() + + return menus + } +} + +export default Menu diff --git a/components/cascader/style/cascader.scss b/components/cascader/style/cascader.scss new file mode 100644 index 000000000..88ab16215 --- /dev/null +++ b/components/cascader/style/cascader.scss @@ -0,0 +1,54 @@ + +.hi-cascader { + &.hi-cascader--focused { + .hi-cascader { + &__input-container { + border-color: #4284F5; + } + } + } + &.hi-cascader--disabled { + cursor: not-allowed; + opacity: .6; + .hi-cascader__input-keyword { + cursor: not-allowed; + } + } + &:not(.hi-cascader--disabled) { + &.hi-cascader--clearable:hover { + .hi-cascader__icon--expand { + display: none; + } + .hi-cascader__icon--clear { + display: block; + color: #999 + } + } + } + &__input-container { + display: flex; + align-items: center; + padding: 5px 12px; + border: 1px solid #d9d9d9; + } + &__input-keyword { + flex: auto; + font-size: 14px; + cursor: pointer; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + border: none; + outline: none; + box-sizing: border-box; + } + &__icon { + flex: none; + height: 22px; + line-height: 22px; + &--clear { + display: none; + cursor: pointer; + } + } +} \ No newline at end of file diff --git a/components/cascader/style/index.js b/components/cascader/style/index.js new file mode 100644 index 000000000..f25eb560d --- /dev/null +++ b/components/cascader/style/index.js @@ -0,0 +1,2 @@ +import './cascader.scss' +import './menu.scss' diff --git a/components/cascader/style/menu.scss b/components/cascader/style/menu.scss new file mode 100644 index 000000000..35c28f154 --- /dev/null +++ b/components/cascader/style/menu.scss @@ -0,0 +1,51 @@ +.hi-cascader__popper { + display: flex; + background-color: #fff; + font-size: 14px; + box-shadow: 0 2px 8px rgba(0,0,0,.15); + z-index: 999; +} + +.hi-cascader-menu { + height: 180px; + min-width: 110px; + overflow: auto; + &:not(:last-child) { + border-right: 1px solid #e8e8e8; + } + &, + &__item { + margin: 0; + padding: 0; + list-style: none; + } + &__item { + position: relative; + padding: 5px 12px; + color: #48576a; + cursor: pointer; + &.hi-cascader-menu__item-disabled { + color: #bfcbd9; + cursor: not-allowed; + } + &.hi-cascader-menu__item-expanded { + padding-right: 25px; + } + &.hi-cascader-menu__item-active { + background-color: #f5f5f5; + } + &:hover { + background-color: #f5f5f5; + } + &--icon { + position: absolute; + right: 12px; + } + &--label-hightlight { + color: #f5222d; + } + &--label-split { + margin: 0 3px; + } + } +} \ No newline at end of file diff --git a/components/checkbox/index.js b/components/checkbox/index.js index d731f1ba0..0d3d6913e 100755 --- a/components/checkbox/index.js +++ b/components/checkbox/index.js @@ -1,3 +1,4 @@ import CheckBox from './CheckBox' +import './style/index' export default CheckBox diff --git a/components/collapse/index.js b/components/collapse/index.js index 229b0667b..6f6f414df 100755 --- a/components/collapse/index.js +++ b/components/collapse/index.js @@ -1,6 +1,7 @@ import React, { Component, Children } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' +import './style/index' const noop = () => {} class Collapse extends Component { diff --git a/components/confirm/index.js b/components/confirm/index.js index d5f88dd3c..5977b8db6 100644 --- a/components/confirm/index.js +++ b/components/confirm/index.js @@ -3,10 +3,7 @@ import PropTypes from 'prop-types' import ReactDOM from 'react-dom' import Modal from '../modal' -import '../modal/style' -import '../button/style' -import '../input/style' -import './style' +import './style/index' class Confirm extends Component { render () { diff --git a/components/counter/index.js b/components/counter/index.js index 0e7f0d2a6..481658084 100644 --- a/components/counter/index.js +++ b/components/counter/index.js @@ -1,5 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' +import './style/index' + /** * 加减器 */ diff --git a/components/date-picker/BasePicker.js b/components/date-picker/BasePicker.js index 148997430..a80e8ee5d 100644 --- a/components/date-picker/BasePicker.js +++ b/components/date-picker/BasePicker.js @@ -2,17 +2,17 @@ import React, {Component} from 'react' import Modal from './Modal' import classNames from 'classnames' import {formatterDate, FORMATS, PLACEHOLDER, isVaildDate} from './constants' -import {dateFormat} from './util' + import PropTypes from 'prop-types' import DatePickerType from './Type' + +import {startOfDay, endOfDay, parse, startOfWeek, endOfWeek, dateFormat} from './dateUtil' export default class BasePicker extends Component { inputRoot = null input = null rInput = null constructor (props) { super(props) - // let {value, type, format} = props - // format = format || FORMATS[type] this.state = { showPanel: false, style: {}, @@ -26,7 +26,24 @@ export default class BasePicker extends Component { } static propTypes = { type: PropTypes.oneOf(Object.values(DatePickerType)), - date: PropTypes.instanceOf(Date), + value: function (props, propName, componentName) { + // Invalid Date + const val = props[propName] + if (val === undefined || val === null) { + return null + } + if (val.start && val.end) { + const _start = dateFormat(val.start) + const _end = dateFormat(val.end) + if (_start === 'Invalid Date' || _end === 'Invalid Date') { + return new Error(`Invalid prop ${propName} supplied to ${componentName}. Validation failed. start or end is an invalid date.`) + } + } else { + if (dateFormat(val) === 'Invalid Date') { + return new Error(`Invalid prop ${propName} supplied to ${componentName}. Validation failed. value is an invalid data.`) + } + } + }, onChange: PropTypes.func, format: PropTypes.string, showTime: PropTypes.bool, @@ -43,41 +60,38 @@ export default class BasePicker extends Component { _parseProps (props, callback) { let {value, showTime, type, format} = props format = format || FORMATS[type] - let text = formatterDate(type, value, format, showTime) - let rText = text - let l = '' - let r = '' - let date = new Date() - if (value instanceof Date) { - // type 为范围选择且 value 传入 一个 Date 类型时,需要计算开始和结束时间 - // value = value.getTime() - // const start = value - 1 * DAY_MILLISECONDS // 得到前一天时间 - l = value - r = value - if (type.indexOf('range') !== -1) { - l = l.setHours(0, 0, 0, 0) - r = r.setHours(23, 59, 59, 0) - date = {startDate: l, endDate: r} - } else { - date = value - } - // date = type.indexOf('range') !== -1 ? {startDate: l, endDate: r} : value + // let text = formatterDate(type, value, format, showTime) + // let rText = text + let date = new Date() // 当前时间 + let noText = false + /** + * value 可能的格式: + * '' | undefined | null | Date | String | Number | {start: xxx, end: xxx} + */ + if (value === '' || !value) { + // value 未传入情况 + date = new Date() + noText = true } - if (typeof value === 'string' || !value) { - date = new Date().getTime() - l = '' - r = '' + if (typeof value === 'number' || (typeof value === 'string' && value.trim().length > 4)) { + // value 为数字(times) + date = parse(value) } - if (value && value.start && value.end) { - l = value.start.getTime() - r = value.end.getTime() - date = {startDate: l, endDate: r} + if (value instanceof Date) { + date = value + } + + if (type.indexOf('range') !== -1) { + if (value instanceof Date || !value) { + date = {startDate: startOfDay(date), endDate: endOfDay(date)} + } + if (value && value.start && value.end) { + date = {startDate: value.start, endDate: value.end} + } } - text = formatterDate(type, l, format, showTime) - rText = formatterDate(type, r, format, showTime) this.setState({ - text, - rText, + text: noText ? '' : formatterDate(type, date.startDate || date, format, showTime), + rText: noText ? '' : formatterDate(type, date.endDate || date, format, showTime), date, placeholder: PLACEHOLDER[props.type] || '请选择日期', format @@ -125,7 +139,7 @@ export default class BasePicker extends Component { this._parseProps(nextProps) } onPick (date, showPanel) { - const {type, showTime, onChange} = this.props + const {type, showTime, onChange, weekOffset} = this.props const {format} = this.state this.setState({ date, @@ -135,8 +149,18 @@ export default class BasePicker extends Component { isFocus: false }) if (onChange) { - if (date.startDate && date.endDate) { - onChange({start: date.startDate, end: date.endDate}) + const {startDate, endDate} = date + const _weekOffset = {weekStartsOn: weekOffset} + if (type === 'week') { + onChange({start: startOfWeek(date, _weekOffset), end: endOfWeek(date, _weekOffset)}) + return + } + if (startDate && endDate) { + if (type === 'weekrange') { + onChange({start: startOfWeek(startDate, _weekOffset), end: endOfWeek(endDate, _weekOffset)}) + } else { + onChange({start: startOfDay(startDate), end: endOfDay(endDate)}) + } } else { onChange(date) } @@ -212,7 +236,6 @@ export default class BasePicker extends Component { }) this.calcPanelPos(this.inputRoot.getBoundingClientRect()) }} - // onBlur={() => this.setState({isFocus: false})} value={text} /> ) @@ -222,27 +245,33 @@ export default class BasePicker extends Component { if (onChange) { onChange(null) } - // this._parseProps(this.props) this.setState({text: '', isFocus: false}) } _icon () { const {isFocus} = this.state const iconCls = classNames( - 'icon', + 'hi-datepicker__input-icon', 'hi-icon', - isFocus ? 'icon-close-circle clear' : 'icon-date', - this.props.disabled && 'disabled' + isFocus ? 'icon-close-circle clear' : 'icon-date' ) - return isFocus ? : { - this.setState({showPanel: true, isFocus: true}) - }} /> + return isFocus + ? + : { + if (this.props.disabled) return + this.setState({showPanel: true, isFocus: true}) + }} /> } - getRangeInput () { + renderRangeInput () { const { disabled } = this.props + const _cls = classNames( + 'hi-datepicker__input', + 'hi-datepicker__input--range', + disabled && 'hi-datepicker__input--disabled' + ) return ( -
+
{this._input(this.state.text, 'input')} {this._input(this.state.rText, 'rInput')} @@ -254,8 +283,13 @@ export default class BasePicker extends Component { const { disabled } = this.props + const _cls = classNames( + 'hi-datepicker__input', + 'hi-datepicker__input--normal', + disabled && 'hi-datepicker__input--disabled' + ) return ( -
+
{this._input(this.state.text, 'input')} {this._icon()}
@@ -264,9 +298,9 @@ export default class BasePicker extends Component { render () { const {type, showTime} = this.props return ( - { this.inputRoot = el }} className='input-root' style={{display: 'inline-block'}}> + { this.inputRoot = el }} className='hi-datepicker__input-root'> { - type.indexOf('range') !== -1 ? this.getRangeInput() : this.renderNormalInput() + type.indexOf('range') !== -1 ? this.renderRangeInput() : this.renderNormalInput() } { this.state.showPanel ? ( @@ -279,5 +313,3 @@ export default class BasePicker extends Component { ) } } - -BasePicker.format = dateFormat diff --git a/components/date-picker/Calender.js b/components/date-picker/Calender.js index dcab36e8d..e240de588 100644 --- a/components/date-picker/Calender.js +++ b/components/date-picker/Calender.js @@ -1,5 +1,15 @@ import React, {Component} from 'react' -import {deconstructDate, getYearWeek, calcDayCount, calcDayWeek, clearHours} from './util' +import {deconstructDate, getYearWeek} from './util' + +import { + getDaysInMonth, + subMonths, + getDay, + startOfMonth, + isWithinRange, + isSameDay, + compareAsc +} from './dateUtil' import {WEEK_DATA, DAY_MILLISECONDS} from './constants' class Calender extends Component { constructor (props) { @@ -22,20 +32,19 @@ class Calender extends Component { getRows () { let {type, range, date, minDate, maxDate, weekOffset} = this.props let _date = new Date(new Date(date).getTime()) - minDate && clearHours(minDate) - maxDate && clearHours(maxDate) let {year, month, week} = deconstructDate(_date) let {endDate, startDate} = range || {startDate: null, endDate: null} // * dayCount: 当月天数 // * lastMonthDayCount: 上月总天数 // * firstDayWeek: 当月第一天是周几 - let firstDayWeek = calcDayWeek(year, month, 1) - weekOffset + let firstDayWeek = getDay(startOfMonth(_date)) - weekOffset if (firstDayWeek <= 0) { // 如果为0 代表该月第一天是周日,在日历上需要第二行开始显示 firstDayWeek = 7 - weekOffset } const _time = this._getTime(firstDayWeek, year, month)// 当前日期面板中第一个日期的具体毫秒数(指向上一个月) - const dayCount = calcDayCount(year, month) - let lastMonthDayCount = calcDayCount(year, month - 1) // 上月总天数 + const dayCount = getDaysInMonth(_date) + + let lastMonthDayCount = getDaysInMonth(subMonths(_date, 1)) // 上月总天数 const {rows} = this.state let count = 0 const now = _date.setHours(0, 0, 0, 0) // 今天 @@ -69,12 +78,11 @@ class Calender extends Component { col.type = 'today' } if (type === 'daterange' || type === 'weekrange') { - col.rangeStart = startDate && time === clearHours(startDate) - col.rangeEnd = endDate && time === clearHours(endDate) - col.range = time > startDate && endDate && time < clearHours(endDate) - // col.range = time >= startDate && endDate && time <= clearHours(endDate) && col.type !== 'prev' && col.type !== 'next' + col.rangeStart = startDate && isSameDay(time, startDate) + col.rangeEnd = endDate && isSameDay(time, endDate) + col.range = endDate && isWithinRange(time, startDate, endDate) } - col.disabled = (minDate && new Date(time) < minDate) || (maxDate && new Date(time) > maxDate) + col.disabled = (minDate && compareAsc(time, minDate) === -1) || (maxDate && compareAsc(time, maxDate) === 1) } if (type === 'week') { let _month = month @@ -117,7 +125,7 @@ class Calender extends Component { const td = e.target const cls = this._getClassName(td) const value = td.getAttribute('value') - if ((td.nodeName !== 'A' && td.nodeName !== 'TD' && td.nodeName !== 'DIV') || td.disabled) return false + if ((td.nodeName !== 'SPAN' && td.nodeName !== 'TD' && td.nodeName !== 'DIV') || td.disabled) return false if (cls.indexOf('disabled') !== -1) return false if (cls.indexOf('prev') !== -1) { month -= 1 @@ -165,7 +173,7 @@ class Calender extends Component { let td = e.target const {mouseMove, date, type, range} = this.props let {year, month} = deconstructDate(date) - if (td.nodeName !== 'A' || td.disabled || type.indexOf('range') === -1 || !range.selecting) return false + if (td.nodeName !== 'SPAN' || td.disabled || type.indexOf('range') === -1 || !range.selecting) return false td = td.parentNode.parentNode const day = parseInt(td.innerText) const cls = td.className @@ -187,7 +195,7 @@ class Calender extends Component { mouseMove(newDate) } getTDClass (td) { - let _class = [] + let _class = ['hi-datepicker__cell'] if (td.disabled) { _class.push('disabled') return _class.join(' ') @@ -220,14 +228,14 @@ class Calender extends Component { const rows = data || this.getRows() return ( { (type.indexOf('date') !== -1 || type.indexOf('week') !== -1) && ( - + { this.getWeeks().map((item, index) => { return @@ -243,7 +251,7 @@ class Calender extends Component { return ( { row.map((cell, _index) => { @@ -253,10 +261,10 @@ class Calender extends Component { value={cell.value} className={this.getTDClass(cell)} > -
- + ) diff --git a/components/date-picker/DatePanel.js b/components/date-picker/DatePanel.js index 2ed7574e3..93c33f0c7 100644 --- a/components/date-picker/DatePanel.js +++ b/components/date-picker/DatePanel.js @@ -4,6 +4,7 @@ import {deconstructDate} from './util' import TimePanel from './TimePanel' import {MONTH_DATA} from './constants' import Icon from '../icon' +import classNames from 'classnames' export default class DatePanel extends Component { constructor (props) { super(props) @@ -15,9 +16,6 @@ export default class DatePanel extends Component { tempDate: new Date(props.date) } } - componentDidMount () { - // f - } componentWillReceiveProps (nextProps) { this.setState({ date: nextProps.date @@ -130,25 +128,25 @@ export default class DatePanel extends Component { renderHeader (type, value) { const {month} = deconstructDate(value) return ( -
-
+
+
{/* this.changeYear(true)} /> */} this.changeYear(true)} > { (type !== 'month' && type !== 'year') && this.changeMonth(true)} > }
- this.setState({currentView: 'year'})}> + this.setState({currentView: 'year'})}> {this.getHeaderCenterContent()} { type !== 'month' && type !== 'year' && ( - + {month}月 ) } -
+
{ (type !== 'month' && type !== 'year') && this.changeMonth(false)}> } @@ -269,17 +267,17 @@ export default class DatePanel extends Component { } renderTimeHeader () { return ( -
- this.setState({currentView: 'date'})} className={this.state.currentView === 'date' ? 'active' : ''}>日期选择 +
+ this.setState({currentView: 'date'})} className={this.state.currentView === 'date' ? 'hi-datepicker__time-header--active' : ''}>日期选择 - this.setState({currentView: 'time'})} className={this.state.currentView === 'time' ? 'active' : ''}>时间选择 + this.setState({currentView: 'time'})} className={this.state.currentView === 'time' ? 'hi-datepicker__time-header--active' : ''}>时间选择
) } renderTimeFooter () { return (
this.props.timeConfirm(this.state.date)} > ok @@ -288,20 +286,23 @@ export default class DatePanel extends Component { } render () { const {date, currentView} = this.state + const {theme} = this.props + const _c = classNames( + 'hi-datepicker', + theme && 'theme__' + theme + ) return (
-
+
{ this.props.showTime && this.renderTimeHeader() } -
-
- {currentView !== 'time' && this.renderHeader(currentView, date)} -
-
+
+ {currentView !== 'time' && this.renderHeader(currentView, date)} +
{this._getNormalComponent()}
diff --git a/components/date-picker/DatePicker.js b/components/date-picker/DatePicker.js index 565c93c49..df95dd004 100644 --- a/components/date-picker/DatePicker.js +++ b/components/date-picker/DatePicker.js @@ -4,7 +4,9 @@ import BasePicker from './BasePicker' import DatePanel from './DatePanel' import DateRangePanel from './DateRangePanel' import WeekRangePanel from './WeekRangePanel' -export default class DatePicker extends BasePicker { +import Provider from '../context' +import dateFormat from 'date-fns/format' +class DatePicker extends BasePicker { initPanel (state, props) { let component = null let d = state.date @@ -55,3 +57,6 @@ export default class DatePicker extends BasePicker { return component } } +const pd = Provider(DatePicker) +pd.format = dateFormat +export default pd diff --git a/components/date-picker/DateRangePanel.js b/components/date-picker/DateRangePanel.js index e17c9625f..56e8d9a8b 100644 --- a/components/date-picker/DateRangePanel.js +++ b/components/date-picker/DateRangePanel.js @@ -4,6 +4,7 @@ import {deconstructDate, nextMonth} from './util' import {DAY_MILLISECONDS} from './constants' import TimePanel from './TimePanel' import Icon from '../icon' +import classNames from 'classnames' export default class DatePanel extends Component { constructor (props) { super(props) @@ -163,27 +164,27 @@ export default class DatePanel extends Component { const {year, month} = deconstructDate(value) return ( -
+
{ -
+
this.changeYear(true, lr)} > { type.indexOf('date') !== -1 && this.changeMonth(true, lr)} > }
} - + {this.getHeaderCenterContent(year)} { (currentView === 'date' || currentView === 'daterange') && ( - + {month}月 ) } { -
+
{ type.indexOf('date') !== -1 && this.changeMonth(false, lr)} > } @@ -240,7 +241,7 @@ export default class DatePanel extends Component { } renderShortcut (shortcuts) { return ( -
+
{ shortcuts.map((m, n) => { return ( @@ -273,7 +274,7 @@ export default class DatePanel extends Component { } renderTimeHeader (flag) { return ( -
+
this.setState({[flag === 'left' ? 'leftView' : 'rightView']: 'date'})}>日期选择 this.setState({[flag === 'left' ? 'leftView' : 'rightView']: 'time'})}>时间选择 @@ -283,7 +284,7 @@ export default class DatePanel extends Component { renderTimeFooter () { return (
{ this.props.timeConfirm(this.state.range) // this.props.onPick(this.state.date) @@ -296,26 +297,28 @@ export default class DatePanel extends Component { render () { let {minDate, maxDate, currentView, range, leftDate, rightDate, leftView, rightView} = this.state // const rightDate = nextMonth(leftDate) - const {shortcuts} = this.props + const {shortcuts, theme} = this.props + const _c = classNames( + 'hi-datepicker', + theme && 'theme__' + theme + ) return (
{ shortcuts && this.renderShortcut(shortcuts) } -
-
+
+
{ this.props.showTime && this.renderTimeHeader('left') } { - leftView !== 'time' &&
- {this.renderHeader(currentView, leftDate, 'left')} -
+ leftView !== 'time' && this.renderHeader(currentView, leftDate, 'left') } -
+
{ leftView === 'time' ?
-
+
{ this.props.showTime && this.renderTimeHeader('right') } { - rightView !== 'time' &&
- {this.renderHeader(currentView, rightDate, 'right')} -
+ rightView !== 'time' && this.renderHeader(currentView, rightDate, 'right') } -
+
{ rightView === 'time' ? 1
- } -} diff --git a/components/date-picker/Time.js b/components/date-picker/Time.js index e971a672f..7b52af04a 100644 --- a/components/date-picker/Time.js +++ b/components/date-picker/Time.js @@ -16,8 +16,8 @@ export default class TimePanel extends Component { seconds: 0 } } - this.liPrefix = props.onlyTime ? [
  • ,
  • ] : [
  • ,
  • ,
  • ] - this.liSuffix = props.onlyTime ? [
  • ,
  • ] : [
  • ,
  • ,
  • ] + this.liPrefix = props.onlyTime ? [1, 2] : [1, 2, 3] + this.liSuffix = props.onlyTime ? [1, 2] : [1, 2, 3] } range (num) { let arr = [] @@ -109,9 +109,17 @@ export default class TimePanel extends Component { render () { const {date} = this.state const {hours, minutes, seconds} = deconstructDate(date) + this.liPrefix = this.liPrefix.map((item, index) => { + return
  • + }) + this.liSuffix = this.liSuffix.map((item, index) => { + return
  • + }) return ( -
    -
      { this.hoursList = el }} +
      +
        { this.hoursList = el }} + className='hi-timepicker__list' onClick={this.clickEvent.bind(this, 'hours')} onMouseEnter={this.mouseOverEvent.bind(this)} > @@ -121,32 +129,42 @@ export default class TimePanel extends Component { return (
      • {m}
      • ) }) } {this.liSuffix}
      -
        { this.minutesList = el }} onClick={this.clickEvent.bind(this, 'minutes')} onMouseEnter={this.mouseOverEvent.bind(this)}> +
          { this.minutesList = el }} + onClick={this.clickEvent.bind(this, 'minutes')} + onMouseEnter={this.mouseOverEvent.bind(this)} + > {this.liPrefix} { this.range(60).map((m, n) => { - return
        • {m}
        • + return
        • {m}
        • }) } {this.liSuffix}
        -
          { this.secondsList = el }} onClick={this.clickEvent.bind(this, 'seconds')} onMouseEnter={this.mouseOverEvent.bind(this)}> +
            { this.secondsList = el }} + className='hi-timepicker__list' + onClick={this.clickEvent.bind(this, 'seconds')} + onMouseEnter={this.mouseOverEvent.bind(this)} + > {this.liPrefix} { this.range(60).map((m, n) => { - return
          • {m}
          • + return
          • {m}
          • }) } {this.liSuffix}
          -
          +
          ) } diff --git a/components/date-picker/TimePanel.js b/components/date-picker/TimePanel.js index c81af3d54..373518ce9 100644 --- a/components/date-picker/TimePanel.js +++ b/components/date-picker/TimePanel.js @@ -34,7 +34,7 @@ export default class TimePanel extends Component {
  • {item}
    - + {this.state.open && } } @@ -133,9 +131,9 @@ render () { ### Attributes -| 参数 | 说明 | 类型 | 可选值 |默认值 | +| Attribute | Description | Type | Options | Default | | -------- | ----- | ---- | ---- | ---- | -| size | 组件大小 | string | large default small | default | -| tip | 自定义的旋转动画下的文字 | string | - | | -| full | 是否全屏 | bool | - | false | -| show | 是否显示加载动画 | boolean | true false | false | \ No newline at end of file +| size | Size | string | large default small | default | +| tip | Text | string | - | | +| full | Whether full screen | bool | - | false | +| show | Whether to display the loading animation | boolean | true false | false | \ No newline at end of file diff --git a/docs/en-US/menu.md b/docs/en-US/menu.md index 45462753b..a25848cb9 100644 --- a/docs/en-US/menu.md +++ b/docs/en-US/menu.md @@ -1,21 +1,21 @@ ## Menu -### 水平排列 +### Horizontal :::demo -水平排列 +Horizontal ```js constructor () { super() this.state = { list: [{ - title: '菜单一' + title: 'Menu one' }, { - title: '菜单二', + title: 'Menu two', }, { - title: '菜单三' + title: 'Menu three' }] } } @@ -30,22 +30,22 @@ ``` ::: -### 竖直排列 +### Vertical :::demo -竖直排列 +Vertical ```js constructor () { super() this.state = { list: [{ - title: '菜单一' + title: 'Menu one' }, { - title: '菜单二' + title: 'Menu two', }, { - title: '菜单三' + title: 'Menu three' }] } } @@ -76,17 +76,20 @@ ### Attributes -| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| Attribute | Description | Type | Options | Default | | -------- | ----- | ---- | ---- | ---- | -| active | 是否激活 | boolean | true / false | false | -| defaultActive | 默认激活(当 active 存在时,此项无效 | boolean | true / false | false | -| text | 文本 | string | - | - | -| value | 文本对应的值,可为空 | - | - | -| mode | 菜单排列模式 | string | horizontal / vertical | vertical | +| active | is active | boolean | true / false | false | +| defaultActive | default active(This item is invalid when active is present | boolean | true / false | false | +| text | text | string | - | - | +| value | value | - | - | +| mode | +6/5000 +Càidān páiliè móshì +Menu arrangement mode | string | horizontal / vertical | vertical | ### Events -| 参数 | 说明 | 回调参数 | +| Attribute | Description | Callback Params | | -------- | ----- | ---- | | onOpen | 打开某菜单事件 | - | | onClose | 关闭某菜单事件 | - | diff --git a/docs/en-US/notification.md b/docs/en-US/notification.md index ae70f50f7..ea04aa518 100755 --- a/docs/en-US/notification.md +++ b/docs/en-US/notification.md @@ -1,6 +1,6 @@ ## Notification -### 基础 +### Basic :::demo @@ -8,17 +8,17 @@ render(){ return(
    - - + +
    ) } open(){ - handleNotificate({type: 'success',autoClose:true,title:'标题',message:'自动关闭通知框',onClose:()=>{console.log('关闭回调')}}) + handleNotificate({type: 'success',autoClose:true,title:'Title',message:'Message',onClose:()=>{console.log('Callback')}}) } open1(){ - handleNotificate({autoClose:false,title:'标题',message:'手动关闭通知框',onClose:()=>{console.log('关闭回调')}}) + handleNotificate({autoClose:false,title:'标Title题',message:'Message',onClose:()=>{console.log('Callback')}}) } ``` @@ -26,10 +26,10 @@ ### Attributes -| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| Attribute | Description | Type | Options | Default | | -------- | ----- | ---- | ---- | ---- | -| type | 类型 | string | info/error/success/warning | info | -| message | 提示内容 | string | - | 无 | -| title | 提示标题 | string | - | 无 | -| autoClose | 是否自动关闭 | bool | - | false | -| onClose | 关闭回调 | func | - | 无 | \ No newline at end of file +| type | type | string | info/error/success/warning | info | +| message | message | string | - | null | +| title | title | string | - | null | +| autoClose | autoClose | bool | - | false | +| onClose | Callback | func | - | null | \ No newline at end of file diff --git a/docs/en-US/pagination.md b/docs/en-US/pagination.md new file mode 100644 index 000000000..89601d863 --- /dev/null +++ b/docs/en-US/pagination.md @@ -0,0 +1,117 @@ +## Pagination + +Pagination + +### 基础分页 + +:::demo + +```js +constructor () { + super() + + this.state = { + current: 1 + } +} +render() { + return ( +
    + {console.log(page, prevPage, pageSize)}} + /> + +
    + ) +} +``` +::: + +### Control + +:::demo + +```js +constructor () { + super() + + this.state = { + current: 2 + } +} +render() { + return ( +
    + + {console.log(page, prevPage, pageSize)}} + /> + +
    + + + +
    + ) +} +``` +::: + + +### Full + +:::demo + +```js +constructor(props) { + super(props) + this.state = { + current: 4, + pageSize: 10 + } +} + +render() { + return ( +
    + {this.setState({current: val})}} + sizeChangeEvent={(val, current) => { + this.setState({pageSize: val}) + } + } + onChange={(page, prevPage, pageSize) => { + console.log(page, prevPage, pageSize) + this.setState({ + current: page, + }) + }} + /> +
    + ) +} +``` +::: + +### Pagination Attributes + +| Attribute | Description | Type | Options |Default | +| -------- | ----- | ---- | ---- | ---- | +| defaultCurrent | default current page number | number | - | 1 | +| pageSize | page size | number | - | 10 | +| total | total count | number | - | - | +| pageLink | If this parameter is set, `#/page={page}` will be added in the url | boolean | - | - | +| onChange | callback | function | - | - | - | +| sizeChangeEvent | size change callback | function | - | - | - | diff --git a/docs/en-US/panel.md b/docs/en-US/panel.md new file mode 100755 index 000000000..f264a1bb2 --- /dev/null +++ b/docs/en-US/panel.md @@ -0,0 +1,60 @@ +## Panel + +### Footers + +:::demo + +```js + render(){ + return( + + + Title + + } + footer="Footers" + > +

    Panel content

    +

    Panel content

    +

    Panel content

    +
    + ) + } + +``` +::: + + +### No Footers + +:::demo + + +```js + render(){ + return( + +

    Panel content

    +

    Panel content

    +

    Panel content

    +
    + ) + } + +``` +::: + + +### Attributes + +| Attribute | Description | Type | Options | Default | +| -------- | ----- | ---- | ---- | ---- | +| icon | panel title icon | string | - | null | +| title | panel title | string
    Node
    React.Component | - | null | +| footer | panel footer | string
    Node
    React.Component | - | null | + diff --git a/docs/en-US/popover.md b/docs/en-US/popover.md new file mode 100644 index 000000000..28998d5f8 --- /dev/null +++ b/docs/en-US/popover.md @@ -0,0 +1,45 @@ +## Popover + + +### Basic + +:::demo + + +```js +render() { + const title = Popover Title + const content = ( +
    +

    Vivamus sagittis lacus vel augue laoreet rutrum faucibus.

    +
    + ) + + return ( +
    + + + + + + + + + + + + +
    + ) +} +``` +::: + +### Popover Attributes + +| Attribute | Description | Type | Options | Default | +| ------- | ------- | ------- | ------- | ------- | +| title | Title content | String | -- | -- | +| content | Popover content | string, Node, React.Component | -- | -- | +| placement | Popover position | string | top,right,bottom,left | top | +| trigger | Popover trigger mode| string | click, focus, hover | click | diff --git a/docs/en-US/quick-start.md b/docs/en-US/quick-start.md index a59f02a76..ab35fe068 100644 --- a/docs/en-US/quick-start.md +++ b/docs/en-US/quick-start.md @@ -12,7 +12,7 @@ HIUI is committed to providing programmers with a more concise development exper **We are still in procesing so HIUI have not put in npm, gitlab repository is required to be installed.** ```sh -$ npm install hiui +$ npm install @hi-ui/hiui --save ``` ### 2.use component diff --git a/docs/en-US/radio.md b/docs/en-US/radio.md new file mode 100644 index 000000000..df1a5df91 --- /dev/null +++ b/docs/en-US/radio.md @@ -0,0 +1,143 @@ +## Radio + +### Basic + +:::demo + + +```js +constructor () { + super() + this.state = { + play : [{ + name: 'Phone', + id: 101 + }, { + name: 'TV', + id: 102 + }], + people: [{ + name: 'Jack', + id: 1, + checked: true + }, { + name: 'Rose', + id: 2 + }, { + name: 'Jhon', + id: 3, + checked: true + }, { + name: 'Smith', + id: 4 + }], + address: [{ + id: 1001, + name: 'China' + }, { + id: 1002, + name: 'India' + }, { + id: 1003, + name: 'Italy' + }] + } +} +render() { + return ( +
    +

    Simple data (selected by default for data index setting)

    + { + console.log(data) + }} + /> +

    Complex data structure (selected by default for data indexing)

    + { + console.log(data) + }} + checked={1} + disabled={1} + /> +

    Complex data structure (selected by list item setting)

    + { + console.log(data) + }} + disabled={(item) => item.id === 1 || item.id === 3} + /> +

    Complex data structure (determined by function)

    + { + console.log(data) + }} + checked={(item) => item.id === 1002} + /> +
    + ) +} +``` +::: + +### Button Mode + +:::demo + +```js +constructor () { + super() + this.state = { + disableNum : 2 + } +} +render() { + return ( +
    +

    Vertical

    + +
    +

    Button Mode

    + console.log(data)} + /> +
    +

    Vertical Button Mode

    + console.log(data)} + layout='vertical' + /> +
    + ) +} +``` +::: + +### Radio Attributes + +| Attribute | Description | Type | Options | Default | +| -------- | ----- | ---- | ---- | ---- | +| name | group name | string | - | Under normal circumstances, no need to pass, the component is generated by default. | +| list | datas | array | - | - | +| align | label align | string | left/right | right | +| checked | When applied to a data item in the list, it is a Boolean value indicating whether the item is selected. When multiple items in the list contain this attribute, the last item will be the main one---
    When it is applied to a component attribute as a number or a function is a number, it represents the index value of the selected item. When starting from 0, the function returns the current item and returns the Boolean value after comparison. Whether the item is selected | bool/number/func | - | -1 | +| onChange | Callback | function | - | - | +| disabled | Whether to disable | number/function | - | - | +| mode | style | string | normal/button | normal | +| layout | layout | string | horizontal/vertical | horizontal | \ No newline at end of file diff --git a/docs/en-US/select.md b/docs/en-US/select.md index 94a0ed187..2d791ecbf 100644 --- a/docs/en-US/select.md +++ b/docs/en-US/select.md @@ -1,4 +1,4 @@ -## Select 下拉框 +## Select ### Single selection @@ -12,11 +12,11 @@ constructor () { super() this.state = { singleList: [ - { name:'手机', id:'2' }, - { name:'电视', id:'3', disabled: true }, - { name:'笔记本', id:'4', disabled: true }, - { name:'生活周边', id:'5' }, - { name:'办公', id:'6' }, + { name:'Phone', id:'2' }, + { name:'TV', id:'3', disabled: true }, + { name:'Laptop', id:'4', disabled: true }, + { name:'Daily necessities', id:'5' }, + { name:'Office', id:'6' }, ], tmp: [ {name: 'json', id: '1'}, @@ -31,11 +31,11 @@ render () { { - console.log('单选结果', item) + console.log('Result', item) }} disabled /> @@ -101,11 +101,11 @@ constructor () { super() this.state = { singleList: [ - { name:'较长的一段描述文本', label: '这是一段较长的描述文本', id:'2' }, - { name:'手机', label: 'tanke', id:'3' }, - { name:'笔记本', label: 'chaojitanke', id:'4', disabled: true }, - { name:'生活周边', label: 'wurenji', id:'5' }, - { name:'生态链', label: 'huojian', id:'6' }, + { name:'Longer description text', label: 'Longer description text', id:'2' }, + { name:'Phone', label: 'tanke', id:'3' }, + { name:'Laptop', label: 'chaojitanke', id:'4', disabled: true }, + { name:'Daily necessities', label: 'wurenji', id:'5' }, + { name:'Office', label: 'huojian', id:'6' }, ] } } @@ -116,11 +116,11 @@ render () { { - console.log('异步多选结果', selectList) - }} - /> - - ) -} -``` -::: - ### Attributes diff --git a/docs/en-US/stepper.md b/docs/en-US/stepper.md index 081c5f159..e381e9ae3 100644 --- a/docs/en-US/stepper.md +++ b/docs/en-US/stepper.md @@ -10,13 +10,13 @@ The basic usage of stepper is left and right structure, just pass in the step in render() { const list = [ { - title: '账号信息', + title: 'Account information', }, { - title: '邮箱激活', + title: 'Mailbox activation', }, { - title: '信息登记', + title: 'Information registration', }, ] @@ -43,15 +43,15 @@ Stepper icon usage render() { const list = [ { - title: '账号信息', + title: 'Account information', icon: , }, { - title: '邮箱激活', + title: 'Mailbox activation', icon: }, { - title: '信息登记', + title: 'Information registration', icon: }, ] @@ -79,16 +79,16 @@ The upper and lower structures only need to add `up=true`; only the upper and lo render() { const list = [ { - title: '账号信息', - text: '请输入账号信息', + title: 'Account information', + text: 'Please Input Account information', }, { - title: '邮箱激活', - text: '请输入邮箱', + title: 'Mailbox activation', + text: 'Please Input Emial', }, { - title: '信息登记', - text: '请输入个人信息', + title: 'Information registration', + text: 'Please Input Personal information', }, ] @@ -116,18 +116,18 @@ The icon usage of the upper and lower structure needs to add `up=true` and add t render() { const list = [ { - title: '账号信息', - text: '请输入账号信息', + title: 'Account information', + text: 'Please Input Account information', icon: }, { - title: '邮箱激活', - text: '请输入邮箱', + title: 'Mailbox activation', + text: 'Please Input Emial', icon: }, { - title: '信息登记', - text: '请输入个人信息', + title: 'Information registration', + text: 'Please Input Personal information', icon: }, ] @@ -157,16 +157,16 @@ render() { render() { const list = [ { - title: '账号信息', - text: '请输入账号信息', + title: 'Account information', + text: 'Please Input Account information', }, { - title: '邮箱激活', - text: '请输入邮箱', + title: 'Mailbox activation', + text: 'Please Input Emial', }, { - title: '信息登记', - text: '请输入个人信息', + title: 'Information registration', + text: 'Please Input Personal information', }, ] @@ -196,18 +196,18 @@ Need to pass in attribute `vertical = true` render() { const list = [ { - title: '账号信息', - text: '请输入账号信息', + title: 'Account information', + text: 'Please Input Account information', icon: , }, { - title: '邮箱激活', - text: '请输入邮箱', + title: 'Mailbox activation', + text: 'Please Input Emial', icon: , }, { - title: '信息登记', - text: '请输入个人信息', + title: 'Information registration', + text: 'Please Input Personal information', icon: , }, ] diff --git a/docs/en-US/table.md b/docs/en-US/table.md index 4aa027f27..3ed4c0ea2 100644 --- a/docs/en-US/table.md +++ b/docs/en-US/table.md @@ -14,7 +14,7 @@ no matter data item or column item need to add key , most great ### basic - +:::demo ```js constructor(props){ super(props) @@ -56,11 +56,11 @@ render() { return
    } ``` - +::: ### sort - +:::demo ```js constructor(props){ super(props) @@ -111,11 +111,11 @@ render() { return
    } ``` - +::: ### select - +:::demo ```js @@ -184,14 +184,14 @@ render() { return
    } ``` - +::: ### Table header Top suction fixTop,this attribute represents the height of the header to the window - +:::demo ```js constructor(props){ super(props) @@ -233,9 +233,10 @@ render() { return
    } ``` - +::: ### Column freeze +:::demo Columns that freeze will have to pass the width attribute, otherwise the form may be inconsistent. @@ -273,13 +274,13 @@ render() { } ``` - +::: ### Right-click to freeze - +:::demo When you need to use the right-click to freeze, be sure to pass the scrollWidth property to indicate the scroll width of the frozen table, as well as the width of each column, otherwise the table will not be aligned ```js @@ -318,11 +319,11 @@ render() { return
    } ``` - +::: ### Merge Cell - +:::demo ```js constructor(props){ @@ -437,13 +438,13 @@ render() { return
    } ``` - +::: ### Header Group - +:::demo ```js constructor(props){ super(props) @@ -536,12 +537,12 @@ render() { return
    } ``` - +::: ### expand a row - +:::demo ```js constructor(props){ @@ -601,15 +602,14 @@ render() { return
    } ``` - +::: ### pagination Here are just a few properties. For details, see the detailed configuration of pagination components. ### 分页 -这里只演示了几个属性,详情请查看分页组件的详细配置 -:::demo Table 表格代码说明 +:::demo ```js diff --git a/docs/en-US/tree.md b/docs/en-US/tree.md index 5a418e508..a9ebce5e8 100644 --- a/docs/en-US/tree.md +++ b/docs/en-US/tree.md @@ -8,28 +8,28 @@ constructor(props) { super(props) this.treeData = [ - { id: 1, title: '小米', + { id: 1, title: 'Mi', children: [ - { id: 2, title: '技术', + { id: 2, title: 'Redmi Phones', children: [ - { id: 3, title: '后端', onClick: data => {console.log('后端:', data)} }, - { id: 4, title: '运维' }, - { id: 5, title: '前端' } + { id: 3, title: 'Redmi 6 Pro', onClick: data => {console.log('result', data)} }, + { id: 4, title: 'Redmi 6A' }, + { id: 5, title: 'Redmi Y2' } ] }, - { id: 6, title: '产品' } + { id: 6, title: 'Mi Action Camera 4k' } ] }, - { id: 11, title: '小米', + { id: 11, title: 'Mi TV', children: [ - { id: 22, title: 技术, + { id: 22, title: TV, children: [ - { id: 33, title: '后端' }, - { id: 44, title: '运维' }, - { id: 55, title: '前端' } + { id: 33, title: 'Mi LED TV 4 PRO 55' }, + { id: 44, title: 'Mi LED TV 4A PRO 49' }, + { id: 55, title: 'Mi LED Smart TV 4A 43' } ] }, - { id: 66, title: '产品' } + { id: 66, title: 'Other' } ] }, ] @@ -62,28 +62,28 @@ checkbox constructor(props) { super(props) this.treeData = [ - { id: 1, title: '小米', + { id: 1, title: 'Mi', children: [ - { id: 2, title: '技术', + { id: 2, title: 'Redmi Phones', children: [ - { id: 3, title: '后端' }, - { id: 4, title: '运维' }, - { id: 5, title: '前端' } + { id: 3, title: 'Redmi 6 Pro', onClick: data => {console.log('result', data)} }, + { id: 4, title: 'Redmi 6A' }, + { id: 5, title: 'Redmi Y2' } ] }, - { id: 6, title: '产品' } + { id: 6, title: 'Mi Action Camera 4k' } ] }, - { id: 11, title: '小米', + { id: 11, title: 'Mi TV', children: [ - { id: 22, title: '技术', + { id: 22, title: TV, children: [ - { id: 33, title: '后端' }, - { id: 44, title: '运维' }, - { id: 55, title: '前端' } + { id: 33, title: 'Mi LED TV 4 PRO 55' }, + { id: 44, title: 'Mi LED TV 4A PRO 49' }, + { id: 55, title: 'Mi LED Smart TV 4A 43' } ] }, - { id: 66, title: '产品' } + { id: 66, title: 'Other' } ] }, ] diff --git a/docs/en-US/typography.md b/docs/en-US/typography.md new file mode 100644 index 000000000..8c16f1a09 --- /dev/null +++ b/docs/en-US/typography.md @@ -0,0 +1,85 @@ +# Typography + +Article layout + +## Title + +:::demo + +```run +render() { + return ( +
    +

    H1

    +

    H2

    +

    H3

    +

    H4

    +
    H5
    +
    H6
    +
    + ) +} +``` +::: + +## Paragraph + +[Mi](#)ALWAYS BELIEVE +THAT SOMETHING WONDERFUL +IS ABOUT TO HAPPEN + +> The "MI" in our logo stands for “Mobile Internet”. It also has other meanings, including "Mission Impossible", because Xiaomi faced many challenges that +> had seemed impossible to defy in our early days. +> +> The Name + + "Just for fans" – that's our belief. Our hardcore Mi fans lead every step of the way. In fact, many +Xiaomi employees were first Mi fans before joining the team. As a team, we share the same relentless +pursuit of perfection, constantly refining and enhancing our products to create the best user experience +possible. We are also fearless in testing new ideas and pushing our own boundaries. Our dedication +and belief in innovation, together with the support of Mi fans, are the driving forces behind our +unique Mi products. + +## List + +- Mi Sphere Camera Kit +- Redmi Phones + 1. Redmi 6 Pro + 1. Redmi 6A + 1. Redmi Y2 +- Mi TV + - Mi LED TV 4 PRO 55 + - Mi LED TV 4A PRO 49 + - Mi LED TV 4C PRO 32 + - Mi LED Smart TV 4A 43 +- Mi Action Camera 4k + + +1. China +1. Southeast Asia + 1. India + 1. Indonesia + 1. Thailand + 1. Korea +1. Europe + - Italy + - France + - Russia + - Spain +1. United States +1. Arab + +
    +
    Attribute A
    +
    Data A
    +
    Attribute B
    +
    Data B
    +
    Attribute C
    +
    Data C
    +
    + +
    + +## Other + +Use command + option + i to open the "Developer Tools" to view the corresponding code. diff --git a/docs/zh-CN/cascader.md b/docs/zh-CN/cascader.md new file mode 100644 index 000000000..d7fe8c165 --- /dev/null +++ b/docs/zh-CN/cascader.md @@ -0,0 +1,958 @@ +## Cascader 级联选择 + +### 基础用法 + +:::demo + +基础用法 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + +### 禁用 + +:::demo + +禁用 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + disabled={true} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + +### 禁用选项 + +:::demo + +禁用选项 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3', + disabled: true + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + disabled: true, + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + +### 选择即改变 + +:::demo + +选择即改变 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + changeOnSelect={true} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + +### 不可清空 + +:::demo + +不可清空 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + clearable={false} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + + +### 自定义字段名 + +:::demo + +自定义字段名 + +```js + constructor () { + super() + this.state = { + options: [ + { + goodsId: '手机', + goodsName: '手机', + subGoods: [ + { + goodsId: '小米', + goodsName: '小米', + subGoods: [ + { + goodsId: '小米3', + goodsName: '小米3' + }, + { + goodsId: '小米4', + goodsName: '小米4' + }, + ] + }, + { + goodsId: '红米', + goodsName: '红米', + subGoods: [ + { + goodsId: '红米3', + goodsName: '红米3' + }, + { + goodsId: '红米4', + goodsName: '红米4' + } + ] + } + ] + }, + { + goodsId: '电视', + goodsName: '电视', + subGoods: [ + { + goodsId: '小米电视4A', + goodsName: '小米电视4A' + }, + { + goodsId: '小米电视4C', + goodsName: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + fieldNames={{ + label: 'goodsName', + value: 'goodsId', + children: 'subGoods', + }} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + +### 默认值 + +:::demo + +默认值 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + +### 自定义显示 + +:::demo + +自定义显示 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + options={this.state.options} + style={{width: '220px'}} + displayRender={values => { + return values.join(' > ') + }} + /> +
    + ) + } + +``` +::: + + + +### 搜索 + +:::demo + +搜索 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米1', + label: '小米1' + }, + { + value: '小米2', + label: '小米2', + disabled: true + }, + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + { + value: '小米5', + label: '小米5' + }, + { + value: '小米6', + label: '小米6' + }, + { + value: '小米7', + label: '小米7' + }, + { + value: '小米8', + label: '小米8' + } + ] + }, + { + value: '红米', + label: '红米', + disabled: true, + children: [ + { + value: '红米1', + label: '红米1' + }, + { + value: '红米2', + label: '红米2' + }, + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A 55寸 1GB+4GB大内存 64位四核处理器' + }, + { + value: '小米电视4C', + label: '小米电视4C' + }, + { + value: '小米电视4X', + label: '小米电视4X' + }, + { + value: '小米电视4', + label: '小米电视4' + } + ] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + noFoundTip="未搜索到相关内容" + searchable={true} + options={this.state.options} + style={{width: '220px'}} + /> +
    + ) + } + +``` +::: + + + + +### 动态加载选项 + +:::demo + +动态加载选项 + +```js + constructor () { + super() + this.state = { + options: [ + { + value: '手机', + label: '手机', + children: [ + { + value: '小米', + label: '小米', + children: [ + { + value: '小米1', + label: '小米1' + }, + { + value: '小米2', + label: '小米2', + disabled: true + }, + { + value: '小米3', + label: '小米3' + }, + { + value: '小米4', + label: '小米4' + }, + { + value: '小米5', + label: '小米5' + }, + { + value: '小米6', + label: '小米6' + }, + { + value: '小米7', + label: '小米7' + }, + { + value: '小米8', + label: '小米8' + } + ] + }, + { + value: '红米', + label: '红米', + children: [ + { + value: '红米1', + label: '红米1' + }, + { + value: '红米2', + label: '红米2' + }, + { + value: '红米3', + label: '红米3' + }, + { + value: '红米4', + label: '红米4' + } + ] + } + ] + }, + { + value: '电视', + label: '电视', + children: [ + { + value: '小米电视4A', + label: '小米电视4A' + }, + { + value: '小米电视4C', + label: '小米电视4C' + }, + { + value: '小米电视4X', + label: '小米电视4X' + }, + { + value: '小米电视4', + label: '小米电视4' + } + ] + }, + { + value: 'mix', + label: 'Mix', + children: [] + } + ] + } + } + render(){ + return( +
    + { + console.log('on change', value) + }} + options={this.state.options} + style={{width: '220px'}} + onActiveItemChange={values=>{ + if(values[0] == 'mix') { + setTimeout(()=>{ + this.state.options[2].children = [ + { + value: 'mix1', + label: 'Mix1' + },{ + value: 'mix2', + label: 'Mix2' + },{ + value: 'mix3', + label: 'Mix3' + } + ] + this.forceUpdate() + }, 1000) + } + }} + /> +
    + ) + } + +``` +::: + + + +### Cascader Attributes + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| -------- | ----- | ---- | ---- | ---- | +| options | 可选项数据源 | array | - | - | +| value | 默认值 | array | - | [] | +| fieldNames | 自定义options中label,value,children的字段 | object | - | {label:'label', value:'value', children:'children'} | +| searchable | 是否可搜索 | bool | true, false | false | +| clearable | 是否可清空 | bool | true, false | true | +| disabled | 是否禁止使用 | bool | true, false | false | +| changeOnSelect | 是否启用选择即改变功能 | bool | true, false | false | +| placeholder | placeholder | string | - | 请选择 | +| noFoundTip | 未搜索到的提示 | string | - | 无匹配数据 | +| className | 自定义class | string | - | - | +| style | 自定义样式 | object | - | - | +| displayRender | 自定义选中的标签展示 | function | - | - | + +### Cascader Events + +| 参数 | 说明 | 回调参数 | +| -------- | ----- | ---- | +| onChange | 选择完成后回调 | 选中的值 | +| onActiveItemChange | 父级选项变化时的回调 | 选中的值 | diff --git a/docs/zh-CN/checkbox.md b/docs/zh-CN/checkbox.md index 7ed892b48..64f574356 100644 --- a/docs/zh-CN/checkbox.md +++ b/docs/zh-CN/checkbox.md @@ -140,6 +140,6 @@ render() { | name | 全选或多选模式下子选项标识(用于全选或多选模式,且 name 值与 all 值保持一致,当没有全选框时,同级选项 name 应保持一致)) | string | - | | ### Checkbox Events -| 参数 | 说明 | 类型 | 说明 | -| -------- | ----- | ---- | ---- | -| onChange | 选择回调函数 | function | 当单个选择框时,返回点击的 value 及是否被选择
    当多选时,返回被选中的数组 | +| 参数 | 说明 | 类型 | +| -------- | ----- | ---- | +| onChange | 选择回调函数 | function | 当单个选择框时,返回点击的 value 及是否被选择
    当多选时,返回被选中的数组 diff --git a/docs/zh-CN/date-picker.md b/docs/zh-CN/date-picker.md index 19fd24c62..38087dc9d 100644 --- a/docs/zh-CN/date-picker.md +++ b/docs/zh-CN/date-picker.md @@ -19,12 +19,50 @@ constructor() { render () { return (
    + { - console.log('含有默认值是,会触发一次', DatePicker.format(d, 'yyyy-MM-dd E')) + console.log('value 为 Date 实例', DatePicker.format(d, 'YYYY-MM-DD E')) }} /> + { + console.log(' value 为 Number(毫秒数)', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + { + console.log('value 为 时间字符串', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + { + console.log('没有 value 属性', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + { + console.log('value 为 Null', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + { + console.log('value 为 undefined', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + { + console.log('value 为 空字符串', DatePicker.format(d, 'YYYY-MM-DD E')) + }} + /> + {this.setState({date: new Date()})}}>重置
    ) @@ -43,7 +81,6 @@ render () { render () { return ( ) @@ -63,10 +100,7 @@ render () { return ( { - console.log(d) - }} + maxDate={new Date(2019, 4, 28)} /> ) } @@ -86,7 +120,7 @@ render () { { - console.log(d) + console.log('周选择', d) }} /> ) @@ -150,9 +184,11 @@ render () {
    { - console.log(d) + console.log(1, d) }} /> {this.setState({rangeDate: ''})}}>重置 @@ -175,7 +211,7 @@ render () { ) } @@ -193,7 +229,7 @@ render () { render () { return ( { console.log(d) @@ -302,7 +338,7 @@ render () { { - console.log(DatePicker.format(d, 'yyyy-MM E')) + console.log(DatePicker.format(d, 'YYYY-MM E')) }} /> daterange 日期范围
    year 年份
    month 月份
    week 周
    weekrange 周范围 | date | -| value | 默认显示的日期 | Date/String/Object/Undefined | 可选值参见示例
    用于范围选择时,可传入单个 Date 对象或{start: Date, end: Date}
    可传入空字符串,效果与不传入一致 | null | -| minDate | 最小日期 | date | null | null | -| maxDate | 最大日期 | date | null | null | -| disabled | 是否禁用输入框 | boolean | true false | false | -| showTime | 是否在日期选择器中显示时间选择器 | boolean | true false | false | -| shortcuts | 快捷面板 | array | 近一周, 近一月, 近三月, 近一年 | null | -| weekOffset | 周起始
    默认周日做为第一列 | number | 0/1 | 0 | +| type | 选择器类型 | String | date 普通日期
    daterange 日期范围
    year 年份
    month 月份
    week 周
    weekrange 周范围 | date | +| value | 默认显示的日期 | Date/String/Number/Object/Undefined/Null | -- | null | +| minDate | 最小日期 | Date | null | null | +| maxDate | 最大日期 | Date | null | null | +| disabled | 是否禁用输入框 | Boolean | true false | false | +| showTime | 是否在日期选择器中显示时间选择器 | Boolean | true false | false | +| shortcuts | 快捷面板 | Array | 近一周, 近一月, 近三月, 近一年 | null | +| weekOffset | 周起始
    默认周日做为第一列 | Number | 0/1 | 0 | ### Datepicker Events @@ -348,16 +384,41 @@ render () { ### format -| 格式 | 说明/(长度) | 示例 | 结果 | -| :--: | :------------------------------: | ------------------- | ------------------- | -| y | 年/(1~4) | yyyy |2018| -| M | 月/(1~2) | yyyy-MM |2018-06| -| d | 日/(1~2) | yyyy-dd |2018-29| -| h | 12小时制/(1~2) | dd : hh |29:03| -| H | 24小时制/(1~2) | dd : HH |29:15| -| m | 分钟/(1~2) | dd hh-mm |29 15-30| -| s | 秒/(1~2) | yyyy-MM-dd hh:mm:ss |2018-06-29 03:30:00| -| S | 毫秒/(1) | MM-dd: HH:mm:ss:S |06-29: 15:30:00| -| E | 周/(1~3) 分别对应 一/周一/星期一 | yy-MM-dd EE |18-06-29 18| -| q | 季度/(1~2) | yyyy-MM q |2018-06 2| +| 单位 | 字符 | 示例 | +| ----------- | ---- | -------------------------------- | +| 月 | M | 1, 2, ..., 12 | +|   | Mo | 1st, 2nd, ..., 12th | +|   | MM | 01, 02, ..., 12 | +|   | MMM | Jan, Feb, ..., Dec | +|   | MMMM | January, February, ..., December | +| 季度 | Q | 1, 2, 3, 4 | +|   | Qo | 1st, 2nd, 3rd, 4th | +| 天/月 | D | 1, 2, ..., 31 | +|   | Do | 1st, 2nd, ..., 31st | +|   | DD | 01, 02, ..., 31 | +| 天/年 | DDD | 1, 2, ..., 366 | +|   | DDDo | 1st, 2nd, ..., 366th | +|   | DDDD | 001, 002, ..., 366 | +| 天/周 | d | 0, 1, ..., 6 | +|   | do | 0th, 1st, ..., 6th | +|   | dd | Su, Mo, ..., Sa | +|   | ddd | Sun, Mon, ..., Sat | +|   | dddd | Sunday, Monday, ..., Saturday | +| 年 | YY | 00, 01, ..., 99 | +|   | YYYY | 1900, 1901, ..., 2099 | +| 上午/下午 | A | AM, PM | +|   | a | am, pm | +|   | aa | a.m., p.m. | +| 小时 | H | 0, 1, ... 23 | +|   | HH | 00, 01, ... 23 | +|   | h | 1, 2, ..., 12 | +|   | hh | 01, 02, ..., 12 | +| 分钟 | m | 0, 1, ..., 59 | +|   | mm | 00, 01, ..., 59 | +| 秒 | s | 0, 1, ..., 59 | +|   | ss | 00, 01, ..., 59 | +| 秒(1/10) | S | 0, 1, ..., 9 | +| 秒(1/100) | SS | 00, 01, ..., 99 | +| 毫秒 | SSS | 000, 001, ..., 999 | +| 毫秒时间戳 | x | 512969520900 | diff --git a/docs/zh-CN/input.md b/docs/zh-CN/input.md index 4e6668180..b04a793f3 100644 --- a/docs/zh-CN/input.md +++ b/docs/zh-CN/input.md @@ -245,11 +245,11 @@ render() { | 参数 | 说明 | 类型 | 可选值 | 默认值 | | -------- | ----- | ---- | ---- | ---- | -| type | 设置按钮类型 | string | text, textarea, id, tel, card, amount, email | text | -| disabled | 输入框尾部文字 | boolean | true/false | false | -| required | 输入框尾部文字 | string | true/false | false | -| prefix | 输入框头部文字 | string | - | - | -| suffix | 输入框尾部文字 | string | - | - | +| type | 设置输入框类型 | string | text, textarea, id, tel, card, amount, email | text | +| disabled | 是否禁用 | boolean | true/false | false | +| required | 是否必填 | string | true/false | false | +| prefix | 前缀 | string | - | - | +| suffix | 后缀 | string | - | - | ### Input Events diff --git a/docs/zh-CN/progress.md b/docs/zh-CN/progress.md new file mode 100644 index 000000000..1edaa2fd0 --- /dev/null +++ b/docs/zh-CN/progress.md @@ -0,0 +1,158 @@ +## Progress进度条 + +### 进度条类型 + +:::demo + +Progress组件 + +```js +render() { + return ( +
    + +
    + +
    + +
    + +
    + ) +} +``` +::: + +### 进度条动态 + +:::demo + +Progress动态 + +```js +constructor () { + super() + this.state = { + percent: 10 + } +} + +render() { + return ( +
    + +
    + this.setState({percent})} + /> +
    + ) +} +``` +::: + +### 环形进度条 + +:::demo + +环形进度条 + +```js +constructor () { + super() + this.state = { + percent: 10 + } +} + +render() { + return ( +
    +
    + +
    +
    + }/> +
    +
    + }/> +
    +
    + }/> +
    +
    + }/> +
    +
    + this.setState({percent})} + /> +
    + ) +} +``` +::: + +### 仪表盘进度条 + +:::demo + +环形进度条 + +```js +constructor () { + super() + this.state = { + percent: 10 + } +} + +render() { + return ( +
    +
    + +
    +
    + this.setState({percent})} + /> +
    + ) +} +``` +::: + + +### 进度条文字内显 + +:::demo + +Progress组件 + +```js +render() { + return ( +
    + +
    + +
    + +
    + ) +} +``` +::: \ No newline at end of file diff --git a/docs/zh-CN/quick-start.md b/docs/zh-CN/quick-start.md index 990aeccb5..7ea86823a 100644 --- a/docs/zh-CN/quick-start.md +++ b/docs/zh-CN/quick-start.md @@ -14,7 +14,7 @@ HIUI 是一套适用于前中后台的交互界面设计标准与前端解决方 ### 1. 将HIUI添加到项目中 ```sh -$ npm install hiui +$ npm install @hi-ui/hiui --save ``` ### 2. 使用组件 diff --git a/docs/zh-CN/select.md b/docs/zh-CN/select.md index 82a28e3c4..08e54cfbf 100644 --- a/docs/zh-CN/select.md +++ b/docs/zh-CN/select.md @@ -31,7 +31,7 @@ render () { list={this.state.singleList} placeholder='请选择品类' style={{width: '200px'}} - value={'3'} + value='3' onChange={(item) => { console.log('单选结果', item) }} @@ -154,6 +154,7 @@ render () { return JSON.parse(body).data } }} + list={[]} placeholder='请选择种类' style={{width: '200px'}} onChange={(item) => { @@ -198,7 +199,7 @@ render () { mode='multiple' style={{width: '300px'}} list={this.state.multipleList} - value='4,5' + value={['4', '5']} searchable={true} placeholder='请选择...' onChange={(item) => { @@ -234,6 +235,7 @@ render () { return JSON.parse(body).data } }} + list={[]} placeholder='请选择...' onChange={(item) => { console.log('异步多选结果', item) @@ -253,7 +255,7 @@ render () { | mode | 下拉框类型 | string | single, multiple | single | | list | 下拉框选项,一般为 {name: '', id: ''} 形式。可以加入 'disabled' 属性,表示是否禁止选择 | array | - | - | | origin | 异步选择配置,有 type / url / func 三种属性,分别代表请求类型/请求路径/请求返回后的数据处理函数 | object | - | - | -| value | 默认值被选中项,值与被选中的id相同,多个以,分割| string | - | - | +| value | 默认值被选中项,值与被选中的id相同,多个以,分割或者传递数组| string|number|array | - | - | | searchable | 是否可以筛选 | bool | true, false | false | | autoload | origin从远端获取数据,初始时是否自动加载 | bool | true, false | false | | disabled | 禁用该下拉框 | bool | true, false | false | diff --git a/docs/zh-CN/tree.md b/docs/zh-CN/tree.md index 5a3138b16..5876ef312 100644 --- a/docs/zh-CN/tree.md +++ b/docs/zh-CN/tree.md @@ -63,6 +63,7 @@ render() { onChange={data => {console.log('Tree data:', data)}} openIcon='down' closeIcon='up' + onNodeClick={(item) => console.log('------click node', item)} />
    @@ -146,6 +147,7 @@ render() { | ------- | ------- | ------- | ------- | ------- | | expand | 默认是否展开子菜单(优先级高于defaultExpandAll) | blooean | true, false | false | | onClick | 点击每项时触发的事件 | Func() | - | - | +| onNodeClick | 点击每项时触发,onClick作用具体绑定的项,onNodeClick作用于所以项 | Func() | - | - | | style | 单个节点样式 | object | - | - | ### Tree Attributes-options @@ -161,10 +163,5 @@ render() { | -------- | ----- | ---- | | onChange | 改变复选框状态时触发 | (data: Object) | | onNodeToggle | 节点被点击(展开/收起)时触发 | (data: Obejct, isExpanded: boolean) | - + diff --git a/gulpfile.js b/gulpfile.js index 55031b85d..fdc771984 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -14,11 +14,12 @@ const esDir = path.join(cwd, 'es') const compile = modules => { rimraf.sync(modules !== false ? libDir : esDir) const sass = gulp - .src(['components/**/*.scss']) + .src(['components/**/*.scss', '!components/**/_*.scss']) .pipe( through2.obj(function (file, encoding, next) { - this.push(file.clone()) - if (file.path.match(/\/style\/index\.scss$/)) { + // this.push(file.clone()) + + if (file.path.match(/\/style\/.*\.scss$/)) { transformSass(file.path) .then(css => { file.contents = Buffer.from(css) @@ -47,7 +48,7 @@ const compile = modules => { 'env', { targets: { - browsers: ['ie >= 6'] + browsers: ['ie > 8'] }, loose: true, modules: modules, @@ -60,6 +61,17 @@ const compile = modules => { plugins: [['transform-remove-console', { exclude: ['error', 'warn'] }]] }) ) + .pipe(through2.obj(function (file, encoding, next) { + if (file.path.match(/\/style\/.*\.js$/)) { + const cssContent = file.contents.toString().replace(/\.scss/g, '.css') + file.contents = Buffer.from(cssContent) + this.push(file) + next() + } else { + this.push(file) + next() + } + })) .pipe(gulp.dest(modules === false ? esDir : libDir)) return merge2([sass, assets, js]) } diff --git a/libs/markdown/index.js b/libs/markdown/index.js index bbe1c4163..b0db61fd0 100644 --- a/libs/markdown/index.js +++ b/libs/markdown/index.js @@ -36,7 +36,6 @@ class Markdown extends Component { render () { let document = this.document(localStorage.getItem('HIUI_LANGUAGE') || 'zh-CN') - if (typeof document === 'string') { this.components.clear() diff --git a/libs/markdown/parse2demo.js b/libs/markdown/parse2demo.js index f4e4511de..84de0ab63 100644 --- a/libs/markdown/parse2demo.js +++ b/libs/markdown/parse2demo.js @@ -5,6 +5,10 @@ import marked from 'marked' import { transform } from 'babel-standalone' import Prism from 'prismjs' +const LANG = { + 'zh-CN': ['显示代码', '收起代码', '复制代码'], + 'en-US': ['Show Code', 'Hide Code', 'Copy Code'] +} class Demo extends Component { constructor (props) { super(props) @@ -95,7 +99,11 @@ class Demo extends Component { render () { const showCode = this.state.showCode - + const locale = this.props.locale + let ls = LANG[locale] + if (!ls) { + ls = LANG['zh-CN'] + } return (
    @@ -135,7 +143,7 @@ class Demo extends Component { document.execCommand('Copy', 'false', null) }} > - 复制代码 + {ls[2]}
    @@ -183,7 +191,7 @@ class Demo extends Component {
    - {showCode ? '收起代码' : '显示代码'} + {showCode ? ls[1] : ls[0]}
    diff --git a/locales/en-US.js b/locales/en-US.js index 4780a5cac..2b31c8479 100644 --- a/locales/en-US.js +++ b/locales/en-US.js @@ -10,7 +10,9 @@ module.exports = { components: 'Basic Components' }, pagination: { - total: total => `Total ${total} items`, + total: function (total) { + return 'Total ' + total + ' items' + }, item: 'items', goto: 'Goto' }, diff --git a/locales/zh-CN.js b/locales/zh-CN.js index 3f4f0c250..b50258e3c 100644 --- a/locales/zh-CN.js +++ b/locales/zh-CN.js @@ -15,7 +15,9 @@ module.exports = { week: [ '日', '一', '二', '三', '四', '五', '六' ] }, pagination: { - total: total => `共${total}条`, + total: function (total) { + return '共 ' + total + ' 条' + }, item: '条', goto: '前往' }, diff --git a/package.json b/package.json index 71b11ee35..1d786c302 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hi-ui/hiui", - "version": "1.0.2", + "version": "1.0.3", "description": "HIUI for React", "scripts": { "test": "node_modules/.bin/standard", @@ -38,6 +38,7 @@ "axios": "^0.18.0", "classnames": "^2.2.5", "component-classes": "^1.2.6", + "date-fns": "^1.29.0", "hoist-non-react-statics": "^2.5.0", "lodash": "^4.17.10", "mini-store": "^1.1.0", @@ -73,6 +74,7 @@ "cross-env": "^5.1.6", "css-loader": "^0.28.11", "cssnano": "^4.0.5", + "date-fns": "^1.29.0", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.11", "gh-pages": "^2.0.1", diff --git a/site/App.js b/site/App.js deleted file mode 100644 index b9f74ea79..000000000 --- a/site/App.js +++ /dev/null @@ -1,351 +0,0 @@ -/* global localStorage, location */ -import React, { Component } from 'react' -import './styles/page/index.scss' - -import locales from './locales' -import pages from './pages' -import Dropdown from '../components/dropdown' - -const req = require.context('../components', true, /^\.\/[^_][\w-]+\/style\/index\.js?$/) - -req.keys().forEach((mod) => { - let v = req(mod) - if (v && v.default) { - v = v.default - } -}) - -class App extends Component { - constructor (props) { - super(props) - - this.state = { - anchors: [], - footNavs: [], - pre: '', - next: '', - theme: 'hiui-blue', - locale: 'zh-CN', - themes: [ - { - title: '默认', - value: 'default', - prefix: - }, - { - title: '经典', - value: 'classics', - prefix: - } - ], - locales: [ - { - title: '中文', - value: 'zh-CN' - }, - { - title: 'English', - value: 'en-US' - } - ] - } - } - - static markdown - - componentWillMount () { - this.setPage(() => { - window.addEventListener( - 'hashchange', - () => { - window.scrollTo(0, 0) - this.setPage() - this.getAnchors() - this.getSiblingNav() - }, - false - ) - - this.traverse(() => { - this.getSiblingNav() - }) - }) - } - - componentDidMount () { - this.getAnchors() - - if (!this.state.locale) { - this.setLocale(localStorage.getItem('HIUI_LANGUAGE') || 'zh-CN') - } - this.setTheme(localStorage.getItem('HIUI_THEME') || 'hiui-blue') - } - // 切换中英文文档 - // componentDidUpdate(props, state) { - // if (state.locale != this.state.locale) { - // switch(this.state.locale) { - // case 'en-US': - // i18n.use(en); break; - // default: - // i18n.use(zh); break; - // } - // } - // } - setLocale (locale) { - window.location.hash = `/${locale}/${this.state.page}` - } - setTheme (theme) { - this.setState({theme}, () => { - localStorage.setItem('HIUI_THEME', this.state.theme) - }) - } - - getLocale (key) { - const map = locales['zh-CN'] || {} - - return key.split('.').reduce((a, b) => { - const parent = map[a] - if (b) { - return (parent || {})[b] - } - - return parent - }) - } - - getPage () { - const routes = location.hash.match(/(?:\/(.+))?\/(.+)/) - - if (routes) { - if (locales.hasOwnProperty(routes[1])) { - this.setState({ locale: routes[1] }, () => { - localStorage.setItem('HIUI_LANGUAGE', this.state.locale) - }) - } - - return routes[2] - } else { - return 'quick-start' - } - // return default //打开默认页面 - } - - setPage (fn) { - this.setState({ page: this.getPage() }, fn) - } - - getComponent (page) { - const { theme, locale } = this.state - this.components = - this.components || - Object.assign( - Object.values(pages.components).reduce((a, b) => { - return Object.assign(a, b) - }, {}), - pages.documents - ) - // 控制markdown显示隐藏 - const currentPage = this.components[page] - if (currentPage) { - return React.createElement(currentPage.default, { theme, locale }) - } - } - - getAnchors () { - const anchorsDOM = document.getElementById('markdown-content').getElementsByTagName('h3') - const anchorsDOMList = [].slice.call(anchorsDOM) - - const anchors = anchorsDOMList.map((v, i) => { - const id = 'component-anchors-' + i - anchorsDOM[i].id = id - - return {id, text: anchorsDOM[i].innerHTML} - }) - - this.setState({anchors}) - } - - getSiblingNav () { - const footNavs = this.state.footNavs - const index = footNavs.indexOf(this.state.page) - const pre = footNavs[index - 1] ? footNavs[index - 1] : '' - const next = footNavs[index + 1] ? footNavs[index + 1] : '' - - this.setState({pre, next}) - } - - // 收集所有导航 - traverse (fn) { - const components = Object.keys(pages.components).map(group => { - return Object.keys(pages.components[group]).map(page => page) - }) - - const documents = Object.keys(pages.documents).map(page => page) - - const footNavs = [].concat(...documents, ...components) - - this.setState({footNavs}, fn) - } - - render () { - const { anchors, pre, next } = this.state - - return ( -
    -
    -
    -
    - HIUI DESIGN -
    -
    - this.setTheme(val)} /> - this.setLocale(val)} /> -
    -
    -
    -
    - -
    -
    -
    { this.markdown = arg }} - > - {this.getComponent(this.state.page)} -
    - - -
    - - - -
    - {/* */} -
    - ) - } -} - -export default App diff --git a/site/locales/zh-CN.js b/site/locales/zh-CN.js index addf746b6..ed2026087 100755 --- a/site/locales/zh-CN.js +++ b/site/locales/zh-CN.js @@ -29,12 +29,14 @@ module.exports = { 'navMenu': 'NavMenu 导航菜单', 'menu': 'Menu 菜单', 'select': 'Select 选择器', + 'cascader': 'Cascader 级联选择', 'radio': 'Radio 单选按钮', 'checkbox': 'Checkbox 复选按钮', 'grid': 'Grid 栅格', 'stepper': 'Stepper 步骤', 'ficon': 'Ficon', - 'icon': 'Icon 图标' + 'icon': 'Icon 图标', + 'progress': 'Progress 进度条' }, misc: { 'components': '组件', diff --git a/site/pages/cascader/index.js b/site/pages/cascader/index.js new file mode 100644 index 000000000..4c172f872 --- /dev/null +++ b/site/pages/cascader/index.js @@ -0,0 +1,9 @@ +import Markdown from '../../../libs/markdown' + +class Cascader extends Markdown { + document (locale) { + return require(`../../../docs/${locale}/cascader.md`) + } +} + +export default Cascader diff --git a/site/pages/index.js b/site/pages/index.js index a43f3bc41..214a7b7d6 100755 --- a/site/pages/index.js +++ b/site/pages/index.js @@ -24,6 +24,7 @@ export default { 'input': require('./input'), 'counter': require('./counter'), 'select': require('./select'), + 'cascader': require('./cascader'), 'radio': require('./radio'), 'checkbox': require('./checkbox'), 'date-picker': require('./date-picker'), @@ -37,7 +38,8 @@ export default { 'panel': require('./panel'), 'collapse': require('./collapse'), 'tooltip': require('./tooltip'), - 'popover': require('./popover') + 'popover': require('./popover'), + 'progress': require('./progress') }, '通知/提示': { 'modal': require('./modal'), diff --git a/site/pages/progress/index.js b/site/pages/progress/index.js new file mode 100644 index 000000000..d9c44cb4c --- /dev/null +++ b/site/pages/progress/index.js @@ -0,0 +1,9 @@ +import Markdown from '../../../libs/markdown' + +class progress extends Markdown { + document (locale) { + return require(`../../../docs/${locale}/progress.md`) + } +} + +export default progress diff --git a/site/view/Component/Dropdown/ThemeDropdown.js b/site/view/Component/Dropdown/ThemeDropdown.js index 45492078b..fb2bf68b1 100644 --- a/site/view/Component/Dropdown/ThemeDropdown.js +++ b/site/view/Component/Dropdown/ThemeDropdown.js @@ -3,7 +3,10 @@ import { connect } from 'react-redux' import { setTheme } from '../../../redux/action/global' import classnames from 'classnames' import './style/index.scss' - +const LANG = { + 'zh-CN': '主题', + 'en-US': 'Theme' +} class ThemeDropdown extends React.Component { constructor (props) { super(props) @@ -39,7 +42,7 @@ class ThemeDropdown extends React.Component { onMouseLeave={this.toggleDropdown.bind(this, false)} > - 主题 + {LANG[this.props.locale]}
      diff --git a/site/view/Component/Dropdown/style/index.scss b/site/view/Component/Dropdown/style/index.scss index f2572ac96..e5318cb44 100644 --- a/site/view/Component/Dropdown/style/index.scss +++ b/site/view/Component/Dropdown/style/index.scss @@ -4,12 +4,6 @@ align-items: center; } } -// 'hiui-blue': #4285f4, -// 'orange': #f63, -// 'cyan': #46bc99, -// 'blue': #3da8f5, -// 'purple': #8a8acb, -// 'green': #1da653 .colors { position: relative; } @@ -23,21 +17,6 @@ margin: 2px 0; } } -.hiui-blue { - background-color: map-get($palette-hiui, '50'); -} -.orange { - background-color: map-get($palette-orange, '50'); -} -.cyan { - background-color: map-get($palette-cyan, '50'); -} -.blue { - background-color: map-get($palette-blue, '50'); -} -.purple { - background-color: map-get($palette-purple, '50'); -} .hi-demo { &__dropdown { @@ -49,13 +28,17 @@ } } &__list { - font-size: 12px; position: absolute; - background: #fff; + right: 0; + z-index: 1; width: 100%; + margin: 0; padding: 10px 20px; border: 1px solid #e6e7e8; border-top: none; + list-style-type: none; + font-size: 12px; + background: #fff; &--hide { display: none; } diff --git a/site/view/Doc/Component/style/anchor.scss b/site/view/Doc/Component/style/anchor.scss index 918d70c18..06251364c 100644 --- a/site/view/Doc/Component/style/anchor.scss +++ b/site/view/Doc/Component/style/anchor.scss @@ -5,7 +5,11 @@ width: 124px; height: auto; border-left: 1px solid #F2F2F2; - + ul { + margin: 0; + padding: 0; + list-style-type: none; + } li { padding-left: 16px; margin-left: -1px; diff --git a/site/view/Doc/Component/style/index.scss b/site/view/Doc/Component/style/index.scss index af9a11d2f..bf6807c5c 100644 --- a/site/view/Doc/Component/style/index.scss +++ b/site/view/Doc/Component/style/index.scss @@ -7,6 +7,12 @@ .noaction { font-size: 12px; } + &-list { + padding: 0; + li { + list-style: none; + } + } .components-title { color: #999; } diff --git a/site/view/Doc/en-US.js b/site/view/Doc/en-US.js new file mode 100644 index 000000000..a6cc4c85a --- /dev/null +++ b/site/view/Doc/en-US.js @@ -0,0 +1,135 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { Link } from 'react-router-dom' +import locales from '../../locales' +import Dashboard, { Logo } from '@hi-ui/classic-theme' + +import logoImg from '../../static/img/logo.png' +import routes from './router' +import LocaleDropdown from '../Component/Dropdown/LocaleDropdown' +import ThemeDropdown from '../Component/Dropdown/ThemeDropdown' + +import './index.scss' + +// 引入组件样式 +const req = require.context('../../../components', true, /^\.\/[^_][\w-]+\/style\/index\.js?$/) +req.keys().forEach((mod) => { + let v = req(mod) + if (v && v.default) { + v = v.default + } +}) + +class Doc extends Component { + // constructor (props) { + // super(props) + + // // this.hashChangeEvent = this.hashChangeEvent.bind(this) + // } + + componentDidMount () { + + // window.addEventListener('hashchange', this.hashChangeEvent) + } + + componentWillUnmount () { + // window.removeEventListener('hashchange', this.hashChangeEvent) + } + + // hashChangeEvent () { + // let locale = window.location.hash.split('/')[1] + + // if (!locale) { return } + + // // 临时用于隐藏语言 + // if (locale !== 'zh-CN') { + // window.location.hash = window.location.hash.replace(locale, 'zh-CN') + // } + + // if (locale !== window.localStorage.getItem('HIUI_LANGUAGE')) { + // window.localStorage.setItem('HIUI_LANGUAGE', locale) + + // this.setState({locale}) + // } + // } + + // 保存语言类型 + storeLang () { + let locale = window.location.hash.split('/')[1] + + if (!locale || !(locale in locales)) { + locale = 'zh-CN' + } + + window.localStorage.setItem('HIUI_LANGUAGE', locale) + + return locale + } + + getCurrentDoc () { + const doc = window.location.hash.split('/') + if (doc[2] === 'components') { + return doc[2] + } else if (doc[2] === 'docs') { + return doc[3] + } + } + + renderHeader () { + const { + locale + } = this.props + + // const LANG = { + // 'zh-CN': 'English', + // 'en-US': '中文' + // } + + const doc = this.getCurrentDoc() + + return ( + + +
        +
      • Home
      • + {/*
      • 设计规范
      • */} +
      • Component
      • +
      • + +
      • +
      • + +
      • +
      +
      + ) + } + + render () { + const { sider } = this.props + const header = this.renderHeader() + + return ( + + ) + } +} + +export default connect(state => ({ + sider: state.global.sider, + theme: state.global.theme, + locale: state.global.locale +}))(Doc) diff --git a/site/view/Doc/index.js b/site/view/Doc/index.js index 4ff870809..b0900fd6e 100644 --- a/site/view/Doc/index.js +++ b/site/view/Doc/index.js @@ -12,13 +12,13 @@ import ThemeDropdown from '../Component/Dropdown/ThemeDropdown' import './index.scss' // 引入组件样式 -const req = require.context('../../../components', true, /^\.\/[^_][\w-]+\/style\/index\.js?$/) -req.keys().forEach((mod) => { - let v = req(mod) - if (v && v.default) { - v = v.default - } -}) +// const req = require.context('../../../components', true, /^\.\/[^_][\w-]+\/style\/index\.js?$/) +// req.keys().forEach((mod) => { +// let v = req(mod) +// if (v && v.default) { +// v = v.default +// } +// }) class Doc extends Component { // constructor (props) { @@ -28,6 +28,7 @@ class Doc extends Component { // } componentDidMount () { + // window.addEventListener('hashchange', this.hashChangeEvent) } @@ -89,7 +90,7 @@ class Doc extends Component { return ( 设计规范 */}
    • 组件
    • - +
    • - +
    diff --git a/site/view/Doc/index.scss b/site/view/Doc/index.scss index 9e4287b53..de23dfde5 100644 --- a/site/view/Doc/index.scss +++ b/site/view/Doc/index.scss @@ -1,14 +1,10 @@ -// @Todo: should be removed after classic-theme updated -ul, -li { - margin: 0; - padding: 0; - list-style: none; -} .dashboard { .header { &-nav { height: 64px; + margin: 0; + padding: 0; + list-style-type: none; display: flex; justify-content: flex-end; a { @@ -16,9 +12,9 @@ li { height: 64px; line-height: 64px; padding: 0 20px; - color: #383E47; display: inline-block; cursor: pointer; + color: #383e47; &:hover, &.active { color: #4284f5; diff --git a/site/view/Home/index.js b/site/view/Home/index.js index a158a0cfe..383f2f71b 100644 --- a/site/view/Home/index.js +++ b/site/view/Home/index.js @@ -7,8 +7,7 @@ import locales from '../../locales' class Home extends React.Component { constructor (props) { super(props) - - // const locale = this.storeLang() + this.storeLang() this.designText = React.createRef() this.designList = React.createRef() @@ -32,46 +31,28 @@ class Home extends React.Component { componentDidMount () { this.scrollEvent() window.addEventListener('scroll', this.scrollEvent) - // window.addEventListener('hashchange', this.hashChangeEvent) } componentWillUnmount () { window.removeEventListener('scroll', this.scrollEvent) - // window.removeEventListener('hashchange', this.hashChangeEvent) } - // hashChangeEvent () { - // let locale = window.location.hash.split('/')[1] - - // if (!locale) { return } - - // // 临时用于隐藏语言 - // if (locale !== 'zh-CN') { - // window.location.hash = window.location.hash.replace(locale, 'zh-CN') - // } - - // if (locale !== window.localStorage.getItem('HIUI_LANGUAGE')) { - // window.localStorage.setItem('HIUI_LANGUAGE', locale) - - // this.setState({locale}) - // } - // } - // 保存语言类型 storeLang () { let locale = window.location.hash.split('/')[1] - if (!locale || !(locale in locales)) { locale = window.localStorage.getItem('HIUI_LANGUAGE') if (locale && (locale in locales)) { window.location.hash = `#/${locale}` + } else { + window.localStorage.setItem('HIUI_LANGUAGE', this.props.locale) + window.location.hash = `#/${this.props.locale}` } } else { locale = 'zh-CN' window.localStorage.setItem('HIUI_LANGUAGE', locale) window.location.hash = `#/${locale}` } - return locale } diff --git a/site/view/Home/style/index.scss b/site/view/Home/style/index.scss index 355ace3a9..d9150dd87 100644 --- a/site/view/Home/style/index.scss +++ b/site/view/Home/style/index.scss @@ -32,26 +32,35 @@ .section-header { height: 64px; - line-height: 64px; - // border-bottom: 1px solid #eee; font-size: 14px; color: $primary-color; box-shadow: inset 0 -1px 0 0 #E6E7E8; } - -.logo-con .logo{ - display: inline-block; - width: 40px; - height: 40px; - margin-top: 12px; - margin-right: 10px; - background: url(#{$imgurl}../logo.png) center no-repeat; - background-size: 100%; +.logo-con { + line-height: 64px; + .logo { + display: inline-block; + width: 40px; + height: 40px; + margin-top: 12px; + margin-right: 10px; + background: url(#{$imgurl}../logo.png) center no-repeat; + background-size: 100%; + } } .intro { display: flex; align-items: center; + a { + line-height: 64px; + color: #383e47; + cursor: pointer; + &:hover, + &.active { + color: #4284f5; + } + } .item { margin-left: 35px; diff --git a/site/view/index.js b/site/view/index.js index 99d990846..dbf201ec1 100644 --- a/site/view/index.js +++ b/site/view/index.js @@ -1,6 +1,7 @@ import React from 'react' import { HashRouter, Route, Switch } from 'react-router-dom' import Doc from './Doc' +import DocEn from './Doc/en-US' import Home from './Home' import HomeEn from './Home/en-US' @@ -10,7 +11,7 @@ class Index extends React.Component { - +