@ozdao/martyrs 0.2.541 → 0.2.542

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 (171) hide show
  1. package/dist/_virtual/index.cjs +4 -4
  2. package/dist/_virtual/index.js +4 -4
  3. package/dist/_virtual/index2.cjs +3 -6
  4. package/dist/_virtual/index2.cjs.map +1 -1
  5. package/dist/_virtual/index2.js +2 -5
  6. package/dist/_virtual/index2.js.map +1 -1
  7. package/dist/{main-BpBtIUcJ.js → main-ByKkD9qa.js} +2724 -3143
  8. package/dist/main-Czyu-VcC.cjs +11 -0
  9. package/dist/martyrs/src/components/FieldTags/BlockTags.vue.cjs +30 -21
  10. package/dist/martyrs/src/components/FieldTags/BlockTags.vue.cjs.map +1 -1
  11. package/dist/martyrs/src/components/FieldTags/BlockTags.vue.js +32 -23
  12. package/dist/martyrs/src/components/FieldTags/BlockTags.vue.js.map +1 -1
  13. package/dist/martyrs/src/components/FieldTags/FieldTags.vue2.cjs +235 -0
  14. package/dist/martyrs/src/components/FieldTags/FieldTags.vue2.cjs.map +1 -0
  15. package/dist/martyrs/src/components/FieldTags/FieldTags.vue2.js +235 -0
  16. package/dist/martyrs/src/components/FieldTags/FieldTags.vue2.js.map +1 -0
  17. package/dist/martyrs/src/components/Marquee/Marquee.vue.cjs +17 -8
  18. package/dist/martyrs/src/components/Marquee/Marquee.vue.cjs.map +1 -1
  19. package/dist/martyrs/src/components/Marquee/Marquee.vue.js +17 -8
  20. package/dist/martyrs/src/components/Marquee/Marquee.vue.js.map +1 -1
  21. package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.cjs → Spoiler.vue2.cjs} +2 -2
  22. package/dist/martyrs/src/components/Spoiler/Spoiler.vue2.cjs.map +1 -0
  23. package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.js → Spoiler.vue2.js} +2 -2
  24. package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.cjs.map → Spoiler.vue2.js.map} +1 -1
  25. package/dist/martyrs/src/components/Tab/{Tab.vue.cjs → Tab.vue2.cjs} +2 -2
  26. package/dist/martyrs/src/components/Tab/Tab.vue2.cjs.map +1 -0
  27. package/dist/martyrs/src/components/Tab/{Tab.vue.js → Tab.vue2.js} +2 -2
  28. package/dist/martyrs/src/components/Tab/{Tab.vue.cjs.map → Tab.vue2.js.map} +1 -1
  29. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.cjs +161 -42
  30. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.cjs.map +1 -1
  31. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js +162 -43
  32. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js.map +1 -1
  33. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
  34. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  35. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
  36. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  37. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.cjs +1 -1
  38. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
  39. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +4 -4
  40. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
  41. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  42. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
  43. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
  44. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
  45. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  46. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +0 -3
  47. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs.map +1 -1
  48. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +0 -3
  49. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js.map +1 -1
  50. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.js +2 -2
  51. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +21 -21
  52. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +1 -1
  53. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
  54. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.cjs +1 -1
  55. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.js +1 -1
  56. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +1 -1
  57. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +1 -1
  58. package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.cjs +1 -1
  59. package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.js +1 -1
  60. package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.cjs +1 -1
  61. package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.js +1 -1
  62. package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.cjs +1 -1
  63. package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.js +1 -1
  64. package/dist/martyrs/src/modules/marketplace/views/components/layouts/Marketplace.vue.cjs +1 -1
  65. package/dist/martyrs/src/modules/marketplace/views/components/layouts/Marketplace.vue.js +1 -1
  66. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +11 -11
  67. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +12 -12
  68. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +16 -16
  69. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +16 -16
  70. package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.cjs +1 -1
  71. package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.js +1 -1
  72. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
  73. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  74. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.cjs +1 -1
  75. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
  76. package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.cjs +3 -4
  77. package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.cjs.map +1 -1
  78. package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js +3 -4
  79. package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js.map +1 -1
  80. package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.cjs +1 -1
  81. package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +20 -20
  82. package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.cjs +3 -4
  83. package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.cjs.map +1 -1
  84. package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js +3 -4
  85. package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js.map +1 -1
  86. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +4 -5
  87. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs.map +1 -1
  88. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +4 -5
  89. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js.map +1 -1
  90. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +3 -4
  91. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs.map +1 -1
  92. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +3 -4
  93. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js.map +1 -1
  94. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
  95. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +7 -7
  96. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.cjs +1 -1
  97. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
  98. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
  99. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
  100. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +46 -38
  101. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs.map +1 -1
  102. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +52 -44
  103. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
  104. package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +1 -1
  105. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
  106. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +1 -1
  107. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
  108. package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +2 -2
  109. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +2 -2
  110. package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.cjs +1 -1
  111. package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.js +1 -1
  112. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +1 -1
  113. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
  114. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.cjs +1 -1
  115. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  116. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +1 -1
  117. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
  118. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs +1 -1
  119. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
  120. package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.cjs +1 -1
  121. package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.js +1 -1
  122. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
  123. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +11 -11
  124. package/dist/martyrs.cjs.js +1 -1
  125. package/dist/martyrs.css +1 -1
  126. package/dist/martyrs.es.js +1 -1
  127. package/dist/node_modules/.pnpm/lodash.merge@4.6.2/node_modules/lodash.merge/index.cjs +1 -1
  128. package/dist/node_modules/.pnpm/lodash.merge@4.6.2/node_modules/lodash.merge/index.js +1 -1
  129. package/dist/style.css +129 -129
  130. package/dist/{web-DsdyXC8n.js → web-BklgIiYr.js} +1 -1
  131. package/dist/{web-C9bVm6Nw.cjs → web-CQBm7C6L.cjs} +1 -1
  132. package/package.json +1 -1
  133. package/src/components/FieldTags/BlockTags.vue +28 -16
  134. package/src/components/FieldTags/FieldTags.vue +327 -508
  135. package/src/components/Marquee/Marquee.vue +25 -14
  136. package/src/components/UploadImage/UploadImage.vue +192 -18
  137. package/src/modules/community/components/pages/CreateBlogPost.vue +0 -1
  138. package/src/modules/products/components/pages/CategoryEdit.vue +53 -39
  139. package/dist/_virtual/index3.cjs +0 -5
  140. package/dist/_virtual/index3.cjs.map +0 -1
  141. package/dist/_virtual/index3.js +0 -5
  142. package/dist/_virtual/index3.js.map +0 -1
  143. package/dist/main-7IA3UHca.cjs +0 -11
  144. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs +0 -480
  145. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs.map +0 -1
  146. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js +0 -480
  147. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js.map +0 -1
  148. package/dist/martyrs/src/components/FieldTags/create-tags.cjs +0 -52
  149. package/dist/martyrs/src/components/FieldTags/create-tags.cjs.map +0 -1
  150. package/dist/martyrs/src/components/FieldTags/create-tags.js +0 -52
  151. package/dist/martyrs/src/components/FieldTags/create-tags.js.map +0 -1
  152. package/dist/martyrs/src/components/FieldTags/tag-input.vue2.cjs +0 -32
  153. package/dist/martyrs/src/components/FieldTags/tag-input.vue2.cjs.map +0 -1
  154. package/dist/martyrs/src/components/FieldTags/tag-input.vue2.js +0 -32
  155. package/dist/martyrs/src/components/FieldTags/tag-input.vue2.js.map +0 -1
  156. package/dist/martyrs/src/components/FieldTags/vue-tags-input.props.cjs +0 -329
  157. package/dist/martyrs/src/components/FieldTags/vue-tags-input.props.cjs.map +0 -1
  158. package/dist/martyrs/src/components/FieldTags/vue-tags-input.props.js +0 -329
  159. package/dist/martyrs/src/components/FieldTags/vue-tags-input.props.js.map +0 -1
  160. package/dist/martyrs/src/components/Spoiler/Spoiler.vue.js.map +0 -1
  161. package/dist/martyrs/src/components/Tab/Tab.vue.js.map +0 -1
  162. package/dist/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.cjs +0 -39
  163. package/dist/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.cjs.map +0 -1
  164. package/dist/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js +0 -39
  165. package/dist/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js.map +0 -1
  166. package/src/components/FieldTags/FieldTagsNew.vue +0 -366
  167. package/src/components/FieldTags/README.md +0 -513
  168. package/src/components/FieldTags/create-tags.js +0 -97
  169. package/src/components/FieldTags/tag-input.vue +0 -55
  170. package/src/components/FieldTags/vue-tags-input.props.js +0 -342
  171. package/src/components/FieldTags/vue-tags-input.scss +0 -149
