@itfin/components 1.0.61 → 1.0.66

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itfin/components",
3
- "version": "1.0.61",
3
+ "version": "1.0.66",
4
4
  "main": "dist/itfin-components.umd.js",
5
5
  "unpkg": "dist/itfin-components.common.js",
6
6
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
@@ -1,7 +1,7 @@
1
1
  @import '../variables';
2
2
 
3
3
  /* Selected Tags */
4
- .vs__selected {
4
+ .vs__selected, .badge.vs__selected {
5
5
  display: flex;
6
6
  align-items: center;
7
7
  background-color: $vs-selected-bg;
@@ -1,5 +1,6 @@
1
1
  import Vue from 'vue';
2
2
  import ToastContainer from './ToastContainer.vue';
3
+
3
4
  const MessageConstructor = Vue.extend(ToastContainer);
4
5
 
5
6
  const instances = [];
@@ -19,8 +20,8 @@ const Message = function (options) {
19
20
  'itf-toast-container toast-container',
20
21
  'is-' + position,
21
22
  hasMask ? 'has-mask' : ''
22
- ].filter(function (e) { return !!e; }).join(' ');
23
- document.getElementById('itf-app').appendChild(containerEl);
23
+ ].filter(Boolean).join(' ');
24
+ document.body.appendChild(containerEl);
24
25
  }
25
26
 
