@avakhula/ui 0.0.505 → 0.0.506-alpha-spa.1

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 (185) hide show
  1. package/.babelrc.json +0 -0
  2. package/.eslintrc.cjs +0 -0
  3. package/.nvmrc +0 -0
  4. package/.storybook/main.js +0 -0
  5. package/.storybook/preview-head.html +0 -0
  6. package/.storybook/preview.js +0 -0
  7. package/dist/index.css +1 -0
  8. package/dist/index.js +14352 -12501
  9. package/dist/index.umd.cjs +93 -82
  10. package/package.json +8 -7
  11. package/src/App.vue +7 -126
  12. package/src/assets/scss/mixins/dropdown-list-item.scss +6 -1
  13. package/src/assets/scss/mixins/tooltip-position.scss +0 -0
  14. package/src/assets/scss/mixins.scss +0 -0
  15. package/src/assets/scss/style.scss +0 -0
  16. package/src/assets/scss/typography.scss +3 -3
  17. package/src/assets/scss/variables/colors.json +0 -0
  18. package/src/assets/scss/variables/colors.scss +0 -0
  19. package/src/assets/scss/variables/shadows.json +0 -0
  20. package/src/assets/scss/variables/shadows.scss +0 -0
  21. package/src/components/Accordion/Accordion.scss +0 -0
  22. package/src/components/Accordion/Accordion.stories.js +0 -0
  23. package/src/components/Accordion/Accordion.vue +0 -0
  24. package/src/components/Accordion/Acordion.spec.js +0 -0
  25. package/src/components/Accordion/readme.mdx +0 -0
  26. package/src/components/Alert/Alert.spec.js +0 -0
  27. package/src/components/Alert/Alert.stories.js +0 -0
  28. package/src/components/Alert/Alert.vue +5 -0
  29. package/src/components/Alert/alert.scss +6 -1
  30. package/src/components/Alert/constants.js +0 -0
  31. package/src/components/Alert/readme.mdx +0 -0
  32. package/src/components/Avatar/Avatar.stories.js +5 -1
  33. package/src/components/Avatar/Avatar.vue +25 -2
  34. package/src/components/Avatar/constants.js +6 -0
  35. package/src/components/Badge/Badge.spec.js +0 -0
  36. package/src/components/Badge/Badge.vue +0 -0
  37. package/src/components/Badge/readme.mdx +0 -0
  38. package/src/components/Breadcrumbs/Breadcrumbs.vue +23 -8
  39. package/src/components/Breadcrumbs/breadcrumbs.scss +0 -0
  40. package/src/components/Breadcrumbs/breadcrumbs.stories.js +0 -0
  41. package/src/components/Button/Button.spec.js +0 -0
  42. package/src/components/Button/Button.vue +19 -3
  43. package/src/components/Button/button.scss +5 -0
  44. package/src/components/Button/readme.mdx +0 -0
  45. package/src/components/ButtonGroup/ButtonGroup.stories.js +0 -0
  46. package/src/components/ButtonGroup/readme.mdx +0 -0
  47. package/src/components/Chips/Chips.stories.js +30 -0
  48. package/src/components/Chips/Chips.vue +125 -0
  49. package/src/components/Dropdown/Dropdown.spec.js +0 -0
  50. package/src/components/Dropdown/Dropdown.stories.js +0 -0
  51. package/src/components/Dropdown/Dropdown.vue +93 -23
  52. package/src/components/Dropdown/DropdownDivider.vue +0 -0
  53. package/src/components/Dropdown/DropdownItem.vue +26 -4
  54. package/src/components/Dropdown/DropdownList.stories.js +0 -0
  55. package/src/components/Dropdown/DropdownList.vue +15 -1
  56. package/src/components/Dropdown/readme.mdx +0 -0
  57. package/src/components/Form/CharactersCount.vue +10 -7
  58. package/src/components/Form/Checkbox/Checkbox.scss +0 -0
  59. package/src/components/Form/Checkbox/Checkbox.stories.js +0 -0
  60. package/src/components/Form/Checkbox/Checkbox.vue +24 -11
  61. package/src/components/Form/Checkbox/readme.mdx +0 -0
  62. package/src/components/Form/CheckboxGroup/CheckboxGroup.stories.js +0 -0
  63. package/src/components/Form/CheckboxGroup/CheckboxGroup.vue +15 -0
  64. package/src/components/Form/CheckboxGroup/readme.mdx +2 -0
  65. package/src/components/Form/DatePicker/DatePicker.scss +352 -261
  66. package/src/components/Form/DatePicker/DatePicker.stories.js +0 -0
  67. package/src/components/Form/DatePicker/DatePicker.vue +72 -17
  68. package/src/components/Form/DatePicker/readme.mdx +0 -0
  69. package/src/components/Form/FormGroup/FormGroup.vue +3 -3
  70. package/src/components/Form/FormGroup/FormGroupSet.vue +0 -0
  71. package/src/components/Form/Input/Input.stories.js +0 -0
  72. package/src/components/Form/Input/Input.vue +119 -13
  73. package/src/components/Form/Input/constants.js +0 -0
  74. package/src/components/Form/Input/input.scss +61 -2
  75. package/src/components/Form/Input/readme.mdx +0 -0
  76. package/src/components/Form/Label/Label.stories.js +0 -0
  77. package/src/components/Form/Label/Label.vue +22 -10
  78. package/src/components/Form/Label/readme.mdx +0 -0
  79. package/src/components/Form/PhoneInput/PhoneInput.stories.js +0 -0
  80. package/src/components/Form/PhoneInput/PhoneInput.vue +76 -27
  81. package/src/components/Form/PhoneInput/phoneInput.scss +38 -6
  82. package/src/components/Form/PhoneInput/readme.mdx +0 -0
  83. package/src/components/Form/Radio/Radio.stories.js +0 -0
  84. package/src/components/Form/Radio/Radio.vue +16 -44
  85. package/src/components/Form/Radio/radio.scss +5 -2
  86. package/src/components/Form/Radio/readme.mdx +0 -0
  87. package/src/components/Form/TextEditor/TextEditor.stories.js +0 -0
  88. package/src/components/Form/TextEditor/TextEditor.vue +91 -137
  89. package/src/components/Form/TextEditor/Toolbar.vue +723 -0
  90. package/src/components/Form/TextEditor/icons/toolbarIcons.js +8 -0
  91. package/src/components/Form/TextEditor/plugins/imageBlot.js +23 -0
  92. package/src/components/Form/TextEditor/readme.mdx +0 -0
  93. package/src/components/Form/TextEditor/setupTextEditor.js +71 -0
  94. package/src/components/Form/TextEditor/textEditor.scss +11 -335
  95. package/src/components/Form/Textarea/Textarea.spec.js +0 -0
  96. package/src/components/Form/Textarea/Textarea.stories.js +0 -0
  97. package/src/components/Form/Textarea/Textarea.vue +20 -6
  98. package/src/components/Form/Textarea/readme.mdx +0 -0
  99. package/src/components/Form/Textarea/textarea.scss +30 -2
  100. package/src/components/Form/Toggle/Toggle.stories.js +0 -0
  101. package/src/components/Form/Toggle/Toggle.vue +0 -0
  102. package/src/components/Form/Toggle/readme.mdx +0 -0
  103. package/src/components/Form/Toggle/toggle.scss +0 -0
  104. package/src/components/IconButton/IconButton.scss +11 -0
  105. package/src/components/IconButton/IconButton.vue +10 -3
  106. package/src/components/IconButton/readme.mdx +0 -0
  107. package/src/components/List.vue +0 -0
  108. package/src/components/Modal/Modal.stories.js +0 -0
  109. package/src/components/Modal/Modal.vue +42 -9
  110. package/src/components/Modal/constants.js +0 -0
  111. package/src/components/Modal/readme.mdx +0 -0
  112. package/src/components/Pagination/LimitSelector.vue +5 -0
  113. package/src/components/Pagination/Pagination.vue +36 -4
  114. package/src/components/Pagination/pagination.scss +17 -1
  115. package/src/components/Panel/Panel.stories.js +0 -0
  116. package/src/components/Panel/Panel.vue +68 -2
  117. package/src/components/Popover/Popover.vue +25 -9
  118. package/src/components/Popover/constants.js +0 -0
  119. package/src/components/Popover/popover.scss +1 -1
  120. package/src/components/Popover/readme.mdx +0 -0
  121. package/src/components/ProgressBar/ProgressBar.vue +0 -0
  122. package/src/components/ProgressBar/constants.js +0 -0
  123. package/src/components/ProgressBar/progressBar.scss +0 -0
  124. package/src/components/ProgressBar/readme.mdx +0 -0
  125. package/src/components/Sorting/Sorting.stories.js +0 -0
  126. package/src/components/Sorting/Sorting.vue +24 -26
  127. package/src/components/Sorting/sorting.scss +0 -0
  128. package/src/components/SplitButton/SplitButton.stories.js +0 -0
  129. package/src/components/SplitButton/SplitButton.vue +51 -8
  130. package/src/components/SplitButton/SplitButtonItem.vue +13 -1
  131. package/src/components/SplitButton/readme.mdx +0 -0
  132. package/src/components/SplitButton/splitButton.scss +0 -0
  133. package/src/components/StatusIndicator/StatusIndicator.stories.js +0 -0
  134. package/src/components/StatusIndicator/StatusIndicator.vue +0 -0
  135. package/src/components/StatusIndicator/constants.js +0 -0
  136. package/src/components/StatusIndicator/icons.js +0 -0
  137. package/src/components/StatusIndicator/readme.mdx +0 -0
  138. package/src/components/Table/Cells/Cell.vue +0 -0
  139. package/src/components/Table/Cells/CheckboxCell.vue +0 -0
  140. package/src/components/Table/Row.vue +0 -0
  141. package/src/components/Table/Table.stories.js +0 -0
  142. package/src/components/Table/Table.vue +0 -0
  143. package/src/components/Tabs/Tab.vue +4 -0
  144. package/src/components/Tabs/TabDropdown.vue +0 -0
  145. package/src/components/Tabs/Tabs.stories.js +0 -0
  146. package/src/components/Tabs/Tabs.vue +20 -5
  147. package/src/components/Tabs/tabs.scss +8 -2
  148. package/src/components/TagPill/TagPill.stories.js +0 -0
  149. package/src/components/TagPill/TagPill.vue +6 -0
  150. package/src/components/TagPill/readme.mdx +0 -0
  151. package/src/components/ToggleTip/ToggleTip.vue +0 -0
  152. package/src/components/ToggleTip/constants.js +0 -0
  153. package/src/components/ToggleTip/readme.mdx +0 -0
  154. package/src/components/ToggleTip/toggleTip.scss +0 -0
  155. package/src/components/Tooltip/Tooltip.vue +1 -1
  156. package/src/components/Tooltip/readme.mdx +0 -0
  157. package/src/components/TreeSelect/Option.vue +58 -24
  158. package/src/components/TreeSelect/Select.stories.js +0 -0
  159. package/src/components/TreeSelect/Select.vue +281 -147
  160. package/src/components/TreeSelect/TreeSelect.stories.js +0 -0
  161. package/src/components/TreeSelect/mixins/InfinityLoaderMixin.js +40 -0
  162. package/src/components/TreeSelect/scss/option.scss +31 -0
  163. package/src/components/TreeSelect/scss/select.scss +93 -2
  164. package/src/constants/keyCodes.js +1 -0
  165. package/src/directives/outside/outside.stories.js +0 -0
  166. package/src/directives/outside/readme.mdx +0 -0
  167. package/src/directives/tooltip/TooltipController.js +2 -0
  168. package/src/directives/tooltip/readme.mdx +0 -0
  169. package/src/directives/tooltip/textOverflowTooltip.js +3 -1
  170. package/src/directives/tooltip/tooltip.js +61 -0
  171. package/src/directives/tooltip/tooltip.stories.js +0 -0
  172. package/src/helpers/debounce.js +23 -0
  173. package/src/helpers/removeEvents.js +0 -0
  174. package/src/helpers/stripHtml.js +4 -0
  175. package/src/index.js +7 -0
  176. package/src/main.js +0 -0
  177. package/src/mixins/expandAnimation.js +0 -0
  178. package/src/scripts/parseScssVariables.js +0 -0
  179. package/src/stories/link.readme.mdx +0 -0
  180. package/src/stories/variables/colors.stories.js +0 -0
  181. package/src/stories/variables/shadows.stories.js +0 -0
  182. package/static/docks/button.pdf +0 -0
  183. package/static/favicon.ico +0 -0
  184. package/vite.config.js +0 -0
  185. package/dist/style.css +0 -1