@@ -1,543 +1,362 @@
1
1
  <template>
2
- <div
3
- class="vue-tags-input pos-relative"
4
- :class="[{ 'ti-disabled': disabled }, { 'ti-focus': focused }, $attrs.class]"
5
- :style="$attrs.style"
6
- >
7
- <div class="ti-input">
8
- <ul v-if="tagsCopy.length || !disabled" class="ti-tags">
9
- <li
10
- v-for="(tag, index) in tagsCopy"
11
- :key="`tag-${index}-${tag.text}`"
12
- :style="tag.style"
13
- :class="[
14
- { 'ti-editing': tagsEditStatus[index] },
15
- tag.tiClasses,
16
- tag.classes,
17
- { 'ti-deletion-mark': isMarked(index) }
18
- ]"
19
- tabindex="0"
20
- class="ti-tag t-medium"
21
- @click="emit('tag-clicked', { tag, index })"
2
+ <div class="field-tags-new">
3
+ <!-- Tags container -->
4
+ <div class="tags-container">
5
+ <span
6
+ v-for="(tag, index) in tags"
7
+ :key="index"
8
+ class="tag"
9
+ >
10
+ {{ getTagText(tag) }}
11
+ <button
12
+ @click="removeTag(index)"
13
+ class="tag-remove"
14
+ type="button"
22
15
  >
