diff --git a/package.json b/package.json index 211112ee..f694e1f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@soramitsu/soramitsu-js-ui", - "version": "0.3.0", + "version": "0.3.1", "private": false, "publishConfig": { "registry": "https://nexus.iroha.tech/repository/npm-soramitsu-private/" diff --git a/src/components/DatePicker/SDatePicker.vue b/src/components/DatePicker/SDatePicker.vue new file mode 100644 index 00000000..04fbc835 --- /dev/null +++ b/src/components/DatePicker/SDatePicker.vue @@ -0,0 +1,487 @@ + + + + + diff --git a/src/components/DatePicker/consts.ts b/src/components/DatePicker/consts.ts new file mode 100644 index 00000000..b28af7a3 --- /dev/null +++ b/src/components/DatePicker/consts.ts @@ -0,0 +1,26 @@ +import { Size } from '../../types' + +export enum PickerTypes { + YEAR = 'year', + MONTH = 'month', + DATE = 'date', + DATES = 'dates', + DATETIME = 'datetime', + WEEK = 'week', + DATETIMERANGE = 'datetimerange', + DATERANGE = 'daterange', + MONTHRANGE = 'monthrange' +} + +export enum PickerAlignment { + LEFT = 'left', + RIGHT = 'right', + CENTER = 'center' +} + +export enum InputTypes { + INPUT = 'input', + SELECT = 'select' +} + +export const PickerSize = Size diff --git a/src/components/DatePicker/index.ts b/src/components/DatePicker/index.ts new file mode 100644 index 00000000..e100a2dc --- /dev/null +++ b/src/components/DatePicker/index.ts @@ -0,0 +1,10 @@ +import SDatePicker from './SDatePicker.vue' +import { PickerTypes, PickerAlignment, InputTypes, PickerSize } from './consts' + +export { + SDatePicker, + PickerTypes, + PickerAlignment, + InputTypes, + PickerSize +} diff --git a/src/components/Pagination/SPagination.vue b/src/components/Pagination/SPagination.vue index f05fc612..4f1b1aaa 100644 --- a/src/components/Pagination/SPagination.vue +++ b/src/components/Pagination/SPagination.vue @@ -77,13 +77,13 @@ export default class SPagination extends Vue { */ @Prop({ default: '', type: String }) readonly popperClass!: string /** - * Custom class name for the total element of the pagination component + * Styles object for the total element of the pagination component */ - @Prop({ default: '', type: String }) readonly totalClass!: string + @Prop() readonly totalStyle!: object /** - * Custom class name for the sizes element of the pagination component + * Styles object for the sizes element of the pagination component */ - @Prop({ default: '', type: String }) readonly sizesClass!: string + @Prop() readonly sizesStyle!: object /** * Text of the previous button */ @@ -118,11 +118,15 @@ export default class SPagination extends Vue { const items = Array.from(this.pagination.$el.childNodes) as Array this.totalItem = items.find(item => item.className === 'el-pagination__total') this.sizesItem = items.find(item => item.className === 'el-pagination__sizes') - if (this.totalItem && this.totalClass) { - (this.totalItem as Element).classList.add(this.totalClass) + if (this.totalItem && this.totalStyle) { + for (const styleProp in this.totalStyle) { + (this.totalItem as HTMLElement).style[styleProp] = this.totalStyle[styleProp] + } } - if (this.sizesItem && this.sizesClass) { - (this.sizesItem as Element).classList.add(this.sizesClass) + if (this.sizesItem && this.sizesStyle) { + for (const styleProp in this.sizesStyle) { + (this.sizesItem as HTMLElement).style[styleProp] = this.sizesStyle[styleProp] + } } } @@ -239,6 +243,7 @@ export default class SPagination extends Vue { } .el-pagination__total, .per-page-text, .el-pagination__jump { color: $color-neutral-secondary; + font-weight: normal; } .el-pager li { color: $color-basic-black; diff --git a/src/components/Select/SOption.vue b/src/components/Select/SOption.vue new file mode 100644 index 00000000..1cea17fa --- /dev/null +++ b/src/components/Select/SOption.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/components/Select/SOptionGroup.vue b/src/components/Select/SOptionGroup.vue new file mode 100644 index 00000000..df01ef52 --- /dev/null +++ b/src/components/Select/SOptionGroup.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/Select/SSelect.vue b/src/components/Select/SSelect.vue new file mode 100644 index 00000000..8ed019e1 --- /dev/null +++ b/src/components/Select/SSelect.vue @@ -0,0 +1,411 @@ + + + + + diff --git a/src/components/Select/consts.ts b/src/components/Select/consts.ts new file mode 100644 index 00000000..0484a8e2 --- /dev/null +++ b/src/components/Select/consts.ts @@ -0,0 +1,4 @@ +export enum InputTypes { + INPUT = 'input', + SELECT = 'select' +} diff --git a/src/components/Select/index.ts b/src/components/Select/index.ts new file mode 100644 index 00000000..fa6ba46e --- /dev/null +++ b/src/components/Select/index.ts @@ -0,0 +1,6 @@ +import SSelect from './SSelect.vue' +import SOption from './SOption.vue' +import SOptionGroup from './SOptionGroup.vue' +import { InputTypes } from './consts' + +export { SSelect, SOption, SOptionGroup, InputTypes } diff --git a/src/components/index.ts b/src/components/index.ts index ccf4ec46..e6622472 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -10,6 +10,7 @@ import { SCheckbox } from './Checkbox' import { SCol } from './Layout/Col' import { SCollapse, SCollapseItem } from './Collapse' import { SContainer } from './Layout/Container' +import { SDatePicker } from './DatePicker' import { SDialog } from './Dialog' import { SDivider } from './Divider' import { SDropdown, SDropdownItem } from './Dropdown' @@ -23,6 +24,7 @@ import { SMenu, SMenuItem, SMenuItemGroup, SSubmenu } from './Menu' import { SPagination } from './Pagination' import { SRow } from './Layout/Row' import { SScrollSectionItem, SScrollSections } from './ScrollSections' +import { SSelect, SOption, SOptionGroup } from './Select' import { STab, STabs } from './Tab' import { STable, STableColumn } from './Table' import { STooltip } from './Tooltip' @@ -40,6 +42,7 @@ export { SCollapse, SCollapseItem, SContainer, + SDatePicker, SDialog, SDivider, SDropdown, @@ -55,10 +58,13 @@ export { SMenu, SMenuItem, SMenuItemGroup, + SOption, + SOptionGroup, SPagination, SRow, SScrollSectionItem, SScrollSections, + SSelect, SSubmenu, STab, STabs, diff --git a/src/index.ts b/src/index.ts index 84fef4dc..e8d3487e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ import { SCollapse, SCollapseItem, SContainer, + SDatePicker, SDialog, SDivider, SDropdown, @@ -28,10 +29,13 @@ import { SMenu, SMenuItem, SMenuItemGroup, + SOption, + SOptionGroup, SPagination, SRow, SScrollSectionItem, SScrollSections, + SSelect, SSubmenu, STab, STabs, @@ -57,6 +61,7 @@ const components = [ { component: SCollapse, name: Components.SCollapse }, { component: SCollapseItem, name: Components.SCollapseItem }, { component: SContainer, name: Components.SContainer }, + { component: SDatePicker, name: Components.SDatePicker }, { component: SDialog, name: Components.SDialog }, { component: SDivider, name: Components.SDivider }, { component: SDropdown, name: Components.SDropdown }, @@ -72,10 +77,13 @@ const components = [ { component: SMenu, name: Components.SMenu }, { component: SMenuItem, name: Components.SMenuItem }, { component: SMenuItemGroup, name: Components.SMenuItemGroup }, + { component: SOption, name: Components.SOption }, + { component: SOptionGroup, name: Components.SOptionGroup }, { component: SPagination, name: Components.SPagination }, { component: SRow, name: Components.SRow }, { component: SScrollSectionItem, name: Components.SScrollSectionItem }, { component: SScrollSections, name: Components.SScrollSections }, + { component: SSelect, name: Components.SSelect }, { component: SSubmenu, name: Components.SSubmenu }, { component: STab, name: Components.STab }, { component: STabs, name: Components.STabs }, @@ -117,6 +125,7 @@ export { SCollapse, SCollapseItem, SContainer, + SDatePicker, SDialog, SDivider, SDropdown, @@ -133,9 +142,12 @@ export { SMenuItem, SMenuItemGroup, SPagination, + SOption, + SOptionGroup, SRow, SScrollSectionItem, SScrollSections, + SSelect, SSubmenu, STab, STabs, diff --git a/src/stories/DatePicker.stories.ts b/src/stories/DatePicker.stories.ts new file mode 100644 index 00000000..f59c5b28 --- /dev/null +++ b/src/stories/DatePicker.stories.ts @@ -0,0 +1,218 @@ +import { text, withKnobs, select, boolean } from '@storybook/addon-knobs' + +import { SDatePicker, SRow, SCol } from '../components' +import { PickerAlignment, PickerTypes, InputTypes } from '../components/DatePicker' + +export default { + component: SDatePicker, + title: 'Design System/Date Picker', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const configurable = () => ({ + components: { SDatePicker }, + template: `
+ + + + v-model="{{ vModelValue }}" + + + @change="{{ changeValue }}" + +
`, + data: () => ({ + vModelValue: '', + changeValue: '' + }), + props: { + unlinkPanels: { + default: boolean('Unlink Panels', false) + }, + type: { + default: select('Type', Object.values(PickerTypes), PickerTypes.DATE) + }, + inputType: { + default: select('Input Type', Object.values(InputTypes), InputTypes.INPUT) + }, + readonly: { + default: boolean('Readonly', false) + }, + disabled: { + default: boolean('Disabled', false) + }, + clearable: { + default: boolean('Clearable', true) + }, + align: { + default: select('Align', Object.values(PickerAlignment), PickerAlignment.LEFT) + } + }, + methods: { + handleChange: (value: any, model: any) => console.log(value, model) + } +}) + +export const differentTypesData = Object.values(PickerTypes).map(type => { + const label = type[0].toUpperCase() + type.slice(1) + const data = { type, label, inputType: InputTypes.SELECT, model: '' } as any + if ([PickerTypes.DATERANGE, PickerTypes.DATETIMERANGE, PickerTypes.MONTHRANGE].includes(type)) { + data.startPlaceholder = 'From' + data.endPlaceholder = 'To' + } else { + data.placeholder = `Select ${type}` + } + return data +}).concat([ + PickerTypes.DATE, + PickerTypes.DATES, + PickerTypes.DATETIME, + PickerTypes.MONTH, + PickerTypes.WEEK, + PickerTypes.YEAR +].map(type => { + const label = `${type[0].toUpperCase() + type.slice(1)} with input-type="input"` + const data = { type, label, inputType: InputTypes.INPUT, model: '' } as any + data.placeholder = `Select ${type}` + return data +})) +export const withDifferentTypes = () => ({ + components: { SCol, SRow, SDatePicker }, + template: ` + +
{{ item.label }}
+ + +
+ +
{{ item.label }}
+ + +
+
`, + data: () => ({ + selectItems: differentTypesData.filter(item => item.inputType === InputTypes.SELECT), + inputItems: differentTypesData.filter(item => item.inputType === InputTypes.INPUT) + }) +}) + +export const differentRangeTypesData = [ + PickerTypes.DATERANGE, + PickerTypes.DATETIMERANGE, + PickerTypes.MONTHRANGE +].map(type => { + const label = type[0].toUpperCase() + type.slice(1) + return { type, label, model: '', startPlaceholder: 'From', endPlaceholder: 'To' } +}) +export const withUnlinkPanels = () => ({ + components: { SCol, SRow, SDatePicker }, + template: ` + +
{{ item.label }}
+ + +
+
`, + data: () => ({ + items: differentRangeTypesData + }) +}) + +export const disabledData = Object.values(InputTypes).map(inputType => { + return { type: PickerTypes.DATE, placeholder: 'Select date', inputType } +}).flatMap(item => [{ ...item, model: '' }, { ...item, model: new Date() }]) +export const disabled = () => ({ + components: { SCol, SRow, SDatePicker }, + template: ` + + + + + `, + data: () => ({ + items: disabledData + }) +}) + +export const withAdditionalOptions = () => ({ + components: { SCol, SRow, SDatePicker }, + template: ` + + + + + `, + data: () => ({ + model: '', + pickerOptions: { + disabledDate (time) { + return time.getTime() > Date.now() + }, + shortcuts: [{ + text: 'Today', + onClick (picker) { + picker.$emit('pick', new Date()) + } + }, { + text: 'Yesterday', + onClick (picker) { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24) + picker.$emit('pick', date) + } + }, { + text: 'A week ago', + onClick (picker) { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7) + picker.$emit('pick', date) + console.log(picker) + } + }] + } + }) +}) diff --git a/src/stories/Select/SOption.stories.ts b/src/stories/Select/SOption.stories.ts new file mode 100644 index 00000000..79770041 --- /dev/null +++ b/src/stories/Select/SOption.stories.ts @@ -0,0 +1,44 @@ +import { text, withKnobs, boolean } from '@storybook/addon-knobs' + +import { SSelect, SRow, SCol, SOption } from '../../components' + +export default { + component: SOption, + title: 'Design System/Select/Option', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const optionsData = [ + { label: 'First', value: 'first' }, + { label: 'Second', value: 'second' }, + { label: 'Third', value: 'third' } +] +export const configurable = () => ({ + components: { SSelect, SOption, SRow, SCol }, + template: ` + + + + + + + `, + data: () => ({ + model: '', + options: optionsData + }), + props: { + disabled: { + default: boolean('Disabled', false) + }, + label: { + default: text('Label', 'Custom') + } + } +}) diff --git a/src/stories/Select/SOptionGroup.stories.ts b/src/stories/Select/SOptionGroup.stories.ts new file mode 100644 index 00000000..49c9a274 --- /dev/null +++ b/src/stories/Select/SOptionGroup.stories.ts @@ -0,0 +1,53 @@ +import { text, withKnobs, boolean } from '@storybook/addon-knobs' + +import { SSelect, SRow, SCol, SOption, SOptionGroup } from '../../components' + +export default { + component: SOptionGroup, + title: 'Design System/Select/Option Group', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const optionsData = [ + { label: 'First', value: 'first' }, + { label: 'Second', value: 'second' }, + { label: 'Third', value: 'third' } +] +export const configurable = () => ({ + components: { SSelect, SOption, SRow, SCol, SOptionGroup }, + template: ` + + + + + + + + + + + `, + data: () => ({ + model: '', + options: optionsData + }), + props: { + disabled: { + default: boolean('Disabled', false) + }, + label: { + default: text('Label', 'Custom') + } + } +}) diff --git a/src/stories/Select/SSelect.stories.ts b/src/stories/Select/SSelect.stories.ts new file mode 100644 index 00000000..0fb66cba --- /dev/null +++ b/src/stories/Select/SSelect.stories.ts @@ -0,0 +1,153 @@ +import { text, withKnobs, boolean, number } from '@storybook/addon-knobs' + +import { SSelect, SRow, SCol, SOption } from '../../components' +import { InputTypes } from '../../components/Select' + +export default { + component: SSelect, + title: 'Design System/Select', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const differentInputsData = Object.values(InputTypes).map(inputType => ({ inputType, model: '' })) +export const optionsData = [ + { label: 'First', value: 'first' }, + { label: 'Second', value: 'second' }, + { label: 'Third', value: 'third' } +] + +export const configurable = () => ({ + components: { SSelect, SOption, SRow, SCol }, + template: ` + +
"{{ item.inputType }}" input type
+ + + +
+
`, + data: () => ({ + model: '', + items: differentInputsData, + options: optionsData + }), + props: { + disabled: { + default: boolean('Disabled', false) + }, + loading: { + default: boolean('Loading', false) + }, + multiple: { + default: boolean('Multiple', false) + }, + clearable: { + default: boolean('Clearable', false) + }, + multipleLimit: { + default: number('Multiple limit', 0) + }, + placeholder: { + default: text('Placeholder', 'Select') + }, + multipleTextPrefix: { + default: text('Multiple text prefix', 'Data') + }, + loadingText: { + default: text('Loading text', 'Loading') + }, + noDataText: { + default: text('No data text', 'No data') + } + }, + methods: { + handleChange: (selected) => console.log('handleChange', selected) + } +}) + +export const multiple = () => ({ + components: { SSelect, SOption, SRow, SCol }, + template: ` + +
"{{ item.inputType }}" input type
+ + + +
+
`, + data: () => ({ + model: '', + items: differentInputsData, + options: optionsData + }), + props: { + multipleLimit: { + default: number('Multiple limit', 0) + }, + multipleTextPrefix: { + default: text('Multiple text prefix', 'Data') + } + }, + methods: { + handleChange: (selected) => console.log('handleChange', selected) + } +}) + +export const disabled = () => ({ + components: { SSelect, SOption, SRow, SCol }, + template: ` + +
{{ item.label }}
+ + + +
+
`, + data: () => ({ + items: differentInputsData.flatMap(item => [ + { ...item, label: `"${item.inputType}" input type` }, + { ...item, model: 'first', label: `"${item.inputType}" input type with selected value` } + ]), + options: optionsData + }) +}) diff --git a/src/styles/icons.scss b/src/styles/icons.scss index 73248705..53039ba4 100644 --- a/src/styles/icons.scss +++ b/src/styles/icons.scss @@ -11,6 +11,7 @@ -moz-osx-font-smoothing: grayscale; color: $color-basic-black; } +$icons-font: 'soramitsu-icons' !important; /*_____________________________________________Icons variables_____________________________________________*/ $s-icon-warning: "\e96c"; $s-icon-logout: "\e98c"; diff --git a/src/types/components.ts b/src/types/components.ts index 6fad8e98..3b1a4701 100644 --- a/src/types/components.ts +++ b/src/types/components.ts @@ -11,6 +11,7 @@ export enum Components { SCollapse = 'SCollapse', SCollapseItem = 'SCollapseItem', SContainer = 'SContainer', + SDatePicker = 'SDatePicker', SDialog = 'SDialog', SDivider = 'SDivider', SDropdown = 'SDropdown', @@ -26,10 +27,13 @@ export enum Components { SMenu = 'SMenu', SMenuItem = 'SMenuItem', SMenuItemGroup = 'SMenuItemGroup', + SOption = 'SOption', + SOptionGroup = 'SOptionGroup', SPagination = 'SPagination', SRow = 'SRow', SScrollSectionItem = 'SScrollSectionItem', SScrollSections = 'SScrollSections', + SSelect = 'SSelect', SSubmenu = 'SSubmenu', STab = 'STab', STabs = 'STabs',