@@ -3,35 +3,56 @@
3
3
  {{ errorMessage }}
4
4
  </ib-alert>
5
5
 
6
- <vue-tel-input
7
- v-outside="clickOutside"
8
- v-model="phone"
9
- v-bind="$attrs"
10
- @country-changed="countryChanged"
11
- :input-options="{ name: inputName, id: inputName }"
12
- :auto-default-country="autoDefaultCountry"
13
- :dropdown-options="{ showSearchBox: true, showFlags: true }"
14
- :defaultCountry="defaultCountry"
15
- :ignoredCountries="ignoredCountries"
16
- :class="{ error: error || errorMessage.length }"
17
- style-classes="ib-phone-input"
18
- ref="vueTel"
19
- >
20
- <template #arrow-icon>
21
- <ib-icon name="chevron-down-outline"></ib-icon>
22
- </template>
23
- </vue-tel-input>
6
+ <div class="ib-phone-wrapper">
7
+ <vue-tel-input
8
+ v-outside="clickOutside"
9
+ v-model="phone"
10
+ v-bind="$attrs"
11
+ @country-changed="countryChanged"
12
+ :input-options="{ name: inputName, id: inputName, autocomplete: 'tel' }"
13
+ :auto-default-country="autoDefaultCountry"
14
+ :dropdown-options="{ showSearchBox: true, showFlags: true, tabindex: 0 }"
15
+ :defaultCountry="defaultCountry"
16
+ :ignoredCountries="ignoredCountries"
17
+ :class="{ error: error || errorMessage.length, disabled }"
18
+ :disabled="disabled"
19
+ style-classes="ib-phone-input"
20
+ ref="vueTel"
21
+ >
22
+ <template #arrow-icon>
23
+ <ib-icon name="chevron-down-outline"></ib-icon>
24
+ </template>
25
+
26
+ <template #icon-right>
27
+ <ib-icon-button
28
+ v-if="showClearButton"
29
+ v-show="phone.length"
30
+ kind="ghost"
31
+ class="ib-phone-clear-button"
32
+ @click="clearPhone"
33
+ >
34
+ <ib-icon name="close-outline" />
35
+ </ib-icon-button>
36
+ </template>
37
+ </vue-tel-input>
38
+ </div>
24
39
  </template>