23
- <div class="ti-content">
24
- <div
25
- v-if="$slots['tag-left']"
26
- class="ti-tag-left"
27
- >
28
- <slot
29
- name="tag-left"
30
- :tag="tag"
31
- :index="index"
32
- :edit="tagsEditStatus[index]"
33
- :perform-save-edit="performSaveTag"
34
- :perform-delete="performDeleteTag"
35
- :perform-cancel-edit="cancelEdit"
36
- :perform-open-edit="performEditTag"
37
- :deletion-mark="isMarked(index)"
38
- />
39
- </div>
40
- <div :ref="el => setTagCenter(el, index)" class="ti-tag-center">
41
- <span
42
- v-if="!$slots['tag-center']"
43
- :class="{ 'ti-hidden': tagsEditStatus[index] }"
44
- @click="performEditTag(index)"
45
- >{{ tag.text }}</span>
46
- <tag-input
47
- v-if="!$slots['tag-center']"
48
- :scope="{
49
- edit: tagsEditStatus[index],
50
- maxlength,
51
- tag,
52
- index,
53
- validateTag: createChangedTag,
54
- performCancelEdit: cancelEdit,
55
- performSaveEdit: performSaveTag,
56
- }"
57
- />
58
- <slot
59
- name="tag-center"
60
- :tag="tag"
61
- :index="index"
62
- :maxlength="maxlength"
63
- :edit="tagsEditStatus[index]"
64
- :perform-save-edit="performSaveTag"
65
- :perform-delete="performDeleteTag"
66
- :perform-cancel-edit="cancelEdit"
67
- :validate-tag="createChangedTag"
68
- :perform-open-edit="performEditTag"
69
- :deletion-mark="isMarked(index)"
70
- />
71
- </div>
72
- <div
73
- v-if="$slots['tag-right']"
74
- class="ti-tag-right"
75
- >
76
- <slot
77
- name="tag-right"
78
- :tag="tag"
79
- :index="index"
80
- :edit="tagsEditStatus[index]"
81
- :perform-save-edit="performSaveTag"
82
- :perform-delete="performDeleteTag"
83
- :perform-cancel-edit="cancelEdit"
84
- :perform-open-edit="performEditTag"
85
- :deletion-mark="isMarked(index)"
86
- />
87
- </div>
88
- </div>
89
- <div class="ti-actions">
90
- <i
91
- v-if="!$slots['tag-actions']"
92
- v-show="tagsEditStatus[index]"
93
- class="ti-icon-undo"
94
- @click.stop="cancelEdit(index)"
95
- />
96
- <i
97
- v-if="!$slots['tag-actions']"
98
- v-show="!tagsEditStatus[index]"
99
- class="ti-icon-close"
100
- @click.stop="performDeleteTag(index)"
101
- />
102
- <slot
103
- v-if="$slots['tag-actions']"
104
- name="tag-actions"
105
- :tag="tag"
106
- :index="index"
107
- :edit="tagsEditStatus[index]"
108
- :perform-save-edit="performSaveTag"
109
- :perform-delete="performDeleteTag"
110
- :perform-cancel-edit="cancelEdit"
111
- :perform-open-edit="performEditTag"
112
- :deletion-mark="isMarked(index)"
113
- />
114
- </div>
115
- </li>
116
- <li class="ti-new-tag-input-wrapper">
117
- <input
118
- ref="newTagInputRef"
119
- :class="[createClasses(newTag, tags, validation, isDuplicate)]"
120
- :placeholder="placeholder"
121
- :value="newTag"
122
- :maxlength="maxlength"
123
- :disabled="disabled"
124
- type="text"
125
- size="1"
126
- class="ti-new-tag-input"
127
- @keydown="handleKeyDown"
128
- @paste="addTagsFromPaste"
129
- @keydown.delete="invokeDelete"
130
- @keydown.tab="performBlur"
131
- @keydown.up.prevent="selectItem('before')"
132
- @keydown.down.prevent="selectItem('after')"
133
- @input="updateNewTag"
134
- @focus="focused = true"
135
- @click="!addOnlyFromAutocomplete && (selectedItem = null)"
136
- >
137
- </li>
138
- </ul>
16
+ ×
17
+ </button>
18
+ </span>
19
+
20
+ <input
21
+ ref="inputRef"
22
+ v-model="newTag"
23
+ @keydown="handleKeyDown"
24
+ @paste="handlePaste"
25
+ @focus="focused = true"
26
+ @blur="handleBlur"
27
+ :placeholder="placeholder || 'Add tags'"
28
+ :maxlength="maxlength"
29
+ :disabled="disabled"
30
+ class="tag-input"
31
+ />
139
32
  </div>
