@itfin/components 1.3.33 → 1.3.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/package.json +2 -1
  2. package/src/ITFSettings.js +8 -0
  3. package/src/assets/fonts/bootstrap-icons.woff +0 -0
  4. package/src/assets/fonts/bootstrap-icons.woff2 +0 -0
  5. package/src/assets/scss/components/select/_selected.scss +1 -1
  6. package/src/assets/scss/icons.scss +2085 -0
  7. package/src/assets/scss/main.scss +1 -0
  8. package/src/components/avatar/index.stories.js +0 -1
  9. package/src/components/button/1.html +30 -0
  10. package/src/components/button/NativeButton.js +116 -0
  11. package/src/components/button/index.stories.js +10 -6
  12. package/src/components/checkbox/Checkbox.vue +5 -1
  13. package/src/components/datepicker/DatePickerInline.vue +10 -3
  14. package/src/components/datepicker/DateRangePickerInline.vue +10 -3
  15. package/src/components/dropdown/Dropdown.vue +5 -4
  16. package/src/components/dropdown/DropdownMenu.vue +7 -0
  17. package/src/components/filter/FilterBadge.vue +36 -19
  18. package/src/components/filter/FilterControl.vue +105 -0
  19. package/src/components/filter/constants.js +7 -6
  20. package/src/components/filter/index.stories.js +31 -3
  21. package/src/components/select/Select.vue +9 -2
  22. package/src/components/sortable/sortable-shopify.js +1 -1
  23. package/src/components/table/Table2.vue +108 -33
  24. package/src/components/table/TableBody.vue +58 -36
  25. package/src/components/table/TableGroup.vue +166 -114
  26. package/src/components/table/TableHeader.vue +153 -36
  27. package/src/components/table/index.stories.js +152 -4
  28. package/src/components/table/sticky.js +439 -0
  29. package/src/components/text-field/TextField.vue +1 -0
@@ -1,5 +1,6 @@
1
1
  @import './css_variables.scss';
2
2
  @import './fonts.scss';
3
+ @import './icons.scss';
3
4
  @import './dark-theme.scss';
4
5
  @import './scrollbar';
5
6
  @import './components/air-select';
@@ -2,7 +2,6 @@ import { storiesOf } from '@storybook/vue';
2
2
  import itfAvatar from './Avatar.vue';
3
3
 
4
4
  storiesOf('Common', module)
