@gorse/shards-vue 1.0.8

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 (173) hide show
  1. package/.editorconfig +13 -0
  2. package/CHANGELOG.md +49 -0
  3. package/CONTRIBUTING.md +92 -0
  4. package/ISSUE_TEMPLATE.md +19 -0
  5. package/LICENSE +21 -0
  6. package/README.md +157 -0
  7. package/build/optimize.js +49 -0
  8. package/build/paths.js +12 -0
  9. package/build/rollup.config.js +106 -0
  10. package/dist/shards-vue.common.js +13994 -0
  11. package/dist/shards-vue.common.js.map +1 -0
  12. package/dist/shards-vue.common.min.js +1 -0
  13. package/dist/shards-vue.common.min.map +1 -0
  14. package/dist/shards-vue.esm.js +13990 -0
  15. package/dist/shards-vue.esm.js.map +1 -0
  16. package/dist/shards-vue.esm.min.js +1 -0
  17. package/dist/shards-vue.esm.min.map +1 -0
  18. package/dist/shards-vue.umd.js +13997 -0
  19. package/dist/shards-vue.umd.js.map +1 -0
  20. package/dist/shards-vue.umd.min.js +1 -0
  21. package/dist/shards-vue.umd.min.map +1 -0
  22. package/logo.jpg +0 -0
  23. package/package.json +121 -0
  24. package/sandbox/Sandbox.vue +45 -0
  25. package/src/components/alert/Alert.vue +156 -0
  26. package/src/components/alert/README.md +86 -0
  27. package/src/components/alert/index.js +17 -0
  28. package/src/components/badge/Badge.vue +62 -0
  29. package/src/components/badge/README.md +112 -0
  30. package/src/components/badge/index.js +17 -0
  31. package/src/components/breadcrumb/Breadcrumb.vue +55 -0
  32. package/src/components/breadcrumb/BreadcrumbItem.vue +42 -0
  33. package/src/components/breadcrumb/BreadcrumbLink.vue +56 -0
  34. package/src/components/breadcrumb/README.md +53 -0
  35. package/src/components/breadcrumb/index.js +23 -0
  36. package/src/components/button/Button.vue +107 -0
  37. package/src/components/button/ButtonClose.vue +47 -0
  38. package/src/components/button/README.md +197 -0
  39. package/src/components/button/index.js +21 -0
  40. package/src/components/button-group/ButtonGroup.vue +66 -0
  41. package/src/components/button-group/README.md +72 -0
  42. package/src/components/button-group/index.js +18 -0
  43. package/src/components/button-toolbar/ButtonToolbar.vue +29 -0
  44. package/src/components/button-toolbar/README.md +24 -0
  45. package/src/components/button-toolbar/index.js +18 -0
  46. package/src/components/card/Card.vue +57 -0
  47. package/src/components/card/CardBody.vue +92 -0
  48. package/src/components/card/CardFooter.vue +61 -0
  49. package/src/components/card/CardGroup.vue +47 -0
  50. package/src/components/card/CardHeader.vue +61 -0
  51. package/src/components/card/CardImg.vue +64 -0
  52. package/src/components/card/README.md +96 -0
  53. package/src/components/card/index.js +27 -0
  54. package/src/components/collapse/Collapse.vue +209 -0
  55. package/src/components/collapse/README.md +86 -0
  56. package/src/components/collapse/index.js +17 -0
  57. package/src/components/container/Col.vue +125 -0
  58. package/src/components/container/Container.vue +31 -0
  59. package/src/components/container/README.md +91 -0
  60. package/src/components/container/Row.vue +64 -0
  61. package/src/components/container/index.js +21 -0
  62. package/src/components/datepicker/Datepicker.vue +391 -0
  63. package/src/components/datepicker/README.md +185 -0
  64. package/src/components/datepicker/index.js +17 -0
  65. package/src/components/dropdown/Dropdown.vue +442 -0
  66. package/src/components/dropdown/DropdownDivider.vue +22 -0
  67. package/src/components/dropdown/DropdownHeader.vue +29 -0
  68. package/src/components/dropdown/DropdownItem.vue +25 -0
  69. package/src/components/dropdown/README.md +177 -0
  70. package/src/components/dropdown/index.js +23 -0
  71. package/src/components/embed/Embed.vue +47 -0
  72. package/src/components/embed/README.md +23 -0
  73. package/src/components/embed/index.js +17 -0
  74. package/src/components/form/Form.vue +40 -0
  75. package/src/components/form/FormFeedback.vue +39 -0
  76. package/src/components/form/FormInvalidFeedback.vue +39 -0
  77. package/src/components/form/FormRow.vue +21 -0
  78. package/src/components/form/FormText.vue +41 -0
  79. package/src/components/form/FormValidFeedback.vue +39 -0
  80. package/src/components/form/README.md +84 -0
  81. package/src/components/form/index.js +29 -0
  82. package/src/components/form-checkbox/FormCheckbox.vue +200 -0
  83. package/src/components/form-checkbox/README.md +131 -0
  84. package/src/components/form-checkbox/index.js +18 -0
  85. package/src/components/form-input/FormInput.vue +176 -0
  86. package/src/components/form-input/README.md +110 -0
  87. package/src/components/form-input/index.js +18 -0
  88. package/src/components/form-radio/FormRadio.vue +155 -0
  89. package/src/components/form-radio/README.md +61 -0
  90. package/src/components/form-radio/index.js +18 -0
  91. package/src/components/form-select/FormSelect.vue +246 -0
  92. package/src/components/form-select/README.md +180 -0
  93. package/src/components/form-select/index.js +18 -0
  94. package/src/components/form-textarea/FormTextarea.vue +250 -0
  95. package/src/components/form-textarea/README.md +74 -0
  96. package/src/components/form-textarea/index.js +18 -0
  97. package/src/components/image/Image.vue +123 -0
  98. package/src/components/image/README.md +32 -0
  99. package/src/components/image/index.js +18 -0
  100. package/src/components/index.js +63 -0
  101. package/src/components/input-group/InputGroup.vue +125 -0
  102. package/src/components/input-group/InputGroupAddon.vue +58 -0
  103. package/src/components/input-group/InputGroupText.vue +20 -0
  104. package/src/components/input-group/README.md +188 -0
  105. package/src/components/input-group/index.js +21 -0
  106. package/src/components/link/Link.vue +157 -0
  107. package/src/components/link/README.md +27 -0
  108. package/src/components/link/create-link-props.js +54 -0
  109. package/src/components/link/index.js +17 -0
  110. package/src/components/list-group/ListGroup.vue +30 -0
  111. package/src/components/list-group/ListGroupItem.vue +90 -0
  112. package/src/components/list-group/README.md +23 -0
  113. package/src/components/list-group/index.js +19 -0
  114. package/src/components/modal/Modal.vue +121 -0
  115. package/src/components/modal/ModalBody.vue +20 -0
  116. package/src/components/modal/ModalFooter.vue +21 -0
  117. package/src/components/modal/ModalHeader.vue +39 -0
  118. package/src/components/modal/ModalTitle.vue +21 -0
  119. package/src/components/modal/README.md +74 -0
  120. package/src/components/modal/index.js +25 -0
  121. package/src/components/nav/Nav.vue +62 -0
  122. package/src/components/nav/NavItem.vue +23 -0
  123. package/src/components/nav/NavText.vue +21 -0
  124. package/src/components/nav/README.md +94 -0
  125. package/src/components/nav/index.js +19 -0
  126. package/src/components/navbar/Navbar.vue +63 -0
  127. package/src/components/navbar/NavbarBrand.vue +41 -0
  128. package/src/components/navbar/NavbarNav.vue +38 -0
  129. package/src/components/navbar/NavbarToggle.vue +55 -0
  130. package/src/components/navbar/README.md +51 -0
  131. package/src/components/navbar/index.js +23 -0
  132. package/src/components/popover/Popover.vue +126 -0
  133. package/src/components/popover/README.md +73 -0
  134. package/src/components/popover/index.js +17 -0
  135. package/src/components/progress/Progress.vue +93 -0
  136. package/src/components/progress/ProgressBar.vue +123 -0
  137. package/src/components/progress/README.md +95 -0
  138. package/src/components/progress/index.js +19 -0
  139. package/src/components/slider/README.md +120 -0
  140. package/src/components/slider/Slider.vue +103 -0
  141. package/src/components/slider/index.js +17 -0
  142. package/src/components/tabs/README.md +111 -0
  143. package/src/components/tabs/Tab.vue +132 -0
  144. package/src/components/tabs/Tabs.vue +290 -0
  145. package/src/components/tabs/_TabButton.vue +130 -0
  146. package/src/components/tabs/index.js +19 -0
  147. package/src/components/tooltip/README.md +70 -0
  148. package/src/components/tooltip/Tooltip.vue +115 -0
  149. package/src/components/tooltip/index.js +17 -0
  150. package/src/directives/index.js +7 -0
  151. package/src/directives/toggle/index.js +16 -0
  152. package/src/directives/toggle/toggle.js +45 -0
  153. package/src/directives/tooltip/README.md +42 -0
  154. package/src/directives/tooltip/index.js +16 -0
  155. package/src/directives/tooltip/meta.json +5 -0
  156. package/src/directives/tooltip/tooltip.js +145 -0
  157. package/src/index.js +27 -0
  158. package/src/markdown/getting-started/README.md +80 -0
  159. package/src/markdown/getting-started/meta.json +4 -0
  160. package/src/markdown/roadmap/README.md +3 -0
  161. package/src/markdown/roadmap/meta.json +4 -0
  162. package/src/mixins/checkbox-radio.mixin.js +73 -0
  163. package/src/mixins/root-listener.mixin.js +32 -0
  164. package/src/mixins/tooltip-popover.mixin.js +292 -0
  165. package/src/scripts/utils.js +18 -0
  166. package/src/utils/constants.js +191 -0
  167. package/src/utils/events.js +48 -0
  168. package/src/utils/index.js +251 -0
  169. package/src/utils/observer.js +56 -0
  170. package/src/utils/popover.class.js +91 -0
  171. package/src/utils/target.js +50 -0
  172. package/src/utils/tooltip.class.js +60 -0
  173. package/src/utils/tpmanager.class.js +730 -0