140
- <slot name="between-elements" />
141
- <div
142
- v-if="autocompleteOpen"
143
- class="ti-autocomplete"
144
- :class="$attrs.class"
145
- @mouseleave="selectedItem = null"
33
+
34
+ <!-- Autocomplete dropdown -->
35
+ <div
36
+ v-if="showAutocomplete && filteredAutocomplete.length > 0"
37
+ class="autocomplete"
146
38
  >
147
- <slot name="autocomplete-header" />
148
- <ul>
149
- <li
150
- v-for="(item, index) in filteredAutocompleteItems"
151
- :key="`autocomplete-${index}-${item.text}`"
152
- :style="item.style"
153
- :class="[
154
- item.tiClasses,
155
- item.classes,
156
- { 'ti-selected-item': isSelected(index) }
157
- ]"
158
- class="ti-item"
159
- @mouseenter="!disabled && (selectedItem = index)"
160
- >
161
- <div
162
- v-if="!$slots['autocomplete-item']"
163
- @click="performAddTags(item, undefined, 'autocomplete')"
164
- >
165
- {{ item.text }}
166
- </div>
167
- <slot
168
- v-else
169
- name="autocomplete-item"
170
- :item="item"
171
- :index="index"
172
- :perform-add="item => performAddTags(item, undefined, 'autocomplete')"
173
- :selected="isSelected(index)"
174
- />
175
- </li>
176
- </ul>
177
- <slot name="autocomplete-footer" />
39
+ <div
40
+ v-for="(item, index) in filteredAutocomplete"
41
+ :key="getTagText(item)"
42
+ @click="addTag(item)"
43
+ @mouseenter="selectedIndex = index"
44
+ :class="['autocomplete-item', { selected: selectedIndex === index }]"
45
+ >
46
+ {{ getTagText(item) }}
47
+ </div>
178
48
  </div>
179
49
  </div>
180
50
  </template>
181
51
 
182
52
  <script setup>
183
- import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount, shallowRef, toRef } from 'vue';
184
- import equal from 'fast-deep-equal';
185
- import { clone, createClasses, createTag, createTags } from './create-tags.js';
186
- import TagInput from './tag-input.vue';
187
- import props from './vue-tags-input.props.js';
188
-
189
- // Props
190
- const propsObj = defineProps(props);
53
+ import { ref, computed, watch } from 'vue'
54
+
55
+ const props = defineProps({
56
+ modelValue: Array,
57
+ textField: {
58
+ type: String,
59
+ default: 'text'
60
+ },
61
+ autocompleteItems: Array,
62
+ separators: {
63
+ type: Array,
64
+ default: () => [',', ';']
65
+ },
66
+ addOnKey: {
67
+ type: Array,
68
+ default: () => [13] // Enter key
69
+ },
70
+ maxTags: {
71
+ type: Number,
72
+ default: 20
73
+ },
74
+ maxlength: {
75
+ type: Number,
76
+ default: 50
77
+ },
78
+ placeholder: String,
79
+ disabled: Boolean,
80
+ addOnBlur: {
81
+ type: Boolean,
82
+ default: true
83
+ },
84
+ autocompleteMinLength: {
85
+ type: Number,
86
+ default: 1
87
+ }
88
+ })
191
89
 
192
- // Emits
193
- const emit = defineEmits([
194
- 'adding-duplicate',
195
- 'before-adding-tag',
196
- 'before-deleting-tag',
197
- 'before-editing-tag',
198
- 'before-saving-tag',
199
- 'max-tags-reached',
200
- 'saving-duplicate',
201
- 'tags-changed',
202
- 'tag-clicked',
203
- 'update:modelValue',
204
- 'update:tags',
205
- ]);
90
+ const emit = defineEmits(['update:modelValue', 'tags-changed'])
206
91
 
207
92
  // State
208
- const tagCenterRefs = ref(new Map());
209
- const newTag = ref(propsObj.modelValue || '');
210
- const tagsCopy = shallowRef([]);
211
- const tagsEditStatus = ref([]);
212
- const deletionMark = ref(null);
213
- const deletionMarkTimer = ref(null);
214
- const selectedItem = ref(null);
215
- const focused = ref(false);
216
- const newTagInputRef = ref(null);
93
+ const newTag = ref('')
94
+ const focused = ref(false)
95
+ const selectedIndex = ref(-1)
96
+ const inputRef = ref(null)
217
97
 
218
98
  // Computed