5
- .addDecorator(withKnobs)
6
5
  .add('Avatar', () => ({
7
6
  components: {
8
7
  itfAvatar
@@ -0,0 +1,30 @@
1
+ <div class="notion-overlay-container notion-default-overlay-container"
2
+ style="position: fixed; inset: 0px; z-index: 999; pointer-events: none; overflow: hidden;">
3
+ <div style="position: relative; z-index: 0;"></div>
4
+ <div data-overlay="true" style="pointer-events: auto; position: relative; z-index: 0;">
5
+ <div>
6
+ <div style="position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh;"></div>
7
+ <div style="position: fixed; left: 347px; top: 463.398px; pointer-events: none;">
8
+ <div style="width: 280px; height: 0px;"></div>
9
+ <div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start;">
10
+ <div style="position: relative; top: 100%; pointer-events: auto;">
11
+ <div style="display: flex; align-items: center; position: relative; flex-direction: column-reverse; transform-origin: 0% top; left: 0px; top: 0px;">
12
+ <div role="dialog"
13
+ style="border-radius: 6px; background: white; backdrop-filter: none; position: relative; max-width: calc(-24px + 100vw); box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px; overflow: visible; width: 280px; min-height: 34px; max-height: 634px; display: flex; flex-direction: column;">
14
+ <div style="display: flex; flex-direction: column; overflow-y: auto; flex-grow: 1; height: 100%;">
15
+ <div style="padding: 6px 9px; font-size: 14px; min-height: 34px; display: flex; height: 100%; flex-direction: column; justify-content: space-between; flex-grow: 1; font-weight: 500;">
16
+ <div class="notranslate" spellcheck="true" placeholder=" "
17
+ data-content-editable-leaf="true" contenteditable="true"
18
+ style="max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-color: rgb(55, 53, 47);">
19
+ d
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
@@ -0,0 +1,116 @@
1
+ const CSS_CLASSES = {
2
+ btn: ['itf-button', 'btn'],
3
+ basic: ['btn-basic'],
4
+ primary: ['btn-primary'],
5
+ secondary: ['btn-secondary'],
6
+ large: ['btn-lg'],
7
+ small: ['btn-sm'],
8
+ block: ['itf-button__block'],
9
+ labeled: ['labeled'],
10
+ squircle: ['btn-squircle'],
11
+ icon: ['btn-icon'],
12
+ loading: ['loading'],
13
+ spinner: ['itf-spinner'],
14
+ loadingWhite: ['itf-spinner__white'],
15
+ };
16
+
17
+ export
18
+ class Button extends HTMLElement {
19
+
20
+ static get observedAttributes() {
21
+ return ['disabled', 'open'];
22
+ }
23
+
24
+ get isLoading() {
25
+ return this.hasAttribute('loading');
26
+ }
27
+
28
+ get styleClasses() {
29
+ let styles = [];
30
+ if (this.hasAttribute('color')) {
31
+ styles.push(`btn-${this.getAttribute('color')}`);
32
+ }
33
+ if (this.hasAttribute('block')) {
34
+ styles.push(CSS_CLASSES.block);
35
+ }
36
+ if (this.hasAttribute('labeled')) {
37
+ styles.push(CSS_CLASSES.labeled);
38
+ }
39
+ if (this.hasAttribute('squircle')) {
40
+ styles.push(CSS_CLASSES.squircle);
41
+ }
42
+ if (this.hasAttribute('icon')) {
43
+ styles.push(CSS_CLASSES.icon);
44
+ }
45
+ if (this.isLoading) {
46
+ styles.push(CSS_CLASSES.loading);
47
+ }
48
+
49
+ if (this.hasAttribute('small')) {
50
+ styles = styles.concat(CSS_CLASSES.small);
51
+ } else if (this.hasAttribute('large')) {
52
+ styles = styles.concat(CSS_CLASSES.large);
53
+ }
54
+
55
+ if (this.hasAttribute('primary')) {
56
+ styles = styles.concat(CSS_CLASSES.primary);
57
+ } else if (this.hasAttribute('secondary')) {
58
+ styles = styles.concat(CSS_CLASSES.secondary);
59
+ } else if (!this.hasAttribute('color')) {
60
+ styles = styles.concat(CSS_CLASSES.basic);
61
+ }
62
+ return styles;
63
+ }
64
+
65
+ get open() {
66
+ return this.hasAttribute('open');
67
+ }
68
+
69
+ get disabled() {
70
+ return this.hasAttribute('disabled');
71
+ }
72
+
73
+ set disabled(val) {
74
+ if (val) {
75
+ this.setAttribute('tabindex', '-1');
76
+ this.setAttribute('disabled', '');
77
+ this.setAttribute('aria-disabled', 'true');
78
+ } else {
79
+ this.setAttribute('tabindex', '0');
80
+ this.setAttribute('aria-disabled', 'false');
81
+ this.removeAttribute('disabled');
82
+ }
83
+ }
84
+
85
+ constructor() {
86
+ super();
87
+ }
88
+
89
+ connectedCallback() {
90
+ const button = document.createElement('button');
91
+
92
+ const loadingText = this.getAttribute('loading-text');
93
+ const html = this.innerHTML;
94
+ this.replaceWith(button);
95
+ button.innerHTML = html;
96
+ button.classList.add(...CSS_CLASSES.btn);
97
+ button.classList.add(...this.styleClasses);
98
+
99
+ if (this.isLoading) {
100
+ button.setAttribute('disabled', 'disabled');
101
+ const loadingDiv = document.createElement('div');
102
+ const spinnerDiv = document.createElement('div');
103
+ spinnerDiv.classList.add(...CSS_CLASSES.spinner);
104
+ if (this.hasAttribute('primary') || this.hasAttribute('white')) {
105
+ spinnerDiv.classList.add(CSS_CLASSES.loadingWhite);
106
+ }
107
+ loadingDiv.appendChild(spinnerDiv);
108
+ // if (this.isLoading && loadingText) {
109
+ // const loadingTextDiv = document.createElement('div');
110
+ // loadingTextDiv.innerHTML = loadingText;
111
+ // loadingDiv.appendChild(loadingTextDiv);
112
+ // }
113
+ button.appendChild(loadingDiv);
114
+ }
115
+ }
116
+ }
@@ -5,14 +5,18 @@ import itfLabel from '../form/Label.vue';
5
5
  import itfDatePicker from '../datepicker/DatePicker.vue';
6
6
  import itfDateRangePicker from '../datepicker/DateRangePicker.vue';
7
7
  import itfApp from '../app/App.vue';
8
+ // import {Button} from './Button.js';
9
+
10
+ // window.customElements.define('itf-button', Button);
11
+
8
12
 
9
13
  storiesOf('Common', module)
10
14
  .add('Buttons', () => ({
11
15
  components: {
16
+ itfButton,
12
17
  itfApp,
13
18
  itfForm,
14
19
  itfLabel,
15
- itfButton,
16
20
  itfDatePicker,
17
21
  itfDateRangePicker
18
22
  },
@@ -62,7 +66,7 @@ storiesOf('Common', module)
62
66
 
63
67
  <h3>Standart button</h3>
64
68
 
65
- <itf-button primary>Primary button</itf-button>
69
+ <itf-button squircle primary>Primary button</itf-button>
66
70
  <itf-button secondary>Secondary button</itf-button>
67
71
  <itf-button>Basic button</itf-button>
68
72
  <itf-button icon>
@@ -88,7 +92,7 @@ storiesOf('Common', module)
88
92
 
89
93
  <h3>Large button</h3>
90
94
 
91
- <itf-button large primary>Primary button</itf-button>
95
+ <itf-button squircle large primary>Primary button</itf-button>
92
96
  <itf-button large secondary>Secondary button</itf-button>
93
97
  <itf-button large>Basic button</itf-button>
94
98
  <itf-button large icon>
@@ -103,12 +107,12 @@ storiesOf('Common', module)
103
107
  <itf-button primary loading>Primary button</itf-button>
104
108
  <itf-button secondary loading>Secondary button</itf-button>
105
109
  <itf-button loading>Basic button</itf-button>
106
- <itf-button primary loading small>Small button</itf-button>
110
+ <itf-button primary loading small loading-text="Loading...">Small button</itf-button>
107
111
  <itf-button primary loading large>Large button</itf-button>
108
112
 
109
113
  <h4>Test loading</h4>
110
-
111
- <itf-button @click="testLoading" primary :loading="isLoading" loading-text="Saving...">Click to test loading</itf-button>
114
+ {{isLoading}}
115
+ <itf-button onclick="testLoading" primary :loading.prop="isLoading" loading-text="Saving...">Click to test loading</itf-button>
112
116
 
113
117
  </itf-app>
114
118
  </div>`,
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
 
3
3
  <div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
4
- <input class="form-check-input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
4
+ <input class="form-check-input" ref="input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
5
5
  <label :for="id" class="form-check-label">
6
6
  <slot name="label">
7
7
  {{label}}
@@ -60,5 +60,9 @@ class itfCheckbox extends Vue {
60
60
  }
61
61
  this.$emit('input', val);
62
62
  }
63
+
64
+ get input() {
65
+ return this.$refs.input;
66
+ }
63
67
  }
64
68
  </script>
@@ -68,15 +68,22 @@ class itfDatePickerInline extends Vue {
68
68
  const [
69
69
  { default: AirDatepicker },
70
70
  { default: localeEn },
71
- { default: localeUk }
71
+ { default: localeUk },
72
+ { default: localeDe }
72
73
  ] = await Promise.all([
73
74
  import('babel-loader!air-datepicker/air-datepicker.js'),
74
75
  import('babel-loader!air-datepicker/locale/en'),
75
- import('babel-loader!air-datepicker/locale/uk')
76
+ import('babel-loader!air-datepicker/locale/uk'),
77
+ import('babel-loader!air-datepicker/locale/de')
76
78
  ]);
77
79
 
80
+ const locales = {
81
+ en: localeEn,
82
+ uk: localeUk,
83
+ de: localeDe,
84
+ };
78
85
  this.calendar = new AirDatepicker(this.$refs.calendar, {
79
- locale: this.$i18n.locale === 'en' ? localeEn : localeUk,
86
+ locale: locales[this.$i18n.locale] || locales.en,
80
87
  firstDay: 1,
81
88
  altFieldDateFormat: this.valueFormat,
82
89
  range: this.range,
@@ -68,19 +68,26 @@ class itfDatePickerInline extends Vue {
68
68
  const [
69
69
  { default: AirDatepicker },
70
70
  { default: localeEn },
71
- { default: localeUk }
71
+ { default: localeUk },
72
+ { default: localeDe }
72
73
  ] = await Promise.all([
73
74
  import('babel-loader!air-datepicker/air-datepicker.js'),
74
75
  import('babel-loader!air-datepicker/locale/en'),
75
- import('babel-loader!air-datepicker/locale/uk')
76
+ import('babel-loader!air-datepicker/locale/uk'),
77
+ import('babel-loader!air-datepicker/locale/de')
76
78
  ]);
77
79
 
80
+ const locales = {
81
+ en: localeEn,
82
+ uk: localeUk,
83
+ de: localeDe,
84
+ };
78
85
  this.calendar = new AirDatepicker(this.$refs.calendar, {
86
+ locale: locales[this.$i18n.locale] || locales.en,
79
87
  firstDay: 1,
80
88
  altFieldDateFormat: this.valueFormat,
81
89
  minDate: this.minDate,
82
90
  maxDate: this.maxDate,
83
- locale: this.$i18n.locale === 'en' ? localeEn : localeUk,
84
91
  range: true,
85
92
  dynamicRange: true,
86
93
  toggleSelected: false,
@@ -33,22 +33,23 @@ class itfDropdown extends Vue {
33
33
  render (createElement, context) {
34
34
  const { props, slots, data } = context;
35
35
  const modalId = `dropdownId${globalModalIndex++}`;
36
- const { buttonOptions, toggle, text, right, shadow, label, appendToBody } = props;
36
+ const { buttonOptions, toggle, text, disabled, label, appendToBody } = props;
37
37
  const { button, default: defaultSlot } = slots();
38
38
  let elements = [
39
39
  createElement(
40
40
  text ? 'div' : itfButton,
41
41
  {
42
+ staticClass: data.staticClass || '',
42
43
  props: buttonOptions || {},
43
44
  class: { 'dropdown-toggle': toggle },
44
- attrs: { id: modalId, 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false' },
45
- ref: 'toggle',
45
+ attrs: { id: modalId, 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false', ...(data.attrs || {}) },
46
46
  },
47
47
  button || label
48
48
  ),
49
- createElement(
49
+ disabled ? null : createElement(
50
50
  itfDropdownMenu,
51
51
  {
52
+ ref: data.ref,
52
53
  props: { ...props, toggleId: modalId },
53
54
  },
54
55
  defaultSlot
@@ -57,6 +57,13 @@ class itfDropdownMenu extends Vue {
57
57
  });
58
58
  }
59
59
 
60
+ beforeDestroy() {
61
+ if (this.modalEl) {
62
+ this.modalEl.hide();
63
+ this.modalEl.dispose();
64
+ }
65
+ }
66
+
60
67
  show() {
61
68
  if (this.modalEl) {
62
69
  this.modalEl.show();
@@ -1,18 +1,35 @@
1
1
  <template>
2
2
 
3
3
 
4
- <span class="border rounded d-inline-flex ps-3 pe-1 gap-1 align-items-center">
4
+ <span class="b-filter-badge border rounded d-inline-flex ps-3 pe-1 gap-1 align-items-center">
5
5
  Status
6
6
 
7
-
8
- <select class="form-control input-sm filter-operation" v-model="operator">
9
- <option v-for="option in operators" :value="option.id">
10
- {{option.title}}
11
- </option>
12
- </select>
7
+ <itf-select
8
+ class="mx-2"
9
+ v-model="operator"
10
+ simple
11
+ :reduce="(item) => item.id"
12
+ :get-option-label="(item) => item.title"
13
+ :options="operators"
14
+ >
15
+ <template #selected-option="{ option }">
16
+ <span class="sign-box"> {{option.sign || option.title}}</span>
17
+ </template>
18
+ <template #option="{ option }">
19
+ <span class="sign-box" v-if="option.sign"> {{option.sign}}</span>
20
+ {{option.title}}
21
+ </template>
22
+ <template #open-indicator><div></div></template>
23
+ </itf-select>
13
24
 
14
25
  <div>
15
- asda
26
+ <itf-select
27
+ simple
28
+ multiple
29
+ :get-option-label="(item) => item.title"
30
+ :options="[{ title:'text' }, { title:'text2' }]"
31
+ >
32
+ </itf-select>
16
33
  </div>
17
34
 
18
35
  <itf-button icon>
@@ -22,17 +39,15 @@
22
39
 
23
40
  </template>
24
41
  <style>
25
- .form-control.filter-operation {
26
- background: transparent;
27
- border: none;
28
- box-shadow: none;
29
- border-radius: 0;
30
-
31
- &:focus, &:active {
32
- box-shadow: none;
33
- outline: none;
34
- }
35
- &:hover {
42
+ .b-filter-badge {
43
+ padding: 1px;
44
+
45
+ .sign-box {
46
+ height: 24px;
47
+ text-align: center;
48
+ line-height: 22px;
49
+ width: 24px;
50
+ border-radius: 0.25rem;
36
51
  background-color: var(--bs-tertiary-bg);
37
52
  }
38
53
  }
@@ -41,6 +56,7 @@
41
56
  import { Component, Prop, Watch, Vue } from 'vue-property-decorator';
42
57
  import {getOperatorsByType} from "./constants";
43
58
  import itfButton from '../button/Button.vue';
59
+ import itfSelect from '../select/Select.vue';
44
60
  import itfIcon from '../icon/Icon.vue';
45
61
 
46
62
 
@@ -48,6 +64,7 @@ export default @Component({
48
64
  name: 'itfFilterBadge',
49
65
  components: {
50
66
  itfButton,
67
+ itfSelect,
51
68
  itfIcon
52
69
  }
53
70
  })
@@ -0,0 +1,105 @@
1
+ <template>
2
+
3
+
4
+ <div class="d-flex align-items-center">
5
+ <itf-text-field
6
+ style="width: 250px;"
7
+ prepend-icon="search"
8
+ placeholder="Search"
9
+ @change="onQueryChanged"
10
+ />
11
+
12
+ <itf-dropdown class="ms-3" :button-options="{ secondary: true }">
13
+ <template #button>
14
+ <itf-icon name="flip_view" class="me-1" />
15
+ Group
16
+ </template>
17
+
18
+ <div v-for="(filter, n) of filters" :key="n" class="dropdown-item">
19
+ <slot name="dropdown-item" :item="filter">{{filter.text}}</slot>
20
+ </div>
21
+ </itf-dropdown>
22
+
23
+ <template v-if="filters && filters.length">
24
+ <itf-dropdown class="mx-3" :button-options="{ secondary: true }">
25
+ <template #button>
26
+ <itf-icon name="filter" class="me-1" />
27
+ Filter
28
+ </template>
29
+
30
+ <div v-for="(filter, n) of filters" :key="n" class="dropdown-item">
31
+ <slot name="dropdown-item" :item="filter">{{filter.text}}</slot>
32
+ </div>
33
+ </itf-dropdown>
34
+
35
+ <div class="flex-grow-1">
36
+ <itf-filter-badge type="string" />
37
+ </div>
38
+ </template>
39
+ </div>
40
+
41
+ </template>
42
+ <style>
43
+ </style>
44
+ <script>
45
+ import { Component, Prop, Model, Vue, Watch } from 'vue-property-decorator';
46
+ import itfButton from '../button/Button.vue';
47
+ import itfTextField from '../text-field/TextField.vue';
48
+ import itfDropdown from '../dropdown/Dropdown.vue';
49
+ import itfIcon from '../icon/Icon.vue';
50
+ import itfFilterBadge from './FilterBadge.vue';
51
+
52
+ export default @Component({
53
+ name: 'itfFilterControl',
54
+ components: {
55
+ itfFilterBadge,
56
+ itfTextField,
57
+ itfDropdown,
58
+ itfButton,
59
+ itfIcon
60
+ }
61
+ })
62
+ class itfFilterControl extends Vue {
63
+ @Model('input') value;
64
+ @Prop({ type: String, default: 'query' }) queryField;
65
+ @Prop({ type: Array, default: () => ([]) }) filters;
66
+ @Prop(Boolean) urlSync;
67
+
68
+ mounted() {
69
+ if (this.urlSync) {
70
+ if (window.itfinUrlWatcher) {
71
+ throw new Error('urlSync component already exists');
72
+ }
73
+ window.itfinUrlWatcher = this;
74
+ }
75
+ }
76
+
77
+ @Watch('$route')
78
+ onRouteChange() {
79
+ const newValue = { ...(this.value || {}) };
80
+ const query = this.$route.query;
81
+ if (query) {
82
+ Object.keys(query).forEach((key) => {
83
+ newValue[key] = query[key];
84
+ });
85
+ }
86
+ this.$emit('input', newValue);
87
+ }
88
+
89
+ beforeDestroy() {
90
+ if (this.urlSync) {
91
+ window.itfinUrlWatcher = null;
92
+ }
93
+ }
94
+
95
+ onQueryChanged(value) {
96
+ const newValue = { ...(this.value || {}) };
97
+ newValue[this.queryField] = value;
98
+ if (this.urlSync) {
99
+ this.$router.push({ ...this.$route, query: newValue });
100
+ } else {
101
+ this.$emit('input', newValue);
102
+ }
103
+ }
104
+ }
105
+ </script>
@@ -5,12 +5,13 @@ export function getOperatorsByType(type) {
5
5
  {
6
6
  type: 'string',
7
7
  operators: [
8
- { id: 'eq', title: 'equal' },
9
- { id: 'notEq', title: 'not equal' },
10
- { id: 'contains', title: 'contains' },
11
- { id: 'noContains', title: 'not contains' },
12
- { id: 'startsWith', title: 'starts with' },
13
- { id: 'endsWith', title: 'ends with' }
8
+ { id: 'eq', title: 'equal', sign: '=' },
9
+ { id: 'notEq', title: 'not equal', sign: '≠' },
10
+ { id: 'contains', title: 'contains', sign: '∋' },
11
+ { id: 'noContains', title: 'not contains', sign: '∌' },
12
+ { id: 'startsWith', title: 'starts with', sign: 'A…' },
13
+ { id: 'endsWith', title: 'ends with', sign: '…Z' },
14
+ // { id: 'exists', title: 'exists', sign: '∃' }
14
15
  ]
15
16
  }
16
17
  ];
@@ -2,13 +2,15 @@ import { storiesOf } from '@storybook/vue';
2
2
  import itfRule from './Rule.vue';
3
3
  import itfRuleGroup from './RuleGroup.vue';
4
4
  import itfFilterBadge from './FilterBadge.vue';
5
+ import itfFilterControl from './FilterControl.vue';
5
6
 
6
7
  storiesOf('Common', module)
7
8
  .add('Filter', () => ({
8
9
  components: {
9
10
  itfRule,
10
11
  itfRuleGroup,
11
- itfFilterBadge
12
+ itfFilterBadge,
13
+ itfFilterControl
12
14
  },
13
15
  data() {
14
16
  return {
@@ -44,7 +46,22 @@ storiesOf('Common', module)
44
46
  dates: [],
45
47
  customDays: {
46
48
  '2021-10-21': { text: '🎉', class: 'test' }
47
- }
49
+ },
50
+ filter: {},
51
+ filterFields: [
52
+ {
53
+ type: 'list',
54
+ text: 'Status',
55
+ options: [
56
+ { title: 'Active', value: 'active' },
57
+ { title: 'Inactive', value: 'inactive' },
58
+ ]
59
+ },
60
+ {
61
+ type: 'employee',
62
+ text: 'Employee'
63
+ },
64
+ ]
48
65
  }
49
66
  },
50
67
  methods: {
@@ -65,8 +82,19 @@ storiesOf('Common', module)
65
82
  </pre>
66
83
 
67
84
 
68
- <itf-filter-badge type="string" />
85
+ <itf-filter-control url-sync v-model="filter" :filters="filterFields">
86
+ <template #dropdown-item="{ item }">
87
+ {{item.text}}
88
+ </template>
89
+ <template #item="{ item }">
90
+ {{item}}
91
+ </template>
92
+ <template #item="{ item }">
93
+ {{item}}
94
+ </template>
95
+ </itf-filter-control>
69
96
 
97
+ {{filter}}
70
98
 
71
99
  <h2>Example</h2>
72
100
 
@@ -4,8 +4,8 @@
4
4
  <div
5
5
  :id="`vs${uid}__combobox`"
6
6
  ref="toggle"
7
- :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
8
- class="vs__dropdown-toggle form-control"
7
+ :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess(), 'form-control': !simple }"
8
+ class="vs__dropdown-toggle"
9
9
  role="combobox"
10
10
  :aria-expanded="dropdownOpen.toString()"
11
11
  :aria-owns="`vs${uid}__listbox`"
@@ -212,6 +212,13 @@ export default {
212
212
  type: Boolean,
213
213
  default: false,
214
214
  },
215
+ /**
216
+ * Remove form-control class
217
+ */
218
+ simple: {
219
+ type: Boolean,
220
+ default: false,
221
+ },
215
222
  /**
216
223
  * Can the user deselect an option by clicking it from
217
224
  * within the dropdown.
@@ -1,5 +1,5 @@
1
1
  import Vue from 'vue';
2
- import { Draggable } from './draggable'
2
+ import { Draggable } from '@shopify/draggable';
3
3
  import DraggableEvent from './event'
4
4
 
5
5