@@ -0,0 +1,246 @@
1
+ <template>
2
+ <select ref="input"
3
+ :class="[
4
+ 'form-control',
5
+ stateClass,
6
+ size ? `form-control-${size}` : null,
7
+ !multiple && selectSize > 1 ? null : 'custom-select'
8
+ ]"
9
+ v-model="localValue"
10
+ :id="computedID"
11
+ :name="name"
12
+ :multiple="multiple || null"
13
+ :size="(multiple || selectSize > 1) ? selectSize : null"
14
+ :disabled="disabled"
15
+ :required="required"
16
+ :aria-required="required ? true : null"
17
+ :aria-invalid="computedAriaInvalid"
18
+ @change="handleChange" >
19
+ <option v-for="(option, idx) in formOptions"
20
+ :key="`dr-opt-${idx}`"
21
+ :value="option.value"
22
+ :disabled="Boolean(option.disabled)">
23
+ {{ option.text }}
24
+ </option>
25
+ <slot />
26
+ </select>
27
+ </template>
28
+
29
+ <script>
30
+ import { guid } from '../../utils'
31
+
32
+ export default {
33
+ name: 'd-form-select',
34
+ props: {
35
+ /**
36
+ * The element ID.
37
+ */
38
+ id: {
39
+ type: String,
40
+ default: null
41
+ },
42
+ /**
43
+ * The element name.
44
+ */
45
+ name: {
46
+ type: String
47
+ },
48
+ /**
49
+ * The select options.
50
+ */
51
+ options: {
52
+ type: [Array, Object],
53
+ default() {
54
+ return []
55
+ }
56
+ },
57
+ /**
58
+ * The select value.
59
+ */
60
+ value: {},
61
+ /**
62
+ * Whether it should allow multiple selections, or not.
63
+ */
64
+ multiple: {
65
+ type: Boolean,
66
+ default: false
67
+ },
68
+ /**
69
+ * How many options should be visible.
70
+ */
71
+ selectSize: {
72
+ type: Number,
73
+ default: 0
74
+ },
75
+ /**
76
+ * Controls the `aria-invalid` attribute.
77
+ */
78
+ ariaInvalid: {
79
+ type: [Boolean, String],
80
+ default: false
81
+ },
82
+ /**
83
+ * The value field.
84
+ */
85
+ valueField: {
86
+ type: String,
87
+ default: 'value'
88
+ },
89
+ /**
90
+ * The disabled field.
91
+ */
92
+ disabledField: {
93
+ type: String,
94
+ default: 'disabled'
95
+ },
96
+ /**
97
+ * The text field.
98
+ */
99
+ textField: {
100
+ type: String,
101
+ default: 'text'
102
+ },
103
+ /**
104
+ * The disabled state.
105
+ */
106
+ disabled: {
107
+ type: Boolean,
108
+ default: false
109
+ },
110
+ /**
111
+ * The required state.
112
+ */
113
+ required: {
114
+ type: Boolean,
115
+ default: false
116
+ },
117
+ /**
118
+ * The validity state (invalid, valid, true, false).
119
+ */
120
+ state: {
121
+ type: [Boolean, String],
122
+ default: null,
123
+ validator: v => ['valid', 'invalid', true, false, null].includes(v)
124
+ },
125
+ /**
126
+ * The form control size (sm, lg).
127
+ */
128
+ size: {
129
+ type: String,
130
+ default: null,
131
+ validator: v => ['sm', 'lg', null].includes(v)
132
+ }
133
+ },
134
+ data() {
135
+ return {
136
+ localValue: this.value
137
+ }
138
+ },
139
+ watch: {
140
+ value(newVal) {
141
+ this.localValue = newVal
142
+ },
143
+
144
+ localValue() {
145
+ this.$emit('input', this.localValue)
146
+ }
147
+ },
148
+ computed: {
149
+ computedID() {
150
+ return this.id || `dr-select-${guid()}`
151
+ },
152
+
153
+ computedState() {
154
+ if (this.state === true || this.state === 'valid') {
155
+ return true
156
+ }
157
+
158
+ if (this.state === false || this.state === 'invalid') {
159
+ return false
160
+ }
161
+
162
+ return null
163
+ },
164
+
165
+ stateClass() {
166
+ if (this.computedState === true) {
167
+ return 'is-valid'
168
+ } else if (this.computedState === false) {
169
+ return 'is-invalid'
170
+ }
171
+
172
+ return null
173
+ },
174
+
175
+ computedAriaInvalid() {
176
+ if (this.ariaInvalid === true || this.ariaInvalid === 'true') {
177
+ return 'true';
178
+ }
179
+
180
+ return this.stateClass == 'is-invalid' ? 'true' : null;
181
+ },
182
+
183
+ formOptions() {
184
+ let options = this.options || {}
185
+ const valueField = this.valueField || 'value'
186
+ const textField = this.textField || 'text'
187
+ const disabledField = this.disabledField || 'disabled'
188
+
189
+ // Parse array options
190
+ if (Array.isArray(options)) {
191
+ return options.map(option => {
192
+ if (typeof option === 'object') {
193
+ return {
194
+ value: option[valueField],
195
+ text: String(option[textField]),
196
+ disabled: option[disabledField] || false
197
+ }
198
+ }
199
+
200
+ return { text: String(option), value: option, disabled: false }
201
+ })
202
+
203
+ // Parse object options
204
+ } else if (typeof options === 'object') {
205
+ return Object.keys(options).map(key => {
206
+ let option = options[key] || {}
207
+
208
+ if (typeof option === 'object') {
209
+ const value = option[valueField]
210
+ const text = option[textField]
211
+
212
+ return {
213
+ text: typeof text === 'undefined' ? key : String(text),
214
+ value: typeof value === 'undefined' ? key : value,
215
+ disabled: option[disabledField] || false
216
+ }
217
+ }
218
+
219
+ return { text: String(option), value: key, disabled: false }
220
+ })
221
+ }
222
+
223
+ return []
224
+ }
225
+ },
226
+ methods: {
227
+ handleChange(evt) {
228
+ const target = evt.target;
229
+ const selectedVal = Array.from(target.options)
230
+ .filter(opt => opt.selected)
231
+ .map(opt => '_value' in opt ? opt._value : opt.value)
232
+
233
+ this.localValue = target.multiple ? selectedVal : selectedVal[0];
234
+ this.$emit('change', this.localValue);
235
+ }
236
+ }
237
+ }
238
+ </script>
239
+
240
+ <style scoped>
241
+ .custom-select {
242
+ -webkit-appearance: none;
243
+ -moz-appearance: none;
244
+ appearance: none;
245
+ }
246
+ </style>
@@ -0,0 +1,180 @@
1
+ # Form Select
2
+
3
+ The `<d-form-select>` component is a wrapper over Bootstrap's [custom select component](https://getbootstrap.com/docs/4.1/components/forms/#select-menu).
4
+
5
+ ## Alias
6
+
7
+ The `<d-form-select>` component is also available as `<d-select>`.
8
+
9
+ ## Basic Examples
10
+
11
+ The easiest way of using the `<d-form-select>` component would be by using the `options` prop to pass an `Array` or `Object` for the options.
12
+
13
+ :::demo
14
+ ```html
15
+ <template>
16
+ <d-form-select v-model="selected" :options="options" />
17
+ Selected: {{ selected }}
18
+ </template>
19
+
20
+ <script>
21
+ export default {
22
+ data() {
23
+ return {
24
+ selected: null,
25
+ options: [
26
+ { value: null, text: 'Please select an option' },
27
+ { value: 'first', text: 'This is the first option' },
28
+ { value: 'second', text: 'This is the second option' },
29
+ { value: 'disabled', text: 'This one is disabled', disabled: true }
30
+ ]
31
+ }
32
+ }
33
+ }
34
+ </script>
35
+
36
+ <!-- select-1.vue -->
37
+ ```
38
+ :::
39
+
40
+ ## Sizing
41
+
42
+ You can control the form-control's size using the `size` prop which accepts `sm` for small or `lg` for large.
43
+
44
+ ## Manual Options
45
+
46
+ You can also define your options manually:
47
+
48
+ :::demo
49
+ ```html
50
+ <template>
51
+ <div>
52
+ <d-form-select v-model="selected" class="mb-3">
53
+ <option :value="null">Select an option</option>
54
+ <option value="pizza">🍕Pizza</option>
55
+ <option value="pasta" disabled>🍝 Pasta (disabled)</option>
56
+ <optgroup label="Breakfast">
57
+ <option value="eggs">🍳 Eggs</option>
58
+ <option value="bacon">🥓 Bacon</option>
59
+ <option value="tea">🍵 Tea</option>
60
+ </optgroup>
61
+ </d-form-select>
62
+ <div>Selected: {{ selected }}</div>
63
+ </div>
64
+ </template>
65
+
66
+ <script>
67
+ export default {
68
+ data () {
69
+ return {
70
+ selected: null
71
+ }
72
+ }
73
+ }
74
+ </script>
75
+
76
+ <!-- select-2.vue -->
77
+ ```
78
+ :::
79
+
80
+ ## Mixed Options
81
+
82
+ You can also mix both using the `options` prop and usin manual options.
83
+
84
+ :::demo
85
+ ```html
86
+ <template>
87
+ <div>
88
+ <d-form-select v-model="selected" :options="options" class="mb-3">
89
+ <optgroup label="Breakfast">
90
+ <option value="eggs">🍳 Eggs</option>
91
+ <option value="bacon">🥓 Bacon</option>
92
+ </optgroup>
93
+ </d-form-select>
94
+ <div>Selected: {{ selected }}</div>
95
+ </div>
96
+ </template>
97
+
98
+ <script>
99
+ export default {
100
+ data () {
101
+ return {
102
+ selected: null,
103
+ options: [
104
+ { value: null, text: 'Select an option' },
105
+ { value: 'pizza', text: '🍕 Pizza' },
106
+ { value: 'pasta', text: '🍝 Pasta', disabled: true },
107
+ ]
108
+ }
109
+ }
110
+ }
111
+ </script>
112
+
113
+ <!-- select-3.vue -->
114
+ ```
115
+ :::
116
+
117
+ ## Select Sizing
118
+
119
+ Using the `select-size` prop you can switch the custom select into a select list box. The prop accepts a number larger than 1 to control how many options are visible.
120
+
121
+ :::demo
122
+ ```html
123
+ <template>
124
+ <d-form-select v-model="selected" :options="options" :select-size="2" />
125
+ Selected: {{ selected }}
126
+ </template>
127
+
128
+ <script>
129
+ export default {
130
+ data() {
131
+ return {
132
+ selected: null,
133
+ options: [
134
+ { value: null, text: 'Please select an option' },
135
+ { value: 'first', text: 'This is the first option' },
136
+ { value: 'second', text: 'This is the second option' },
137
+ { value: 'disabled', text: 'This one is disabled', disabled: true }
138
+ ]
139
+ }
140
+ }
141
+ }
142
+ </script>
143
+
144
+ <!-- select-4.vue -->
145
+ ```
146
+ :::
147
+
148
+ ## Multiple Selections
149
+
150
+
151
+ Using the `multiple` prop you can allow users to select multiple values from the `<d-form-select>` component.
152
+
153
+ > Note: Using the `multiple` mode requires an `Array` reference for your `v-model`.
154
+
155
+ :::demo
156
+ ```html
157
+ <template>
158
+ <d-form-select multiple :select-size="4" v-model="selected" :options="options" />
159
+ Selected: {{ selected }}
160
+ </template>
161
+
162
+ <script>
163
+ export default {
164
+ data() {
165
+ return {
166
+ selected: [],
167
+ options: [
168
+ { value: 'first', text: 'This is the first option' },
169
+ { value: 'second', text: 'This is the second option' },
170
+ { value: 'third', text: 'This is the third option' },
171
+ { value: 'fourth', text: 'This is the fourth option' }
172
+ ]
173
+ }
174
+ }
175
+ }
176
+ </script>
177
+
178
+ <!-- select-5.vue -->
179
+ ```
180
+ :::
@@ -0,0 +1,18 @@
1
+ import { registerComponents, vueUse } from './../../utils'
2
+
3
+ import dFormSelect from './FormSelect.vue'
4
+
5
+ const components = {
6
+ dFormSelect,
7
+ dSelect: dFormSelect
8
+ }
9
+
10
+ const VuePlugin = {
11
+ install (Vue) {
12
+ registerComponents(Vue, components)
13
+ }
14
+ }
15
+
16
+ vueUse(VuePlugin)
17
+
18
+ export default VuePlugin
@@ -0,0 +1,250 @@
1
+ <template>
2
+ <textarea
3
+ ref="input"
4
+ :class="[
5
+ plaintext ? 'form-control-plaintext' : 'form-control',
6
+ plaintext ? 'w-100' : '',
7
+ size ? `form-control-${this.size}` : null,
8
+ stateClass
9
+ ]"
10
+ :style="computedStyle"
11
+ :name="name"
12
+ :id="computedID"
13
+ :disabled="disabled"
14
+ :required="required"
15
+ :placeholder="placeholder"
16
+ :autocomplete="autocomplete"
17
+ :readonly="readonly || plaintext"
18
+ :rows="rows"
19
+ :wrap="wrap"
20
+ :aria-required="required ? 'true' : null"
21
+ :aria-invalid="computedAriaInvalid"
22
+ @input="handleInput"
23
+ ></textarea>
24
+ </template>
25
+
26
+ <script>
27
+ import { guid, getComputedStyles, isVisible } from "../../utils";
28
+
29
+ export default {
30
+ name: "d-form-textarea",
31
+ data() {
32
+ return {
33
+ localValue: this.value
34
+ };
35
+ },
36
+ props: {
37
+ /**
38
+ * The element name.
39
+ */
40
+ name: {
41
+ type: String,
42
+ default: null
43
+ },
44
+ /**
45
+ * The element ID.
46
+ */
47
+ id: {
48
+ type: String,
49
+ default: null
50
+ },
51
+ /**
52
+ * The disabled state.
53
+ */
54
+ disabled: {
55
+ type: Boolean,
56
+ required: false
57
+ },
58
+ /**
59
+ * The required state.
60
+ */
61
+ required: {
62
+ type: Boolean,
63
+ required: false
64
+ },
65
+ /**
66
+ * The validity state.
67
+ */
68
+ state: {
69
+ type: [Boolean, String],
70
+ default: null,
71
+ validator: v => ["valid", "invalid", true, false, null].includes(v)
72
+ },
73
+ /**
74
+ * The element's size.
75
+ */
76
+ size: {
77
+ type: String,
78
+ default: null,
79
+ validator: v => ["sm", "lg", null].includes(v)
80
+ },
81
+ /**
82
+ * The placeholder value.
83
+ */
84
+ placeholder: {
85
+ type: String,
86
+ default: null
87
+ },
88
+ /**
89
+ * The autocomplete status.
90
+ */
91
+ autocomplete: {
92
+ type: String,
93
+ default: null
94
+ },
95
+ /**
96
+ * Whether the textarea should be read-only, or not.
97
+ */
98
+ readonly: {
99
+ type: Boolean,
100
+ default: false
101
+ },
102
+ /**
103
+ * Whether the textarea should be plain-text, or not.
104
+ */
105
+ plaintext: {
106
+ type: Boolean,
107
+ default: false
108
+ },
109
+ /**
110
+ * The number of text rows.
111
+ */
112
+ rows: {
113
+ type: [Number, String],
114
+ default: null
115
+ },
116
+ /**
117
+ * The textarea wrap style.
118
+ */
119
+ wrap: {
120
+ type: String,
121
+ default: "soft",
122
+ validator: v => ["soft", "hard", "off"].includes(v)
123
+ },
124
+ /**
125
+ * Whether resizing should be disabled, or not.
126
+ */
127
+ noResize: {
128
+ type: Boolean,
129
+ default: false
130
+ },
131
+ /**
132
+ * The maximum number of rows allowed.
133
+ */
134
+ maxRows: {
135
+ type: [Number, String],
136
+ default: null
137
+ }
138
+ },
139
+ mounted() {
140
+ this.el = this.$el;
141
+ },
142
+ computed: {
143
+ computedID() {
144
+ return this.id || `dr-textarea-${guid()}`;
145
+ },
146
+ computedStyle() {
147
+ return {
148
+ width: this.plaintext ? "100%" : null,
149
+ height: this.computedHeight,
150
+ resize: this.noResize ? "none" : null
151
+ };
152
+ },
153
+ computedMinRows() {
154
+ return Math.max(parseInt(this.rows, 10) || 2, 2);
155
+ },
156
+ computedMaxRows() {
157
+ return Math.max(this.computedMinRows, parseInt(this.maxRows, 10) || 0);
158
+ },
159
+ computedHeight() {
160
+ if (this.localValue === null || !isVisible(this.el)) {
161
+ return null;
162
+ }
163
+
164
+ const _height = this.el.style.height;
165
+
166
+ // eslint-disable-next-line vue/no-side-effects-in-computed-properties
167
+ this.el.style.height = "inherit";
168
+
169
+ const computed = getComputedStyles(this.el);
170
+ const minHeight =
171
+ parseInt(computed.height, 10) || lineHeight * this.computedMinRows;
172
+
173
+ const lineHeight = parseFloat(computed.lineHeight);
174
+ const offset =
175
+ parseInt(computed.borderTopWidth, 10) +
176
+ parseInt(computed.paddingTop, 10) +
177
+ parseInt(computed.paddingBottom, 10) +
178
+ parseInt(computed.borderBottomWidth, 10);
179
+
180
+ // eslint-disable-next-line vue/no-side-effects-in-computed-properties
181
+ this.el.style.height = _height;
182
+
183
+ const rows = Math.min(
184
+ Math.max(
185
+ (this.el.scrollHeight - offset) / lineHeight,
186
+ this.computedMinRows
187
+ ),
188
+ this.computedMaxRows - 1
189
+ );
190
+
191
+ if (!this.localValue.trim()) {
192
+ return `${minHeight}px`;
193
+ }
194
+
195
+ return `${Math.max(Math.ceil(rows * lineHeight + offset), minHeight)}px`;
196
+ },
197
+ computedAriaInvalid() {
198
+ // eslint-disable-next-line
199
+ if (!Boolean(this.ariaInvalid) || this.ariaInvalid === "false") {
200
+ return this.computedState === false ? "true" : null;
201
+ }
202
+
203
+ if (this.ariaInvalid === true) {
204
+ return "true";
205
+ }
206
+
207
+ return this.ariaInvalid;
208
+ },
209
+ computedState() {
210
+ if (this.state === true || this.state === "valid") {
211
+ return true;
212
+ }
213
+
214
+ if (this.state === false || this.state === "invalid") {
215
+ return false;
216
+ }
217
+
218
+ return null;
219
+ },
220
+ stateClass() {
221
+ if (this.computedState === true) {
222
+ return "is-valid";
223
+ }
224
+
225
+ if (this.computedState === false) {
226
+ return "is-invalid";
227
+ }
228
+
229
+ return null;
230
+ }
231
+ },
232
+ watch: {
233
+ value(newVal, oldVal) {
234
+ if (newVal !== oldVal) {
235
+ this.localValue = newVal;
236
+ }
237
+ },
238
+ localValue(newVal, oldVal) {
239
+ if (newVal !== oldVal) {
240
+ this.$emit("input", newVal);
241
+ }
242
+ }
243
+ },
244
+ methods: {
245
+ handleInput(e) {
246
+ this.localValue = e.target.value;
247
+ }
248
+ }
249
+ };
250
+ </script>