219
- const autocompleteOpen = computed(() => {
220
- if (propsObj.autocompleteAlwaysOpen) return true;
221
- return newTag.value !== null &&
222
- newTag.value.length >= propsObj.autocompleteMinLength &&
223
- filteredAutocompleteItems.value.length > 0 &&
224
- focused.value;
225
- });
226
-
227
- const filteredAutocompleteItems = computed(() => {
228
- const items = propsObj.autocompleteItems.map(i =>
229
- createTag(i, propsObj.tags, propsObj.validation, propsObj.isDuplicate)
230
- );
99
+ const tags = computed({
100
+ get: () => props.modelValue || [],
101
+ set: (value) => {
102
+ emit('update:modelValue', value)
103
+ emit('tags-changed', value)
104
+ }
105
+ })
231
106
 
232
- if (!propsObj.autocompleteFilterDuplicates) return items;
233
- return items.filter(duplicateFilter);
234
- });
107
+ const showAutocomplete = computed(() => {
108
+ return focused.value &&
109
+ props.autocompleteItems?.length > 0 &&
110
+ newTag.value.length >= props.autocompleteMinLength
111
+ })
235
112
 
236
- // Methods
237
- const getSelectedIndex = (method) => {
238
- const items = filteredAutocompleteItems.value;
239
- const current = selectedItem.value;
240
- const lastItem = items.length - 1;
113
+ const filteredAutocomplete = computed(() => {
114
+ if (!props.autocompleteItems) return []
241
115
 
242
- if (items.length === 0) return;
243
- if (current === null) return 0;
244
- if (method === 'before' && current === 0) return lastItem;
245
- if (method === 'after' && current === lastItem) return 0;
246
- return method === 'after' ? current + 1 : current - 1;
247
- };
248
-
249
- const selectDefaultItem = () => {
250
- selectedItem.value = propsObj.addOnlyFromAutocomplete && filteredAutocompleteItems.value.length > 0 ? 0 : null;
251
- };
252
-
253
- const selectItem = (method) => {
254
- selectedItem.value = getSelectedIndex(method);
255
- };
256
-
257
- const isSelected = (index) => selectedItem.value === index;
258
- const isMarked = (index) => deletionMark.value === index;
259
-
260
- const setTagCenter = (el, index) => {
261
- if (el) {
262
- tagCenterRefs.value.set(index, el);
263
- } else {
264
- tagCenterRefs.value.delete(index);
265
- }
266
- };
267
-
268
- const invokeDelete = () => {
269
- if (!propsObj.deleteOnBackspace || newTag.value.length > 0) return;
116
+ const searchText = newTag.value.toLowerCase()
270
117
 
271
- const lastIndex = tagsCopy.value.length - 1;
272
- if (deletionMark.value === null) {
273
- clearTimeout(deletionMarkTimer.value);
274
- deletionMarkTimer.value = setTimeout(() => (deletionMark.value = null), 1000);
275
- deletionMark.value = lastIndex;
276
- } else {
277
- performDeleteTag(lastIndex);
278
- }
279
- };
118
+ return props.autocompleteItems.filter(item => {
119
+ const itemText = getTagText(item).toLowerCase()
120
+
121
+ // Filter by search text
122
+ if (!itemText.includes(searchText)) return false
123
+
124
+ // Filter out duplicates
125
+ return !isDuplicate(itemText)
126
+ })
127
+ })
280
128
 
