diff --git a/package.json b/package.json index 412e29fe..211112ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@soramitsu/soramitsu-js-ui", - "version": "0.2.8", + "version": "0.3.0", "private": false, "publishConfig": { "registry": "https://nexus.iroha.tech/repository/npm-soramitsu-private/" @@ -73,6 +73,7 @@ "ts-jest": "^26.0.0", "typescript": "~3.8.3", "vue-cli-plugin-storybook": "~1.2.2", + "vue-i18n": "^8.11.2", "vue-router": "^3.3.4", "vue-template-compiler": "^2.6.11" }, diff --git a/src/components/Button/SButton.vue b/src/components/Button/SButton.vue index 37513e00..f8763a34 100644 --- a/src/components/Button/SButton.vue +++ b/src/components/Button/SButton.vue @@ -33,7 +33,6 @@ import { ButtonTypes, ButtonSize, ButtonNativeTypes } from './consts' }) export default class SButton extends Vue { readonly ButtonTypes = ButtonTypes - /** * Type of button. Possible values: `"primary"`, `"secondary"`, `"tertiary"`, `"action"`. * @@ -82,6 +81,10 @@ export default class SButton extends Vue { * By default it's set to "button" */ @Prop({ default: ButtonNativeTypes.BUTTON, type: String }) readonly nativeType!: string + /** + * Button tabindex + */ + @Prop({ default: '0', type: String }) readonly tabindex!: string @Inject({ default: '', from: 'elForm' }) elForm!: ElForm @Inject({ default: '', from: 'elFormItem' }) elFormItem!: ElFormItem @@ -155,6 +158,7 @@ export default class SButton extends Vue { } mounted (): void { + this.$el.setAttribute('tabindex', this.tabindex) this.$watch('loading', (value) => { if (!value) { return @@ -223,9 +227,10 @@ export default class SButton extends Vue { .tertiary { color: $color-basic-black; border: none; + background-color: transparent; &:hover, &:active, &:focus { color: $color-main-brand; - background-color: $color-basic-white; + background-color: transparent; } &:disabled, &:disabled:hover { color: $color-neutral-inactive; diff --git a/src/components/Pagination/SPagination.vue b/src/components/Pagination/SPagination.vue new file mode 100644 index 00000000..f05fc612 --- /dev/null +++ b/src/components/Pagination/SPagination.vue @@ -0,0 +1,291 @@ + + + + + diff --git a/src/components/Pagination/index.ts b/src/components/Pagination/index.ts new file mode 100644 index 00000000..ae6a4363 --- /dev/null +++ b/src/components/Pagination/index.ts @@ -0,0 +1,3 @@ +import SPagination from './SPagination.vue' + +export { SPagination } diff --git a/src/components/Table/STableColumn.vue b/src/components/Table/STableColumn.vue index 05d89e94..96fb3147 100644 --- a/src/components/Table/STableColumn.vue +++ b/src/components/Table/STableColumn.vue @@ -1,6 +1,5 @@ diff --git a/src/components/index.ts b/src/components/index.ts index e44872bf..ccf4ec46 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -20,6 +20,7 @@ import { SIcon } from './Icon' import { SInput, SJsonInput } from './Input' import { SMain } from './Layout/Main' import { SMenu, SMenuItem, SMenuItemGroup, SSubmenu } from './Menu' +import { SPagination } from './Pagination' import { SRow } from './Layout/Row' import { SScrollSectionItem, SScrollSections } from './ScrollSections' import { STab, STabs } from './Tab' @@ -54,6 +55,7 @@ export { SMenu, SMenuItem, SMenuItemGroup, + SPagination, SRow, SScrollSectionItem, SScrollSections, diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 00000000..4800c0dd --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,3 @@ +import { Float, Integer } from './number' + +export { Float, Integer } diff --git a/src/directives/number.ts b/src/directives/number.ts new file mode 100644 index 00000000..4fbf1122 --- /dev/null +++ b/src/directives/number.ts @@ -0,0 +1,61 @@ +import { DirectiveOptions } from 'vue' + +import { KeyValues } from '../utils/KeyValues' + +const onDigitKeyPress = (e: any) => { + if (!KeyValues.isDigit(e.key)) { + e.preventDefault() + } else { + return true + } +} + +const onNumberKeyPress = (e: any) => { + if (!KeyValues.isNumber(e.key) || (!KeyValues.isDigit(e.key) && e.target.value.includes('.'))) { + e.preventDefault() + } else { + return true + } +} + +export const Integer = { + bind (el, binding, vnode) { + const input = el.querySelector('input[type="text"]') as HTMLInputElement + if (input) { + input.addEventListener( + 'keypress', + onDigitKeyPress + ) + } + }, + unbind (el, binding, vnode) { + const input = el.querySelector('input[type="text"]') as HTMLInputElement + if (input) { + input.removeEventListener( + 'keypress', + onDigitKeyPress + ) + } + } +} as DirectiveOptions + +export const Float = { + bind (el, binding, vnode) { + const input = el.querySelector('input[type="text"]') as HTMLInputElement + if (input) { + input.addEventListener( + 'keypress', + onNumberKeyPress + ) + } + }, + unbind (el, binding, vnode) { + const input = el.querySelector('input[type="text"]') as HTMLInputElement + if (input) { + input.removeEventListener( + 'keypress', + onNumberKeyPress + ) + } + } +} as DirectiveOptions diff --git a/src/index.ts b/src/index.ts index 8359691c..84fef4dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,7 @@ import { SMenu, SMenuItem, SMenuItemGroup, + SPagination, SRow, SScrollSectionItem, SScrollSections, @@ -38,10 +39,12 @@ import { STableColumn, STooltip } from './components' +import { Float, Integer } from './directives' import { Components } from './types/components' +import { Directives } from './types/directives' import { Loading, Message, MessageBox, Notification } from './plugins/elementUI' -const elements = [ +const components = [ { component: SApp, name: Components.SApp }, { component: SAside, name: Components.SAside }, { component: SBreadcrumb, name: Components.SBreadcrumb }, @@ -69,6 +72,7 @@ const elements = [ { component: SMenu, name: Components.SMenu }, { component: SMenuItem, name: Components.SMenuItem }, { component: SMenuItemGroup, name: Components.SMenuItemGroup }, + { component: SPagination, name: Components.SPagination }, { component: SRow, name: Components.SRow }, { component: SScrollSectionItem, name: Components.SScrollSectionItem }, { component: SScrollSections, name: Components.SScrollSections }, @@ -80,9 +84,15 @@ const elements = [ { component: STooltip, name: Components.STooltip } ] +const directives = [ + { directive: Float, name: Directives.Float }, + { directive: Integer, name: Directives.Integer } +] + const SoramitsuElements = { install (vue: typeof Vue): void { - elements.forEach(el => vue.component(el.name, el.component)) + components.forEach(el => vue.component(el.name, el.component)) + directives.forEach(item => vue.directive(item.name, item.directive)) } } @@ -122,6 +132,7 @@ export { SMenu, SMenuItem, SMenuItemGroup, + SPagination, SRow, SScrollSectionItem, SScrollSections, diff --git a/src/lang/en/index.ts b/src/lang/en/index.ts new file mode 100644 index 00000000..2ebc2e95 --- /dev/null +++ b/src/lang/en/index.ts @@ -0,0 +1,7 @@ +import elementEnLocale from 'element-ui/lib/locale/lang/en' + +elementEnLocale.el.pagination.pagesize = '' + +export default { + ...elementEnLocale +} diff --git a/src/lang/index.ts b/src/lang/index.ts new file mode 100644 index 00000000..4fa27059 --- /dev/null +++ b/src/lang/index.ts @@ -0,0 +1,17 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +import en from './en' + +Vue.use(VueI18n) + +const messages = { + en +} + +const i18n = new VueI18n({ + locale: 'en', + messages +}) + +export default i18n diff --git a/src/plugins/elementUI.ts b/src/plugins/elementUI.ts index 36d59aff..0b71c0e0 100644 --- a/src/plugins/elementUI.ts +++ b/src/plugins/elementUI.ts @@ -1,107 +1,22 @@ import Vue from 'vue' -import { - Aside, - Badge, - Breadcrumb, - BreadcrumbItem, - Button, - ButtonGroup, - Card, - Checkbox, - Collapse, - CollapseItem, - Container, - DatePicker, - Dialog, - Divider, - Dropdown, - DropdownItem, - DropdownMenu, - Footer, - Form, - FormItem, - Header, - Input, - InputNumber, +import Element, { Loading, - Main, - Menu, - MenuItem, - MenuItemGroup, Message, MessageBox as MsgBox, - Notification, - Option, - Pagination, - Radio, - RadioGroup, - Select, - Submenu, - Switch, - Table, - TableColumn, - TabPane, - Tabs, - Tag, - Tooltip, - Upload + Notification } from 'element-ui' -// import lang from 'element-ui/lib/locale/lang/en' -// import locale from 'element-ui/lib/locale' -Vue.use(Breadcrumb) -Vue.use(BreadcrumbItem) -Vue.use(Collapse) -Vue.use(CollapseItem) -Vue.use(Dialog) -Vue.use(Divider) -Vue.use(Footer) -Vue.use(Menu) -Vue.use(MenuItem) -Vue.use(MenuItemGroup) -Vue.use(Submenu) -Vue.use(Input) -Vue.use(InputNumber) -Vue.use(Radio) -Vue.use(RadioGroup) -Vue.use(Select) -Vue.use(Option) -Vue.use(Button) -Vue.use(ButtonGroup) -Vue.use(Table) -Vue.use(TableColumn) -Vue.use(DatePicker) -Vue.use(Form) -Vue.use(FormItem) -Vue.use(Tag) -Vue.use(Upload) -Vue.use(Card) -Vue.use(Container) -Vue.use(Header) -Vue.use(Aside) -Vue.use(Main) -Vue.use(Dropdown) -Vue.use(DropdownMenu) -Vue.use(DropdownItem) -Vue.use(Tooltip) -Vue.use(Switch) -Vue.use(Badge) -Vue.use(Pagination) -Vue.use(Tabs) -Vue.use(TabPane) +import i18n from '../lang' + Vue.use(Loading.directive) -Vue.use(Checkbox) +Vue.use(Element, { i18n: (key, value) => i18n.t(key, value) }) const MessageBox = MsgBox -MsgBox.setDefaults({ - cancelButtonText: 'Cancel', - confirmButtonText: 'OK' -}) Vue.prototype.$loading = Loading.service Vue.prototype.$prompt = MessageBox.prompt Vue.prototype.$alert = MessageBox.alert Vue.prototype.$message = Message Vue.prototype.$notify = Notification -// locale.use(lang) // TODO: it will be used later + export { Loading, MessageBox, diff --git a/src/stories/SPagination.stories.ts b/src/stories/SPagination.stories.ts new file mode 100644 index 00000000..95b908b4 --- /dev/null +++ b/src/stories/SPagination.stories.ts @@ -0,0 +1,81 @@ +import { withKnobs, number, text, boolean } from '@storybook/addon-knobs' + +import { SPagination, SRow } from '../components' + +export default { + component: SPagination, + title: 'Design System/Pagination', + decorators: [withKnobs] +} + +export const configurable = () => ({ + components: { SRow, SPagination }, + template: ` + + + `, + props: { + layout: { + default: text('Layout', 'total, sizes, pager, prev, next, jumper') + }, + total: { + default: number('Total', 400) + }, + disabled: { + default: boolean('Disabled', false) + }, + small: { + default: boolean('Small', false) + }, + background: { + default: boolean('Background', false) + }, + prevText: { + default: text('Prev text', '') + }, + nextText: { + default: text('Next text', '') + } + }, + methods: { + handleSizeChange: (newSize: number) => console.log(`@size-change=${newSize}`), + handleCurrentChange: (newCurrent: number) => console.log(`@current-change=${newCurrent}`), + handlePrevClick: (newCurrent: number) => console.log(`@prev-click=${newCurrent}`), + handleNextClick: (newCurrent: number) => console.log(`@next-click=${newCurrent}`) + } +}) + +export const small = () => ({ + components: { SRow, SPagination }, + template: ` + + ` +}) + +export const withBackground = () => ({ + components: { SRow, SPagination }, + template: ` + + ` +}) + +export const disabled = () => ({ + components: { SRow, SPagination }, + template: ` + + + + ` +}) diff --git a/src/stories/Table/STable.stories.ts b/src/stories/Table/STable.stories.ts index daccf7de..23a39ef9 100644 --- a/src/stories/Table/STable.stories.ts +++ b/src/stories/Table/STable.stories.ts @@ -48,7 +48,12 @@ export const configurable = () => ({ - Hello + + + + Expanded! `, data: () => ({ tableData: tableData diff --git a/src/styles/common.scss b/src/styles/common.scss index 4af8f59b..dd3796c6 100644 --- a/src/styles/common.scss +++ b/src/styles/common.scss @@ -66,3 +66,31 @@ button > span { } } } + +.el-message-box { + .el-message-box__header { + .el-message-box__title { + color: $color-basic-black; + font-size: 16px; + } + } + .el-message-box__btns { + button.el-button.el-button--default.el-button--small { + height: $size-medium; + font-size: 14px; + border-radius: 4px; + &:hover, &:active, &:focus { + color: $color-main-brand; + background-color: $color-basic-white; + border-color: $color-main-brand; + } + &.el-button--primary { + &:hover, &:active, &:focus { + color: $color-basic-white; + background-color: $color-main-hover; + border-color: $color-main-hover; + } + } + } + } +} diff --git a/src/types/components.ts b/src/types/components.ts index 981a0733..6fad8e98 100644 --- a/src/types/components.ts +++ b/src/types/components.ts @@ -26,6 +26,7 @@ export enum Components { SMenu = 'SMenu', SMenuItem = 'SMenuItem', SMenuItemGroup = 'SMenuItemGroup', + SPagination = 'SPagination', SRow = 'SRow', SScrollSectionItem = 'SScrollSectionItem', SScrollSections = 'SScrollSections', diff --git a/src/types/directives.ts b/src/types/directives.ts new file mode 100644 index 00000000..b1b8a4bd --- /dev/null +++ b/src/types/directives.ts @@ -0,0 +1,4 @@ +export enum Directives { + Float = 'Float', + Integer = 'Integer' +} diff --git a/src/utils/KeyValues.ts b/src/utils/KeyValues.ts new file mode 100644 index 00000000..1ae08493 --- /dev/null +++ b/src/utils/KeyValues.ts @@ -0,0 +1,12 @@ +export class KeyValues { + private static readonly digits = /[0-9]/ + private static readonly numbers = /[0-9.]/ + + public static isDigit (digit: string): boolean { + return this.digits.test(digit) + } + + public static isNumber (number: string): boolean { + return this.numbers.test(number) + } +} diff --git a/yarn.lock b/yarn.lock index 6881c4bb..304dd4bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15623,6 +15623,11 @@ vue-hot-reload-api@^2.3.0: resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== +vue-i18n@^8.11.2: + version "8.21.0" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.21.0.tgz#526450525fdbb9c877685b5ba6cb9573b73d3940" + integrity sha512-pKBq6Kg5hNacFHMFgPbpYsFlDIMRu4Ew/tpvTWns14CZoCxt7B3tmSNdrLruGMMivnJu1rhhRqsQqT6YwHkuQQ== + vue-jest@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-3.0.5.tgz#d6f124b542dcbff207bf9296c19413f4c40b70c9"