25
40
 
26
41
  <script>
27
- import { VueTelInput } from "vue-tel-input";
28
42
  import IbIcon from "../../Icon.vue";
43
+ import IbIconButton from "../../IconButton/IconButton.vue";
29
44
  import IbAlert from "../../Alert/Alert.vue";
30
45
  import { OutsideDirective as Outside } from "../../../directives/outside/outside";
46
+ import { VueTelInput } from 'vue-tel-input';
47
+ import 'vue-tel-input/vue-tel-input.css'
31
48
 
32
49
  export default {
33
50
  directives: { Outside },
34
51
  props: {
52
+ modelValue: {
53
+ type: String
54
+ },
55
+ value: String,
35
56
  inputName: {
36
57
  type: String,
37
58
  default: "phone",
@@ -40,10 +61,6 @@ export default {
40
61
  type: Boolean,
41
62
  default: true,
42
63
  },
43
- value: {
44
- type: String,
45
- default: "",
46
- },
47
64
  ignoredCountries: {
48
65
  type: Array,
49
66
  default: () => [],
@@ -56,25 +73,43 @@ export default {
56
73
  type: String,
57
74
  default: "",
58
75
  },
76
+ disabled: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ showClearButton: {
81
+ type: Boolean,
82
+ default: true,
83
+ },
59
84
  },
85
+ emits: ['update:modelValue', 'onReady'],
60
86
  components: {
61
87
  VueTelInput,
88
+ IbIconButton,
62
89
  IbAlert,
63
90
  IbIcon,
64
91
  },
65
92
  data() {
66
93
  return {
67
94
  vueTel: null,
68
- phone: "",
69
95
  dialCode: "",
70
96
  defaultCountry: "US",
97
+ allowChange: false
71
98
  };
72
99
  },
73
100
  mounted() {
74
101
  this.vueTel = this.$refs.vueTel;
75
102
 
76
- if (this.value) {
77
- this.phone = this.value[0] === "+" ? this.value : "+" + this.value;
103
+ this.$emit('onReady');
104
+ },
105
+ computed: {
106
+ phone: {
107
+ get() {
108
+ return this.modelValue
109
+ },
110
+ set(value) {
111
+ this.$emit('update:modelValue', value)
112
+ }
78
113
  }
79
114
  },
80
115
  methods: {
@@ -95,11 +130,25 @@ export default {
95
130
  this.vueTel.clickedOutside();
96
131
  }
97
132
  },
133
+ clearPhone() {
134
+ this.phone = "";
135
+ }
98
136
  },
99
137
  };
100
138
  </script>
101
139
 
102
140
  <style lang="scss">
103
141
  @import "./phoneInput.scss";
142
+
143
+ .ib-phone-wrapper {
144
+ position: relative;
145
+
146
+ .ib-phone-clear-button {
147
+ position: absolute;
148
+ right: 5px;
149
+ top: 50%;
150
+ transform: translateY(-50%);
151
+
152
+ }
153
+ }
104
154
  </style>
105
- <style src="vue-tel-input/vue-tel-input.css"></style>
@@ -43,6 +43,39 @@ $dropdown-item-selected-border-color: $blue-900;
43
43
  }
44
44
  }