281
- const addTagsFromPaste = () => {
282
- if (!propsObj.addFromPaste) return;
283
- setTimeout(() => performAddTags(newTag.value), 10);
284
- };
285
-
286
- const performEditTag = (index) => {
287
- if (!propsObj.allowEditTags) return;
288
-
289
- if (!propsObj.onBeforeEditingTag) {
290
- editTag(index);
291
- } else {
292
- emit('before-editing-tag', {
293
- index,
294
- tag: tagsCopy.value[index],
295
- editTag: () => editTag(index),
296
- });
129
+ // Methods
130
+ function getTagText(tag) {
131
+ if (tag === null || tag === undefined) return ''
132
+ if (typeof tag === 'string') return tag
133
+ return tag[props.textField] || ''
134
+ }
135
+
136
+ function createTag(text) {
137
+ // Preserve format based on existing data
138
+ if (tags.value.length > 0) {
139
+ if (typeof tags.value[0] === 'string') {
140
+ return text
141
+ }
297
142
  }
298
- };
299
-
300
- const editTag = (index) => {
301
- if (!propsObj.allowEditTags) return;
302
- toggleEditMode(index);
303
- focus(index);
304
- };
305
-
306
- const toggleEditMode = (index) => {
307
- if (!propsObj.allowEditTags || propsObj.disabled) return;
308
- tagsEditStatus.value[index] = !tagsEditStatus.value[index];
309
- };
310
-
311
- const createChangedTag = (index, event) => {
312
- const tag = tagsCopy.value[index];
313
- tag.text = event ? event.target.value : tagsCopy.value[index].text;
314
143
 
315
- const newTags = [...tagsCopy.value];
316
- newTags[index] = createTag(tag, tagsCopy.value, propsObj.validation, propsObj.isDuplicate);
317
- tagsCopy.value = newTags;
318
- };
319
-
320
- const focus = (index) => {
321
- nextTick(() => {
322
- const el = tagCenterRefs.value.get(index)?.querySelector('input.ti-tag-input');
323
- if (el) el.focus();
324
- });
325
- };
326
-
327
- const quote = (regex) => regex.replace(/([()[{*+.$^\\|?])/g, '\\$1');
328
-
329
- const cancelEdit = (index) => {
330
- if (!propsObj.tags[index]) return;
144
+ // Default to object with custom field
145
+ return { [props.textField]: text }
146
+ }
147
+
148
+ function isDuplicate(text) {
149
+ const searchText = text.toLowerCase().trim()
150
+ return tags.value.some(tag =>
151
+ getTagText(tag).toLowerCase().trim() === searchText
152
+ )
153
+ }
154
+
155
+ function addTag(input) {
156
+ let text = ''
331
157
 
332
- const newTags = [...tagsCopy.value];
333
- newTags[index] = clone(createTag(propsObj.tags[index], propsObj.tags, propsObj.validation, propsObj.isDuplicate));
334
- tagsCopy.value = newTags;
335
- tagsEditStatus.value[index] = false;
336
- };
337
-
338
- const hasForbiddingAddRule = (tiClasses) => {
339
- return tiClasses.some(type => {
340
- const rule = propsObj.validation.find(rule => type === rule.classes);
341
- return rule ? rule.disableAdd : false;
342
- });
343
- };
344
-
345
- const createTagTexts = (string) => {
346
- const regex = new RegExp(propsObj.separators.map(s => quote(s)).join('|'));
347
- return string.split(regex).map(text => ({ text }));
348
- };
349
-
350
- const performDeleteTag = (index) => {
351
- if (!propsObj.onBeforeDeletingTag) {
352
- deleteTag(index);
353
- } else {
354
- emit('before-deleting-tag', {
355
- index,
356
- tag: tagsCopy.value[index],
357
- deleteTag: () => deleteTag(index),
358
- });
158
+ if (typeof input === 'string') {
159
+ text = input.trim()
160
+ } else if (typeof input === 'object') {
161
+ // If it's an autocomplete item, preserve the whole object
162
+ if (props.autocompleteItems?.includes(input)) {
163
+ if (!isDuplicate(getTagText(input))) {
164
+ tags.value = [...tags.value, input]
165
+ }
166
+ newTag.value = ''
167
+ selectedIndex.value = -1
168
+ return
169
+ }
170
+ text = getTagText(input).trim()
359
171
  }
360
- };
361
-
362
- const deleteTag = (index) => {
363
- if (propsObj.disabled) return;
364
172
 
365
- deletionMark.value = null;
366
- clearTimeout(deletionMarkTimer.value);
173
+ if (!text || tags.value.length >= props.maxTags) return
367
174
 
368
- const newTags = [...tagsCopy.value];
369
- newTags.splice(index, 1);
370
- tagsCopy.value = newTags;
175
+ if (isDuplicate(text)) return
371
176
 
372
- tagsEditStatus.value.splice(index, 1);
177
+ const tag = createTag(text)
178
+ tags.value = [...tags.value, tag]
179
+ newTag.value = ''
180
+ selectedIndex.value = -1
181
+ }
182
+
183
+ function removeTag(index) {
184
+ if (props.disabled) return
373
185
 
374
- emit('update:tags', tagsCopy.value);
375
- emit('tags-changed', tagsCopy.value);
376
- };
377
-
378
- const noTriggerKey = (event, category) => {
379
- const triggerKey = propsObj[category].indexOf(event.keyCode) !== -1 ||
380
- propsObj[category].indexOf(event.key) !== -1;
381
- if (triggerKey) event.preventDefault();
382
- return !triggerKey;
383
- };
384
-
385
- const performAddTags = (tag, event, source) => {
386
- if (propsObj.disabled || (event && noTriggerKey(event, 'addOnKey'))) return;
387
-
388
- let tags = [];
389
- if (typeof tag === 'object') tags = [tag];
390
- if (typeof tag === 'string') tags = createTagTexts(tag);
391
-
392
- tags = tags.filter(tag => tag.text.trim().length > 0);
393
-
394
- tags.forEach(tag => {
395
- tag = createTag(tag, propsObj.tags, propsObj.validation, propsObj.isDuplicate);
396
- if (!propsObj.onBeforeAddingTag) {
397
- addTag(tag, source);
398
- } else {
399
- emit('before-adding-tag', {
400
- tag,
401
- addTag: () => addTag(tag, source),
402
- });
186
+ const newTags = [...tags.value]
187
+ newTags.splice(index, 1)
188
+ tags.value = newTags
189
+ }
190
+
191
+ function handleKeyDown(event) {
192
+ // Handle arrow keys for autocomplete navigation
193
+ if (showAutocomplete.value) {
194
+ if (event.key === 'ArrowDown') {
195
+ event.preventDefault()
196
+ selectedIndex.value = Math.min(
197
+ selectedIndex.value + 1,
198
+ filteredAutocomplete.value.length - 1
199
+ )
200
+ return
201
+ }
202
+
203
+ if (event.key === 'ArrowUp') {
204
+ event.preventDefault()
205
+ selectedIndex.value = Math.max(selectedIndex.value - 1, -1)
206
+ return
207
+ }
208
+
209
+ // Add selected autocomplete item on Enter
210
+ if (event.key === 'Enter' && selectedIndex.value >= 0) {
211
+ event.preventDefault()
212
+ addTag(filteredAutocomplete.value[selectedIndex.value])
213
+ return
403
214
  }
404
- });
405
- };
406
-
407
- const duplicateFilter = (tag) => {
408
- return propsObj.isDuplicate ?
409
- !propsObj.isDuplicate(tagsCopy.value, tag) :
410
- !tagsCopy.value.find(t => t.text === tag.text);
411
- };
412
-
413
- const addTag = (tag, source = 'new-tag-input') => {
414
- const options = filteredAutocompleteItems.value.map(i => i.text);
415
- if (propsObj.addOnlyFromAutocomplete && options.indexOf(tag.text) === -1) return;
416
-
417
- nextTick(() => {
418
- const maximumReached = propsObj.maxTags && propsObj.maxTags <= tagsCopy.value.length;
419
- if (maximumReached) return emit('max-tags-reached', tag);
420
-
421
- const dup = propsObj.avoidAddingDuplicates && !duplicateFilter(tag);
422
- if (dup) return emit('adding-duplicate', tag);
423
-
424
- if (hasForbiddingAddRule(tag.tiClasses)) return;
425
-
426
- newTag.value = '';
427
- tagsCopy.value = [...tagsCopy.value, tag];
428
- tagsEditStatus.value.push(false);
429
-
430
- emit('update:tags', tagsCopy.value);
431
-
432
- if (source === 'autocomplete') newTagInputRef.value?.focus();
433
-
434
- emit('tags-changed', tagsCopy.value);
435
- });
436
- };
437
-
438
- const performSaveTag = (index, event) => {
439
- const tag = tagsCopy.value[index];
440
-
441
- if (propsObj.disabled || (event && noTriggerKey(event, 'addOnKey'))) return;
442
- if (tag.text.trim().length === 0) return;
443
-
444
- if (!propsObj['onBeforeSavingTag']) {
445
- saveTag(index, tag);
446
- } else {
447
- emit('before-saving-tag', {
448
- index,
449
- tag,
450
- saveTag: () => saveTag(index, tag),
451
- });
452
215
  }
453
- };
454
-
455
- const saveTag = (index, tag) => {
456
- if (propsObj.avoidAddingDuplicates) {
457
- const tagsDiff = clone(tagsCopy.value);
458
- const inputTag = tagsDiff.splice(index, 1)[0];
459
- const dup = propsObj.isDuplicate ?
460
- propsObj.isDuplicate(tagsDiff, inputTag) :
461
- tagsDiff.map(t => t.text).indexOf(inputTag.text) !== -1;
462
-
463
- if (dup) return emit('saving-duplicate', tag);
216
+
217
+ // Check for add triggers
218
+ const shouldAdd = props.addOnKey.some(key => {
219
+ if (typeof key === 'number') {
220
+ return event.keyCode === key
221
+ }
222
+ return event.key === key
223
+ })
224
+
225
+ if (shouldAdd) {
226
+ event.preventDefault()
227
+ addTag(newTag.value)
228
+ return
464
229
  }
465
-
466
- if (hasForbiddingAddRule(tag.tiClasses)) return;
467
-
468
- const newTags = [...tagsCopy.value];
469
- newTags[index] = tag;
470
- tagsCopy.value = newTags;
471
- toggleEditMode(index);
472
-
473
- emit('update:tags', tagsCopy.value);
474
- emit('tags-changed', tagsCopy.value);
475
- };
476
-
477
- const tagsEqual = () => {
478
- return !tagsCopy.value.some((t, i) => !equal(t, propsObj.tags[i]));
479
- };
480
-
481
- const updateNewTag = (event) => {
482
- const value = event.target.value;
483
- newTag.value = value;
484
- emit('update:modelValue', value);
485
- };
486
-
487
- const initTags = () => {
488
- tagsCopy.value = createTags(propsObj.tags, propsObj.validation, propsObj.isDuplicate);
489
- tagsEditStatus.value = new Array(propsObj.tags.length).fill(false);
490
-
491
- if (!tagsEqual()) {
492
- emit('update:tags', tagsCopy.value);
230
+
231
+ // Handle backspace to delete last tag
232
+ if (event.key === 'Backspace' && newTag.value === '' && tags.value.length > 0) {
233
+ removeTag(tags.value.length - 1)
493
234
  }
494
- };
495
-
496
- const blurredOnClick = (e) => {
497
- const el = e.currentTarget;
498
- if (el?.contains(e.target) || el?.contains(document.activeElement)) return;
499
- performBlur();
500
- };
501
-
502
- const performBlur = () => {
503
- if (propsObj.addOnBlur && focused.value) performAddTags(newTag.value);
504
- focused.value = false;
505
- };
506
-
507
- const handleKeyDown = (event) => {
508
- const item = filteredAutocompleteItems.value[selectedItem.value] || newTag.value;
509
- performAddTags(item, event);
510
- };
511
-
512
- // Watchers
513
- watch(() => propsObj.modelValue, (newValue) => {
514
- if (!propsObj.addOnlyFromAutocomplete) selectedItem.value = null;
515
- newTag.value = newValue;
516
- });
235
+ }
517
236
 
518
- watch(() => propsObj.tags, () => {
519
- initTags();
520
- }, { deep: true });
521
-
522
- watch(autocompleteOpen, selectDefaultItem);
523
-
524
- // Lifecycle
525
- initTags();
526
-
527
- onMounted(() => {
528
- selectDefaultItem();
529
- document.addEventListener('click', blurredOnClick);
530
- });
531
-
532
- onBeforeUnmount(() => {
533
- document.removeEventListener('click', blurredOnClick);
534
- clearTimeout(deletionMarkTimer.value);
535
- });
237
+ function handlePaste(event) {
238
+ event.preventDefault()
239
+
240
+ const text = event.clipboardData.getData('text')
241
+ if (!text) return
242
+
243
+ // Create regex from separators
244
+ const separatorRegex = new RegExp(
245
+ props.separators.map(s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')
246
+ )
247
+
248
+ // Split by separators and add each tag
249
+ const parts = text.split(separatorRegex)
250
+
251
+ parts.forEach(part => {
252
+ if (tags.value.length >= props.maxTags) return
253
+ addTag(part)
254
+ })
255
+ }
256
+
257
+ function handleBlur() {
258
+ // Small delay to allow click on autocomplete items
259
+ setTimeout(() => {
260
+ focused.value = false
261
+ selectedIndex.value = -1
262
+
263
+ if (props.addOnBlur && newTag.value) {
264
+ addTag(newTag.value)
265
+ }
266
+ }, 200)
267
+ }
536
268
 
537
- // Expose for template
538
- defineExpose({
539
- createClasses
540
- });
269
+ // Reset selected index when autocomplete items change
270
+ watch(filteredAutocomplete, () => {
271
+ selectedIndex.value = -1
272
+ })
541
273
  </script>
542
274
 
543
- <style lang="scss" src="./vue-tags-input.scss"></style>
275
+ <style scoped>
276
+ .field-tags-new {
277
+ position: relative;
278
+ }
279
+
280
+ .tags-container {
281
+ display: flex;
282
+ flex-wrap: wrap;
283
+ align-items: center;
284
+ gap: 0.5rem;
285
+ }
286
+
287
+ .tag {
288
+ display: inline-flex;
289
+ align-items: center;
290
+ background: rgb(var(--main, 255, 215, 0));
291
+ color: rgb(var(--black, 0, 0, 0));
292
+ padding: 0.25rem 0.5rem;
293
+ border-radius: 2rem;
294
+ font-size: 0.875rem;
295
+ }
296
+
297
+ .tag-remove {
298
+ margin-left: 0.25rem;
299
+ background: none;
300
+ border: none;
301
+ color: inherit;
302
+ font-size: 1.25rem;
303
+ cursor: pointer;
304
+ padding: 0;
305
+ line-height: 1;
306
+ opacity: 0.7;
307
+ }
308
+
309
+ .tag-remove:hover {
310
+ opacity: 1;
311
+ }
312
+
313
+ .tag-input {
314
+ flex: 1;
315
+ border: none;
316
+ background: none;
317
+ outline: none;
318
+ min-width: 150px;
319
+ padding: 0.25rem;
320
+ font-size: inherit;
321
+ font-family: inherit;
322
+ }
323
+
324
+ .tag-input:disabled {
325
+ cursor: not-allowed;
326
+ opacity: 0.5;
327
+ }
328
+
329
+ .autocomplete {
330
+ position: absolute;
331
+ top: 100%;
332
+ left: 0;
333
+ right: 0;
334
+ margin-top: 0.25rem;
335
+ background: white;
336
+ border: 1px solid rgb(var(--gray, 224, 224, 224));
337
+ border-radius: 0.5rem;
338
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
339
+ max-height: 200px;
340
+ overflow-y: auto;
341
+ z-index: 100;
342
+ }
343
+
344
+ .autocomplete-item {
345
+ padding: 0.5rem 0.75rem;
346
+ cursor: pointer;
347
+ transition: background-color 0.2s;
348
+ }
349
+
350
+ .autocomplete-item:hover,
351
+ .autocomplete-item.selected {
352
+ background: rgb(var(--gray-light, 248, 248, 248));
353
+ }
354
+
355
+ .autocomplete-item:first-child {
356
+ border-radius: 0.5rem 0.5rem 0 0;
357
+ }
358
+
359
+ .autocomplete-item:last-child {
360
+ border-radius: 0 0 0.5rem 0.5rem;
361
+ }
362
+ </style>