26
27
  if (options.zIndex) {
@@ -2,9 +2,11 @@
2
2
 
3
3
  <div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
4
4
  <input class="form-check-input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
5
- <label :for="id" slot="label" class="form-check-label">
6
- {{label}}
7
- <slot name="icon"></slot>
5
+ <label :for="id" class="form-check-label">
6
+ <slot name="label">
7
+ {{label}}
8
+ <slot name="icon"></slot>
9
+ </slot>
8
10
  </label>
9
11
  </div>
10
12
 
@@ -121,8 +121,7 @@ class itfModal extends Vue {
121
121
  }
122
122
  if (this.appendToBody && this.$el instanceof Node && this.$el.parentNode) {
123
123
  this.$el.parentNode.removeChild(this.$el);
124
- const elContext = this.$el.closest('.itf-append-context') || document.body; // @todo getElementById remove when cleanup vuetify
125
- elContext.appendChild(this.$el);
124
+ document.body.appendChild(this.$el); // should append only to body
126
125
  }
127
126
  const { default: Modal } = await import('bootstrap/js/src/modal.js');
128
127
  this.modalEl = new Modal(this.$el);
@@ -1,18 +1,19 @@
1
1
  <template>
2
2
  <div class="itf-segmeneted-control">
3
- <span v-if="!isUndefined" class="selection" :class="{'elevation-1': !disabled}"></span>
3
+ <span v-if="!isUndefined" ref="slider" class="selection" :class="{'elevation-1': !disabled}"></span>
4
4
 
5
5
  <div class="option" v-for="(item, n) in itemsWithNames" :key="n">
6
6
  <label>
7
7
  <input
8
+ ref="input"
8
9
  type="radio"
9
10
  :name="name"
10
11
  :value="n"
11
12
  :checked="isChecked(item)"
12
13
  @change="onItemChanged(item)" />
13
14
  <span>
14
- <slot name="item" :item="item" :itemKey="n">{{item[itemText]}}</slot>
15
- </span>
15
+ <slot name="item" :item="item" :itemKey="n">{{item[itemText]}}</slot>
16
+ </span>
16
17
  </label>
17
18
  </div>
18
19
  </div>
@@ -203,32 +204,30 @@ class itfSegmentedControl extends Vue {
203
204
  }
204
205
 
205
206
  init() {
206
- const INDIVIDUAL_SEGMENT_SELECTOR = '.option input';
207
- const BACKGROUND_PILL_SELECTOR = '.selection';
207
+ this.$el.addEventListener('change', () => updatePillPosition(this));
208
+ //window.addEventListener('resize', () => updatePillPosition(this.$el)); // Prevent pill from detaching from element when window resized. Becuase this is rare I haven't bothered with throttling the event
208
209
 
209
- this.$el.addEventListener('change', () => updatePillPosition(this.$el));
210
- window.addEventListener('resize', () => updatePillPosition(this.$el)); // Prevent pill from detaching from element when window resized. Becuase this is rare I haven't bothered with throttling the event
210
+ updatePillPosition(this);
211
211
 
212
- updatePillPosition(this.$el);
213
-
214
- function updatePillPosition (el) {
215
- forEachElement(el, INDIVIDUAL_SEGMENT_SELECTOR, (elem, index) => {
212
+ function updatePillPosition (component) {
213
+ component.$refs.input.forEach((elem, index) => {
216
214
  if (elem.checked) {
217
- moveBackgroundPillToElement(el, elem, index);
215
+ component.$nextTick(() => moveBackgroundPillToElement(component, elem, index));
216
+ setTimeout(() => moveBackgroundPillToElement(component, elem, index), 500);
217
+ setTimeout(() => moveBackgroundPillToElement(component, elem, index), 750);
218
+ setTimeout(() => moveBackgroundPillToElement(component, elem, index), 1500);
219
+ setTimeout(() => moveBackgroundPillToElement(component, elem, index), 3000);
218
220
  }
219
221
  })
220
222
  }
221
223
 
222
- function moveBackgroundPillToElement (el, elem, index) {
223
- const slider = el.querySelector(BACKGROUND_PILL_SELECTOR);
224
+ function moveBackgroundPillToElement (component, elem, index) {
225
+ const slider = component.$refs.slider;
226
+ console.info('init 2', slider);
224
227
  if (slider) {
225
228
  slider.style.transform = 'translateX(' + (elem.offsetWidth * index) + 'px)';
226
229
  }
227
230
  }
228
-
229
- function forEachElement(el, className, fn) {
230
- Array.from(el.querySelectorAll(className)).forEach(fn);
231
- }
232
231
  }
233
232
 
234
233
  onItemChanged (item) {
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div class="itf-tab" :data-test="`itf-tab-${id}`" @click="tabsManager.setValue(id)" :class="{ 'active': tabsManager && tabsManager.getValue() === id }">
3
+ <span><slot /></span>
4
+ </div>
5
+ </template>
6
+ <style lang="scss" scoped>
7
+ .itf-tab {
8
+
9
+ }
10
+ </style>
11
+ <script>
12
+ import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
13
+
14
+ export default @Component({
15
+ name: 'itfTab',
16
+ components: {
17
+ }
18
+ })
19
+ class itfTab extends Vue {
20
+ @Inject() tabsManager;
21
+ @Prop() id;
22
+ }
23
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div v-show="tabsManager && tabsManager.getValue() === id" class="itf-tab-content" :data-test="`itf-tab-content-${id}`">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+ <style lang="scss" scoped>
7
+ .itf-tab-content {
8
+
9
+ }
10
+ </style>
11
+ <script>
12
+ import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
13
+
14
+ export default @Component({
15
+ name: 'itfTabContent',
16
+ components: {
17
+ }
18
+ })
19
+ class itfTabContent extends Vue {
20
+ @Inject({ default: null }) tabsManager;
21
+ @Prop() id;
22
+ }
23
+ </script>
@@ -0,0 +1,66 @@
1
+ <script>
2
+ import {
3
+ Vue, Component, Provide, Model, Emit,
4
+ } from 'vue-property-decorator';
5
+ import itfTab from './Tab';
6
+ import './tabs.scss';
7
+
8
+ export default @Component({
9
+ name: 'itfTabs',
10
+ components: {
11
+ itfTab
12
+ },
13
+ })
14
+ class itfTabs extends Vue {
15
+ @Provide() tabsManager = this;
16
+
17
+ @Model('input') value;
18
+
19
+ tabNodes;
20
+
21
+ render(createElement) {
22
+ const [tabNodes, contents] = parseNodes(this.$slots);
23
+ this.tabNodes = tabNodes;
24
+
25
+ return createElement('div', { staticClass: 'itf-tabs' }, [
26
+ createElement('div', { staticClass: 'itf-tabs-panel' }, tabNodes),
27
+ createElement('div', { staticClass: 'itf-tabs-content' }, contents)
28
+ ]);
29
+
30
+ function parseNodes(slots) {
31
+ const items = [];
32
+ const contents = [];
33
+ const nodes = (slots.default || []);
34
+
35
+ for (const vnode of nodes) {
36
+ if (!vnode.componentOptions) {
37
+ continue;
38
+ }
39
+ if (vnode.componentOptions.tag.includes('-tab-content')) {
40
+ contents.push(vnode);
41
+ continue;
42
+ }
43
+ if (vnode.componentOptions.tag.includes('-tab')) {
44
+ items.push(vnode);
45
+ }
46
+ }
47
+ return [items, contents];
48
+ }
49
+ }
50
+
51
+ @Emit('input')
52
+ setValue(value) {
53
+ this.tabNodes = null;
54
+ }
55
+
56
+ getValue() {
57
+ return this.value;
58
+ }
59
+
60
+ scrollToTop() {
61
+ this.$el.scrollIntoView({
62
+ behavior: 'smooth',
63
+ });
64
+ }
65
+ }
66
+ </script>
@@ -0,0 +1,60 @@
1
+ import { storiesOf } from '@storybook/vue';
2
+ import itfApp from '../app/App.vue';
3
+ import itfButton from '../button/Button.vue';
4
+ import itfTab from './Tab.vue';
5
+ import itfTabContent from './TabContent.vue';
6
+ import itfTabs from './Tabs.vue';
7
+ import itfLabel from '../form/Label.vue';
8
+ import itfDatePicker from '../datepicker/DatePicker.vue';
9
+ import itfDateRangePicker from '../datepicker/DateRangePicker.vue';
10
+
11
+ storiesOf('Common', module)
12
+ .add('Tabs', () => ({
13
+ components: {
14
+ itfApp,
15
+ itfTabs,
16
+ itfLabel,
17
+ itfDatePicker,
18
+ itfDateRangePicker,
19
+ itfTab,
20
+ itfTabContent,
21
+ itfButton
22
+ },
23
+ data() {
24
+ return {
25
+ tab: 'Test1'
26
+ }
27
+ },
28
+ methods: {
29
+ },
30
+ template: `<div>
31
+ <p>You need wrap whole application with this tag</p>
32
+
33
+ <h2>Usage</h2>
34
+ {{tab}}
35
+ <pre>
36
+ &lt;itf-tabs v-model="tab">
37
+ &lt;itf-tab id="Test1">
38
+ asd
39
+ </itf-tab>
40
+ &lt;/itf-tabs>
41
+ </pre>
42
+
43
+ <h3>Example</h3>
44
+
45
+ <itf-tabs v-model="tab">
46
+ <itf-tab id="Test1">
47
+ Content 1
48
+ </itf-tab>
49
+ <itf-tab id="Test2">
50
+ Content 2
51
+ </itf-tab>
52
+ <itf-tab-content id="Test1">
53
+ asd
54
+ </itf-tab-content>
55
+ <itf-tab-content id="Test2">
56
+ asd123
57
+ </itf-tab-content>
58
+ </itf-tabs>
59
+ </div>`,
60
+ }));
@@ -0,0 +1,90 @@
1
+ @import '../../assets/scss/variables';
2
+ @import '~bootstrap/scss/grid';
3
+ @import '~bootstrap/scss/containers';
4
+
5
+ :root {
6
+ --itf-tabs-active-bg: #fff;
7
+ --itf-tabs-active-color: #222;
8
+ --itf-tabs-active-border-color: #ffb20fc2;
9
+ --itf-tabs-inactive-bg: #fafafa;
10
+ --itf-tabs-inactive-color: #222;
11
+ --itf-tabs-inactive-border-color: rgba(0, 0, 0, .1);
12
+ --itf-tabs-hover-bg: #F4F7F9;
13
+ --itf-tabs-hover-color: #222;
14
+ --itf-tabs-hover-border-color: rgba(0, 0, 0, .5);
15
+ --itf-tabs-tab-padding: 10px;
16
+ }
17
+
18
+ .itf-tabs {
19
+ .itf-tabs-panel {
20
+ margin: 0px;
21
+ padding: 0px;
22
+ overflow: hidden;
23
+ padding-left: calc(var(--itf-tabs-tab-padding) * 2.1);
24
+ list-style-type: none;
25
+ display: flex;
26
+
27
+ .itf-tab {
28
+ display: block;
29
+ //float: right;
30
+ padding: 10px var(--itf-tabs-tab-padding) 8px;
31
+ margin-right: calc(var(--itf-tabs-tab-padding) * 3);
32
+ z-index: 2;
33
+ position: relative;
34
+ cursor: pointer;
35
+ transition: all 250ms ease;
36
+ border-radius: 8px 8px 0 0;
37
+ background-color: var(--itf-tabs-inactive-bg);
38
+ color: var(--itf-tabs-inactive-color);
39
+ border-top: 1px solid var(--itf-tabs-inactive-border-color);
40
+
41
+ & > span {
42
+ position: relative;
43
+ z-index: 4;
44
+ }
45
+ &:before, &:after {
46
+ display: block;
47
+ content: " ";
48
+ position: absolute;
49
+ top: -1px;
50
+ height: calc(100% + 1px);
51
+ width: calc(var(--itf-tabs-tab-padding) * 5);
52
+ background-color: var(--itf-tabs-inactive-bg);
53
+ color: var(--itf-tabs-inactive-color);
54
+ border-top: 1px solid var(--itf-tabs-inactive-border-color);
55
+ transition: all 250ms ease;
56
+ }
57
+ &:before {
58
+ right: calc(var(--itf-tabs-tab-padding) * -2);
59
+ border-radius: 0 8px 0 0;
60
+ transform: skew(30deg, 0deg);
61
+ box-shadow: rgba(0,0,0,.1) 3px 2px 5px, inset rgba(255,255,255,.09) -1px 0;
62
+ }
63
+ &:after {
64
+ left: calc(var(--itf-tabs-tab-padding) * -2);
65
+ border-radius: 8px 0 0 0;
66
+ //transform: skew(-30deg, 0deg);
67
+ box-shadow: rgba(0,0,0,.1) -3px 2px 5px, inset rgba(255,255,255,.09) 1px 0;
68
+ }
69
+ &:hover, &:hover:before, &:hover:after {
70
+ background-color: var(--itf-tabs-hover-bg);
71
+ color: var(--itf-tabs-hover-color);
72
+ border-top: 1px solid var(--itf-tabs-hover-border-color);
73
+ }
74
+ &.active {
75
+ z-index: 3;
76
+
77
+ &, &:before, &:after {
78
+ background-color: var(--itf-tabs-active-bg);
79
+ color: var(--itf-tabs-active-color);
80
+ border-top: 1px solid var(--itf-tabs-active-border-color);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ .itf-tabs-content {
86
+ .itf-tab-content {
87
+
88
+ }
89
+ }
90
+ }
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
 
3
3
  <div class="itf-text-field input-group" :class="{ 'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable }">
4
- <div class="addon" v-if="prependIcon">
4
+ <div class="addon" v-if="prependIcon || $slots.addon">
5
5
  <slot name="addon">
6
6
  <itf-icon :name="prependIcon"/>
7
7
  </slot>
@@ -13,12 +13,19 @@
13
13
  :placeholder="placeholder"
14
14
  :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
15
15
  class="itf-text-field__input form-control"
16
- type="text"
16
+ :type="type"
17
17
  :value="value"
18
18
  :disabled="disabled"
19
19
  :readonly="readonly"
20
20
  @input="onInput($event.target.value)"
21
21
  @keydown="$emit('keydown', $event)"
22
+ @keyup="$emit('keyup', $event)"
23
+ @keypress="$emit('keypress', $event)"
24
+ @blur="$emit('blur', $event)"
25
+ @focus="$emit('focus', $event)"
26
+ :min="min"
27
+ :max="max"
28
+ :step="step"
22
29
  />
23
30
 
24
31
  <div class="addon-end" v-if="clearable && value">
@@ -68,9 +75,13 @@ class itfTextField extends Vue {
68
75
  @Model('input') value;
69
76
  @Prop(String) prependIcon;
70
77
  @Prop(String) placeholder;
78
+ @Prop() step;
79
+ @Prop() min;
80
+ @Prop() max;
71
81
  @Prop(Boolean) clearable;
72
82
  @Prop(Boolean) disabled;
73
83
  @Prop(Boolean) readonly;
84
+ @Prop({ type: String, default: 'text' }) type;
74
85
  @Prop({ type: [Number, String], default: 0 }) delayInput;
75
86
 
76
87
  onInput = null;
@@ -94,5 +105,13 @@ class itfTextField extends Vue {
94
105
  const endText = value.slice(position);
95
106
  this.$emit('input', `${startText}${text}${endText}`);
96
107
  }
108
+
109
+ focus() {
110
+ this.$refs.input.focus();
111
+ }
112
+
113
+ blur() {
114
+ this.$refs.input.blur();
115
+ }
97
116
  }
98
117
  </script>
@@ -18,6 +18,10 @@
18
18
  :value="value"
19
19
  @input="onInput($event.target.value)"
20
20
  @keydown="$emit('keydown', $event)"
21
+ @keyup="$emit('keyup', $event)"
22
+ @keypress="$emit('keypress', $event)"
23
+ @blur="$emit('blur', $event)"
24
+ @focus="$emit('focus', $event)"
21
25
  />
22
26
  </div>
23
27
 
@@ -95,5 +99,13 @@ class itfTextarea extends Vue {
95
99
  const endText = value.slice(position);
96
100
  this.$emit('input', `${startText}${text}${endText}`);
97
101
  }
102
+
103
+ focus() {
104
+ this.$refs.input.focus();
105
+ }
106
+
107
+ blur() {
108
+ this.$refs.input.blur();
109
+ }
98
110
  }
99
111
  </script>
@@ -1,54 +1,19 @@
1
1
  <template>
2
2
 
3
- <div class="eo-tabset breadcrumbs">
3
+ <div class="py-3 px-2">
4
4
 
5
- <ul class="nav nav-pills flex-column mb-auto">
6
- <li class="nav-item">
7
- <a href="#" class="nav-link active" aria-current="page">
8
- <svg class="bi me-2" width="16" height="16"><use xlink:href="#home"></use></svg>
9
- Home
10
- </a>
11
- </li>
12
- <li>
13
- <a href="#" class="nav-link link-dark">
14
- <svg class="bi me-2" width="16" height="16"><use xlink:href="#speedometer2"></use></svg>
15
- Dashboard
16
- </a>
17
- </li>
18
- <li>
19
- <a href="#" class="nav-link link-dark">
20
- <svg class="bi me-2" width="16" height="16"><use xlink:href="#table"></use></svg>
21
- Orders
22
- </a>
23
- </li>
24
- <li>
25
- <a href="#" class="nav-link link-dark">
26
- <svg class="bi me-2" width="16" height="16"><use xlink:href="#grid"></use></svg>
27
- Products
28
- </a>
29
- </li>
30
- <li>
31
- <a href="#" class="nav-link link-dark">
32
- <svg class="bi me-2" width="16" height="16"><use xlink:href="#people-circle"></use></svg>
33
- Customers
34
- </a>
35
- </li>
36
- </ul>
37
-
38
- <ul class="nav nav-pills nav-stacked" data-test="step-sidebar">
5
+ <ul class="nav nav-pills flex-column mb-auto ps-0" data-test="step-sidebar">
39
6
 
40
7
  <li v-for="(step, n) in sidebarItems" :class="{ active: selectedId === step.id, disabled: selectedId !== step.id }"
41
8
  :data-test="'step-sidebar-' + step.id">
42
- <strong v-if="selectedId !== step.id && value.indexOf(step.id) !== -1">
43
- <span aria-hidden="true" class="glyphicon m-0-left" :class="'air-icon-' + step['sidebar-icon']"></span>
9
+ <strong v-if="selectedId !== step.id && value.includes(step.id)" class="nav-link text-success">
10
+ <itf-icon :name="step['sidebar-icon'] || 'check_circle'"></itf-icon>
44
11
  {{step['sidebar-title']}}
45
12
  </strong>
46
- <a href="" v-else @click.prevent="">
47
- <span aria-hidden="true" class="glyphicon m-0-left" :class="'air-icon-' + step['sidebar-icon']"></span>
13
+ <a href="" v-else @click.prevent="" class="nav-link">
14
+ <itf-icon :name="step['sidebar-icon'] || 'circle'"></itf-icon>
48
15
  {{step['sidebar-title']}}
49
16
  </a>
50
- <span aria-hidden="true" class="completed-icon glyphicon air-icon-verified"
51
- :class="{ 'completed': value.indexOf(step.id) !== -1 }"></span>
52
17
  </li>
53
18
  </ul>
54
19
 
@@ -56,50 +21,18 @@
56
21
 
57
22
  </template>
58
23
  <style lang="scss">
59
- .itf-wizard-sidebar {
60
- .eo-tabset.breadcrumbs {
61
- .completed-icon {
62
- position: absolute;
63
- right: 0;
64
- top: 0;
65
- height: 100%;
66
- display: flex;
67
- align-items: center;
68
- //color: $gray-light;
69
-
70
- &.completed {
71
- //color: $brand-primary;
72
- }
73
- }
74
-
75
- li.active > a {
76
- //box-shadow: $drop-shadow-darker;
77
- }
78
-
79
- li > a {
80
- .glyphicon {
81
- margin: 0 10px 0 0;
82
- font-size: 14px;
83
- }
84
- }
85
-
86
- li > strong {
87
- display: block;
88
- padding: 9px 20px;
89
-
90
- .glyphicon {
91
- margin: 0 10px 0 0;
92
- }
93
- }
94
- }
95
- }
24
+ .itf-wizard-sidebar {
25
+ }
96
26
  </style>
97
27
  <script>
98
28
  import { Vue, Component, Prop } from 'vue-property-decorator';
29
+ import itfIcon from '../icon/Icon';
99
30
 
100
31
  export default @Component({
101
32
  name: 'itfWizardSidebar',
102
- components: {},
33
+ components: {
34
+ itfIcon
35
+ },
103
36
  })
104
37
  class itfWizardSidebar extends Vue {
105
38
  @Prop(Array) steps;
@@ -108,19 +108,19 @@ class itfWizard extends Vue {
108
108
  }
109
109
 
110
110
  return createElement('div', { staticClass: 'itf-wizard row gx-0' }, [
111
- isSidebarNeeded ? createElement('div', { staticClass: 'col-md-4 d-none d-md-block itf-wizard-sidebar' }, [
111
+ isSidebarNeeded ? createElement('div', { staticClass: 'col-md-3 d-none d-md-flex' }, [
112
112
  createSidebar({
113
113
  value: (this.value || {}).completed || [],
114
114
  steps: this.stepsNodes,
115
115
  selectedId: this.currentSidebarId,
116
116
  }),
117
117
  ]) : null,
118
- createElement('div', { staticClass: isSidebarNeeded ? 'col-md-8 itf-wizard-step' : 'col-xs-12 itf-wizard-step' }, [node])
118
+ createElement('div', { staticClass: isSidebarNeeded ? 'col-md-9 itf-wizard-step' : 'col-xs-12 itf-wizard-step' }, [node])
119
119
  ]);
120
120
 
121
121
  function createSidebar(props) {
122
122
  return createElement('itf-wizard-sidebar', {
123
- staticClass: '',
123
+ staticClass: 'itf-wizard-sidebar w-100',
124
124
  props,
125
125
  });
126
126
  }
@@ -0,0 +1,113 @@
1
+ // modified copy of https://github.com/vuejs/vue-loader/blob/master/lib/runtime/componentNormalizer.js
2
+ // contains code to inject styles from options.injectStyles
3
+
4
+ /* eslint-disable */
5
+ /* globals __VUE_SSR_CONTEXT__ */
6
+
7
+ // IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
8
+ // This module is a runtime utility for cleaner component module output and will
9
+ // be included in the final webpack user bundle.
10
+
11
+ export default function normalizeComponent (
12
+ scriptExports,
13
+ render,
14
+ staticRenderFns,
15
+ functionalTemplate,
16
+ injectStyles,
17
+ scopeId,
18
+ moduleIdentifier, /* server only */
19
+ shadowMode /* vue-cli only */
20
+ ) {
21
+ // Vue.extend constructor export interop
22
+ var options = typeof scriptExports === 'function'
23
+ ? scriptExports.options
24
+ : scriptExports
25
+
26
+
27
+ // render functions
28
+ if (render) {
29
+ options.render = render
30
+ options.staticRenderFns = staticRenderFns
31
+ options._compiled = true
32
+ }
33
+
34
+ // functional template
35
+ if (functionalTemplate) {
36
+ options.functional = true
37
+ }
38
+
39
+ // scopedId
40
+ if (scopeId) {
41
+ options._scopeId = 'data-v-' + scopeId
42
+ }
43
+
44
+ var hook
45
+ if (moduleIdentifier) { // server build
46
+ hook = function (context) {
47
+ // 2.3 injection
48
+ context =
49
+ context || // cached call
50
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
51
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
52
+ // 2.2 with runInNewContext: true
53
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
54
+ context = __VUE_SSR_CONTEXT__
55
+ }
56
+ // modification start
57
+ if (Array.isArray(options.injectStyles)) {
58
+ options.injectStyles.forEach((style) => {
59
+ if (style.__inject__) { // eslint-disable-line no-underscore-dangle
60
+ style.__inject__(context); // eslint-disable-line no-underscore-dangle
61
+ }
62
+ });
63
+ }
64
+ // modification end
65
+
66
+ // inject component styles
67
+ if (injectStyles) {
68
+ injectStyles.call(this, context)
69
+ }
70
+ // register component module identifier for async chunk inferrence
71
+ if (context && context._registeredComponents) {
72
+ context._registeredComponents.add(moduleIdentifier)
73
+ }
74
+ }
75
+ // used by ssr in case component is cached and beforeCreate
76
+ // never gets called
77
+ options._ssrRegister = hook
78
+ } else if (injectStyles) {
79
+ hook = shadowMode
80
+ ? function () {
81
+ injectStyles.call(
82
+ this,
83
+ (options.functional ? this.parent : this).$root.$options.shadowRoot
84
+ )
85
+ }
86
+ : injectStyles
87
+ }
88
+
89
+ if (hook) {
90
+ if (options.functional) {
91
+ // for template-only hot-reload because in that case the render fn doesn't
92
+ // go through the normalizer
93
+ options._injectStyles = hook
94
+ // register for functional component in vue file
95
+ var originalRender = options.render
96
+ options.render = function renderWithStyleInjection (h, context) {
97
+ hook.call(context)
98
+ return originalRender(h, context)
99
+ }
100
+ } else {
101
+ // inject component registration as beforeCreate hook
102
+ var existing = options.beforeCreate
103
+ options.beforeCreate = existing
104
+ ? [].concat(existing, hook)
105
+ : [hook]
106
+ }
107
+ }
108
+
109
+ return {
110
+ exports: scriptExports,
111
+ options: options
112
+ }
113
+ }
@@ -0,0 +1,9 @@
1
+ import webpack from 'webpack';
2
+ import path from 'path';
3
+
4
+ export default function extend(config) {
5
+ config.plugins.push(new webpack.NormalModuleReplacementPlugin(
6
+ /vue-loader\/lib\/runtime\/componentNormalizer.js/,
7
+ path.join(__dirname, 'componentNormalizer.js'),
8
+ ));
9
+ };