45
45
 
46
+ &.disabled {
47
+ .vti__input {
48
+ background-color: $gray-100 !important;
49
+ color: $neutral-500 !important;
50
+ border-color: $input-border-color !important;
51
+
52
+ &:focus {
53
+ outline: none !important;
54
+ border-bottom: 1px solid $input-border-color !important;
55
+ border-radius: 4px 4px 0 0 !important;
56
+ }
57
+ }
58
+
59
+ .vti__dropdown {
60
+ background-color: $gray-100 !important;
61
+ border-color: $input-border-color !important;
62
+ cursor: not-allowed;
63
+
64
+ .vti__selection {
65
+ filter:grayscale(1);
66
+ }
67
+
68
+ &:focus {
69
+ .vti__selection {
70
+ outline: none !important;
71
+ background-color: $gray-100 !important;
72
+ border-bottom: 1px solid $input-border-color !important;
73
+ border-radius: 4px 4px 0 0 !important;
74
+ }
75
+ }
76
+ }
77
+ }
78
+
46
79
  .vti__dropdown {
47
80
  padding: 0;
48
81
  border-radius: 4px 4px 0 0;
@@ -100,17 +133,16 @@ $dropdown-item-selected-border-color: $blue-900;
100
133
  .vti__input {
101
134
  background-color: transparent;
102
135
  width: 100%;
103
- margin: 0;
104
- margin-bottom: 6.5px;
105
- border-left: 0px;
106
- border-right: 0px;
107
- border-top: 0px;
136
+ margin: 0 0 6.5px;
137
+ border-left: 0;
138
+ border-right: 0;
139
+ border-top: 0;
108
140
  border-radius: 0;
109
141
 
110
142
  &::placeholder {
111
143
  @include Ib-H4-regular-italic;
112
144
  color: $input-placeholder-color;
113
- }
145
+ }
114
146
 
115
147
  &:focus {
116
148
  border-radius: 0;
File without changes
File without changes
@@ -3,19 +3,17 @@
3
3
  role="radio"
4
4
  :class="classes"
5
5
  :for="id"
6
- :aria-checked="checked"
7
- @click.prevent="onClick"
6
+ :aria-checked="isChecked"
8
7
  >
9
8
  <input
10
9
  type="radio"
11
10
  :name="name"
12
11
  :id="id"
13
12
  :value="value"
14
- :checked="checked"
13
+ :checked="isChecked"
15
14
  :disabled="disabled"
16
15
  ref="radio"
17
- @input.stop
18
- @change="onChange"
16
+ @change="checkHandler"
19
17
  />
20
18
  <span class="ib-radio-body" :class="{ 'without-text': !label?.length }">
21
19
  <span class="ib-radio-input"></span>
@@ -29,11 +27,8 @@ import generateUID from "../../../helpers/generateUID";
29
27
 
30
28
  export default {
31
29
  name: "IbRadio",
32
- model: {
33
- prop: "isChecked",
34
- event: "input",
35
- },
36
30
  props: {
31
+ modelValue: '',
37
32
  label: String,
38
33
  error: {
39
34
  type: Boolean,
@@ -49,63 +44,40 @@ export default {
49
44
  },
50
45
  },
51
46
  value: {
52
- type: String,
47
+ type: [String, Number],
53
48
  required: true,
54
49
  },
55
- isChecked: {
56
- type: Boolean,
57
- default: false,
58
- },
59
50
  disabled: {
60
51
  type: Boolean,
61
52
  default: false,
62
53
  },
63
54
  },
64
- watch: {
65
- isChecked(value) {
66
- this.checked = value;
67
- },
68
- },
69
- mounted() {
70
- this.$globalEvents.$on(`radio:update:${this.name}`, (uid) => {
71
- if (this.uid !== uid) {
72
- this.checked = false;
73
- }
74
- });
75
- },
55
+ emits: ['update:modelValue'],
76
56
  data() {
77
57
  return {
78
- checked: this.isChecked,
79
58
  uid: generateUID(),
80
59
  };
81
60
  },
61
+ mounted() {
62
+ this.checked = this.isChecked;
63
+ },
82
64
  methods: {
83
- onClick() {
84
- if (!this.disabled) {
85
- this.checked = !this.checked;
86
- this.$globalEvents.$emit(`radio:update:${this.name}`, this.uid);
87
- this.$emit("input", this.checked);
88
- this.$emit("change", this.checked);
89
- }
90
- },
91
- onChange() {
92
- if (!this.disabled) {
93
- this.checked = !this.checked;
94
- this.$globalEvents.$emit(`radio:update:${this.name}`, this.uid);
95
- this.$emit("change", this.checked);
96
- this.$emit("input", this.checked);
97
- }
98
- },
65
+ checkHandler() {
66
+ this.$emit('update:modelValue', this.value)
67
+ }
99
68
  },
100
69
  computed: {
101
70
  classes() {
102
71
  return {
103
72
  "ib-radio": true,
104
73
  "has-error": this.error,
105
- "radio-filled": this.checked,
74
+ "radio-filled": this.isChecked,
106
75
  "radio-disabled": this.disabled,
107
76
  };
108
77
  },
78
+ isChecked() {
79
+ return this.modelValue === this.value
80
+ }
109
81
  },
110
82
  };
111
83
  </script>
@@ -30,12 +30,15 @@ $radio-border-filled-disabled: $neutral-500;
30
30
  .ib-radio {
31
31
  display: inline-flex;
32
32
  cursor: pointer;
33
+ position: relative;
33
34
 
34
35
  input {
35
36
  opacity: 0;
36
37
  position: absolute;
37
- top: -100%;
38
- right: -100%;
38
+ width: 1px;
39
+ height: 1px;
40
+ z-index: -1;
41
+
39
42
 
40
43
  &:focus + .ib-radio-body {
41
44
  border-radius: 4px;
File without changes
@@ -7,6 +7,7 @@
7
7
  disable: disable,
8
8
  }"
9
9
  >
10
+
10
11
  <ib-character-count
11
12
  v-if="characterLimit"
12
13
  :character-limit="characterLimit"
@@ -23,170 +24,72 @@
23
24
  {{ characterLimitErrorMessage }}
24
25
  </ib-alert>
25
26
 
27
+ <input :name="name" type="hidden" :disabled="disable" :value="data">
28
+
26
29
  <div class="ib-text-editor-wrapper" :class="{ disable: disable }">
27
30
  <div
28
31
  class="ib-text-editor"
29
- :style="{ height: height ? height + 'px' : '' }"
30
32
  ref="wrapper"
31
33
  >
32
34
  <QuillEditor
35
+ aria-label="text-editor"
33
36
  @textChange="onChange"
34
37
  @blur="onBlur"
35
38
  @focus="onFocus"
36
39
  ref="quill"
37
- toolbar="#toolbar"
38
40
  v-model:content="data"
39
41
  contentType="html"
40
42
  :options="config"
41
43
  :modules="modules"
42
44
  ></QuillEditor>
43
45
  </div>
44
- <div id="toolbar" class="toolbar" ref="toolbar">
45
- <div class="toolbar-group header-toolbar-group">
46
- <select class="ql-header">
47
- <option value="1"></option>
48
- <option value="2"></option>
49
- <option value="3"></option>
50
- <option value="4"></option>
51
- <option value="5"></option>
52
- <option value="6"></option>
53
- <option selected></option>
54
- </select>
55
- </div>
56
-
57
- <div class="toolbar-group">
58
- <ib-icon-button
59
- class="toolbar-item ql-bold"
60
- kind="ghost"
61
- ></ib-icon-button>
62
- <ib-icon-button
63
- class="toolbar-item ql-italic"
64
- kind="ghost"
65
- ></ib-icon-button>
66
- <ib-icon-button
67
- class="toolbar-item ql-underline"
68
- kind="ghost"
69
- ></ib-icon-button>
70
- <ib-icon-button
71
- class="toolbar-item ql-strike"
72
- kind="ghost"
73
- ></ib-icon-button>
74
- </div>
75
-
76
- <div class="toolbar-group">
77
- <select class="ql-background"></select>
78
- <select class="ql-color"></select>
79
- </div>
80
-
81
- <div class="toolbar-group">
82
- <ib-icon-button
83
- class="toolbar-item ql-code-block"
84
- kind="ghost"
85
- ></ib-icon-button>
86
- <ib-icon-button
87
- class="toolbar-item ql-link"
88
- kind="ghost"
89
- ></ib-icon-button>
90
- </div>
91
-
92
- <div class="toolbar-group">
93
- <ib-icon-button
94
- class="toolbar-item ql-align"
95
- kind="ghost"
96
- ></ib-icon-button>
97
- <ib-icon-button
98
- class="ql-align toolbar-item"
99
- value="center"
100
- kind="ghost"
101
- ></ib-icon-button>
102
- <ib-icon-button
103
- class="ql-align toolbar-item"
104
- value="right"
105
- kind="ghost"
106
- ></ib-icon-button>
107
- <ib-icon-button
108
- class="ql-align toolbar-item"
109
- value="justify"
110
- kind="ghost"
111
- ></ib-icon-button>
112
- </div>
113
-
114
- <div class="toolbar-group">
115
- <ib-icon-button
116
- class="ql-list toolbar-item"
117
- value="ordered"
118
- kind="ghost"
119
- ></ib-icon-button>
120
- <ib-icon-button
121
- class="ql-list toolbar-item"
122
- value="bullet"
123
- kind="ghost"
124
- ></ib-icon-button>
125
46
 
126
- <ib-icon-button
127
- class="ql-alphabet-list alphabet-list toolbar-item"
128
- kind="ghost"
129
- ></ib-icon-button>
130
- </div>
131
- </div>
47
+ <Toolbar
48
+ id="toolbar"
49
+ class="toolbar"
50
+ ref="toolbar"
51
+ :placeholders="placeholders"
52
+ :uid="uid"
53
+ :hidden-elements="hiddenElements"
54
+ />
132
55
  </div>
133
56
  </div>
134
57
  </template>
135
58
 
136
59
  <script>
137
- import { QuillEditor, Quill } from "@vueup/vue-quill";
60
+
61
+ import {Quill, QuillEditor} from "@vueup/vue-quill";
138
62
  import IbIconButton from "../../IconButton/IconButton.vue";
139
63
  import IbAlert from "../../Alert/Alert.vue";
140
64
  import IbCharacterCount from "../CharactersCount.vue";
141
- import { AlphabetList, AlphabetListItem } from "./plugins/alphabetList";
65
+ import Toolbar from "./Toolbar.vue";
66
+ import { stripHtml } from "../../../helpers/stripHtml";
67
+ import getPlaceholderModule from 'quill-placeholder-module';
142
68
  import "@vueup/vue-quill/dist/vue-quill.snow.css";
69
+ import { setupTextEditor } from "./setupTextEditor";
143
70
 
144
- import {
145
- BOLD,
146
- ITALIC,
147
- UNDERLINE,
148
- STRIKE,
149
- CODE,
150
- LINK,
151
- ALIGN_LEFT,
152
- ALIGN_CENTER,
153
- ALIGN_RIGHT,
154
- ALIGN_JUSTIFY,
155
- LIST_ORDERED,
156
- LIST_BULLET,
157
- LIST_ALPHABET,
158
- } from "./icons/toolbarIcons";
159
-
160
- const icons = Quill.import("ui/icons");
161
- icons.bold = BOLD;
162
- icons.italic = ITALIC;
163
- icons.underline = UNDERLINE;
164
- icons.strike = STRIKE;
165
- icons["code-block"] = CODE;
166
- icons.link = LINK;
167
- icons.align[""] = ALIGN_LEFT;
168
- icons.align.center = ALIGN_CENTER;
169
- icons.align.right = ALIGN_RIGHT;
170
- icons.align.justify = ALIGN_JUSTIFY;
171
- icons.list.ordered = LIST_ORDERED;
172
- icons.list.bullet = LIST_BULLET;
173
- icons["alphabet-list"] = LIST_ALPHABET;
71
+ Quill.register('modules/placeholder', getPlaceholderModule(Quill, {
72
+ className: 'ql-placeholder-content'
73
+ }))
174
74
 
175
- Quill.register({
176
- "formats/alphabet-list": AlphabetList,
177
- "formats/alphabet-list/item": AlphabetListItem,
178
- });
179
-
180
- Quill.register(icons);
181
75
  Quill.debug("error");
76
+ setupTextEditor();
182
77
 
183
78
  export default {
184
79
  name: "IbTextEditor",
185
80
  props: {
81
+ name: {
82
+ type: String,
83
+ required: true
84
+ },
186
85
  placeholder: {
187
86
  type: String,
188
87
  default: "",
189
88
  },
89
+ placeholders: {
90
+ type: Array,
91
+ default: () => []
92
+ },
190
93
  modelValue: {
191
94
  type: String,
192
95
  },
@@ -230,14 +133,13 @@ export default {
230
133
  type: String,
231
134
  default: "",
232
135
  },
233
- height: {
234
- type: String,
235
- },
136
+ hiddenElements: {
137
+ type: Array,
138
+ default: () => ['font-size', 'image']
139
+ }
236
140
  },
141
+ emits: ['onOverLimitHandler', 'update:modelValue', 'change', 'blur'],
237
142
  mounted() {
238
- // Reset default styles for toolbar
239
- this.$refs.toolbar.classList.remove("ql-toolbar");
240
-
241
143
  // Change default placeholder for link input
242
144
  const input = this.$refs.wrapper.querySelector("input[data-link]");
243
145
  input.dataset.link = "Enter Link";
@@ -256,24 +158,61 @@ export default {
256
158
  this.data = val;
257
159
  },
258
160
  data(val) {
259
- this.$emit("update:modelValue", val);
161
+ const cleanedData = this.cleanPlaceholderSpans(val);
162
+ this.$emit("update:modelValue", cleanedData);
260
163
  },
164
+ characterOverLimit(value) {
165
+ this.$emit('onOverLimitHandler', value);
166
+ }
261
167
  },
262
168
  methods: {
263
169
  onChange() {
170
+ let data = this.cleanPlaceholderSpans(this.data);
171
+ this.data = this.patchListStylePosition(data);
172
+
264
173
  this.updateCharacterLength();
265
174
  this.$emit("change", this.data);
266
175
  },
267
176
  onBlur(instance) {
268
- this.$emit("blur", this.data, instance);
177
+ this.$emit("blur", this.cleanPlaceholderSpans(this.data), instance);
269
178
  this.isFocus = false;
270
179
  },
271
180
  onFocus() {
272
181
  this.isFocus = true;
273
182
  },
274
183
  updateCharacterLength() {
275
- this.characterLength = this.$refs.quill.getText().length - 1;
184
+ this.characterLength = stripHtml(this.data).length;
276
185
  },
186
+ cleanPlaceholderSpans(html) {
187
+ if (!html) return html;
188
+
189
+ let prevHtml;
190
+ do {
191
+ prevHtml = html;
192
+ html = html.replace(/<span contenteditable="false">([\s\S]*?)<\/span>/g, (_, content) => {
193
+ return content.replace(/[\u200B-\u200F\uFEFF]/g, '');
194
+ });
195
+ } while (prevHtml !== html);
196
+
197
+ return html;
198
+ },
199
+ patchListStylePosition(html) {
200
+ const tmp = document.createElement('div');
201
+ tmp.innerHTML = html;
202
+
203
+ tmp.querySelectorAll('ul[style*="text-align"], ol[style*="text-align"], li[style*="text-align"]').forEach(el => {
204
+ const style = el.getAttribute('style') ?? '';
205
+
206
+ if (!/list-style-position\s*:\s*inside/i.test(style)) {
207
+ const newStyle =
208
+ (style.trim().endsWith(';') || style.trim() === '' ? style : style + ';') +
209
+ ' list-style-position: inside;';
210
+ el.setAttribute('style', newStyle);
211
+ }
212
+ });
213
+
214
+ return tmp.innerHTML;
215
+ }
277
216
  },
278
217
  computed: {
279
218
  config() {
@@ -281,6 +220,17 @@ export default {
281
220
  placeholder: this.data.length ? "" : this.placeholder,
282
221
  readOnly: this.readOnly ? this.readOnly : this.disable,
283
222
  enable: this.enable,
223
+ modules: {
224
+ toolbar: {
225
+ container: '#toolbar',
226
+ handlers: { 'image': this.imageButtonClickHandler }
227
+ },
228
+ placeholder: {
229
+ delimiters: ['{{', '}}'],
230
+ placeholders: this.placeholders
231
+ }
232
+ },
233
+
284
234
  };
285
235
 
286
236
  return Object.assign(config, this.options);
@@ -290,16 +240,20 @@ export default {
290
240
  !!this.characterLimit && this.characterLength > this.characterLimit
291
241
  );
292
242
  },
243
+ uid() {
244
+ return Math.random().toString(36).substr(2, 9);
245
+ },
293
246
  },
294
247
  components: {
295
248
  QuillEditor,
296
249
  IbIconButton,
297
250
  IbAlert,
298
251
  IbCharacterCount,
252
+ Toolbar,
299
253
  },
300
254
  };
301
255
  </script>
302
256
 
303
- <style lang="scss">
257
+ <style lang="scss" scoped>
304
258
  @import "./textEditor.scss";
305
259
  </style>