apostrophe 4.3.2 → 4.4.0

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 (158) hide show
  1. package/.stylelintrc +1 -93
  2. package/CHANGELOG.md +56 -0
  3. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBar.vue +7 -1
  4. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +6 -3
  5. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarUser.vue +2 -1
  6. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +1 -0
  7. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +3 -2
  8. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposSavingIndicator.vue +6 -2
  9. package/modules/@apostrophecms/any-page-type/index.js +2 -2
  10. package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +13 -7
  11. package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +4 -4
  12. package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +17 -11
  13. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +13 -7
  14. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenuItem.vue +3 -0
  15. package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +36 -20
  16. package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +18 -11
  17. package/modules/@apostrophecms/busy/ui/apos/components/TheAposBusy.vue +6 -8
  18. package/modules/@apostrophecms/command-menu/index.js +12 -7
  19. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuKey.vue +9 -7
  20. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuShortcut.vue +28 -15
  21. package/modules/@apostrophecms/command-menu/ui/apos/components/TheAposCommandMenu.vue +44 -42
  22. package/modules/@apostrophecms/doc-type/index.js +2 -1
  23. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +4 -3
  24. package/modules/@apostrophecms/file-tag/index.js +1 -1
  25. package/modules/@apostrophecms/global/index.js +29 -0
  26. package/modules/@apostrophecms/i18n/i18n/de.json +20 -0
  27. package/modules/@apostrophecms/i18n/i18n/en.json +1 -0
  28. package/modules/@apostrophecms/i18n/i18n/es.json +1 -0
  29. package/modules/@apostrophecms/i18n/i18n/fr.json +1 -0
  30. package/modules/@apostrophecms/i18n/i18n/it.json +1 -0
  31. package/modules/@apostrophecms/i18n/i18n/pt-BR.json +1 -0
  32. package/modules/@apostrophecms/i18n/i18n/sk.json +1 -0
  33. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +25 -17
  34. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalizeErrors.vue +5 -4
  35. package/modules/@apostrophecms/image/index.js +2 -1
  36. package/modules/@apostrophecms/image/ui/apos/components/AposImageCropper.vue +1 -1
  37. package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +9 -8
  38. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +13 -10
  39. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerDisplay.vue +11 -7
  40. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +12 -2
  41. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerSelections.vue +8 -5
  42. package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploader.vue +17 -8
  43. package/modules/@apostrophecms/image-tag/index.js +1 -1
  44. package/modules/@apostrophecms/login/ui/apos/components/AposLoginForm.vue +1 -0
  45. package/modules/@apostrophecms/login/ui/apos/components/AposResetPasswordForm.vue +1 -0
  46. package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +16 -14
  47. package/modules/@apostrophecms/login/ui/apos/components/TheAposLoginHeader.vue +9 -4
  48. package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +11 -59
  49. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +1 -0
  50. package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +59 -55
  51. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBody.vue +1 -0
  52. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBreadcrumbs.vue +5 -0
  53. package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +6 -10
  54. package/modules/@apostrophecms/modal/ui/apos/components/AposModalShareDraft.vue +14 -16
  55. package/modules/@apostrophecms/modal/ui/apos/components/AposModalTabs.vue +68 -5
  56. package/modules/@apostrophecms/modal/ui/apos/components/AposWidgetModalTabs.vue +15 -9
  57. package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +48 -122
  58. package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +9 -6
  59. package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +38 -36
  60. package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +15 -9
  61. package/modules/@apostrophecms/notification/ui/apos/components/TheAposNotifications.vue +2 -2
  62. package/modules/@apostrophecms/page/index.js +9 -6
  63. package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +3 -4
  64. package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +5 -10
  65. package/modules/@apostrophecms/page/views/notFound.html +5 -5
  66. package/modules/@apostrophecms/permission/ui/apos/components/AposPermissionGrid.vue +6 -2
  67. package/modules/@apostrophecms/piece-page-type/index.js +1 -0
  68. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +8 -12
  69. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +2 -2
  70. package/modules/@apostrophecms/piece-type/ui/apos/components/AposRelationshipEditor.vue +1 -2
  71. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +59 -41
  72. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapDivider.vue +1 -0
  73. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapMarks.vue +3 -1
  74. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +3 -1
  75. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapTable.vue +2 -0
  76. package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Classes.js +1 -7
  77. package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Heading.js +10 -0
  78. package/modules/@apostrophecms/schema/lib/addFieldTypes.js +8 -3
  79. package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +4 -6
  80. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +1 -0
  81. package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +5 -2
  82. package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +1 -0
  83. package/modules/@apostrophecms/schema/ui/apos/components/AposInputDateAndTime.vue +1 -1
  84. package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +2 -0
  85. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +1 -0
  86. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +14 -8
  87. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +4 -2
  88. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +7 -1
  89. package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +3 -1
  90. package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +35 -5
  91. package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +7 -4
  92. package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +50 -15
  93. package/modules/@apostrophecms/schema/ui/apos/components/AposSubform.vue +5 -10
  94. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +19 -31
  95. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +3 -0
  96. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +9 -0
  97. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +7 -0
  98. package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +11 -2
  99. package/modules/@apostrophecms/schema/ui/apos/logic/AposSearchList.js +3 -0
  100. package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +5 -0
  101. package/modules/@apostrophecms/schema/ui/apos/scss/AposInputArray.scss +42 -9
  102. package/modules/@apostrophecms/search/index.js +1 -0
  103. package/modules/@apostrophecms/settings/index.js +33 -0
  104. package/modules/@apostrophecms/settings/ui/apos/components/AposSettingsManager.vue +6 -7
  105. package/modules/@apostrophecms/settings/ui/apos/logic/AposSettingsManager.js +0 -1
  106. package/modules/@apostrophecms/submitted-draft/index.js +26 -0
  107. package/modules/@apostrophecms/submitted-draft/ui/apos/components/AposSubmittedDraftIcon.vue +4 -4
  108. package/modules/@apostrophecms/template/views/templateError.html +4 -4
  109. package/modules/@apostrophecms/translation/ui/apos/components/AposTranslationIndicator.vue +2 -1
  110. package/modules/@apostrophecms/ui/ui/apos/components/AposAvatar.vue +3 -2
  111. package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +62 -15
  112. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonGroup.vue +8 -0
  113. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonSplit.vue +9 -3
  114. package/modules/@apostrophecms/ui/ui/apos/components/AposCellContextMenu.vue +2 -0
  115. package/modules/@apostrophecms/ui/ui/apos/components/AposCellLabels.vue +1 -0
  116. package/modules/@apostrophecms/ui/ui/apos/components/AposCloudUploadIcon.vue +5 -5
  117. package/modules/@apostrophecms/ui/ui/apos/components/AposCombo.vue +7 -5
  118. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +8 -5
  119. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +5 -3
  120. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +22 -2
  121. package/modules/@apostrophecms/ui/ui/apos/components/AposEmptyState.vue +3 -1
  122. package/modules/@apostrophecms/ui/ui/apos/components/AposFile.vue +5 -1
  123. package/modules/@apostrophecms/ui/ui/apos/components/AposFilterMenu.vue +2 -1
  124. package/modules/@apostrophecms/ui/ui/apos/components/AposLabel.vue +1 -0
  125. package/modules/@apostrophecms/ui/ui/apos/components/AposMinMaxCount.vue +1 -0
  126. package/modules/@apostrophecms/ui/ui/apos/components/AposPager.vue +1 -0
  127. package/modules/@apostrophecms/ui/ui/apos/components/AposPagerDots.vue +3 -1
  128. package/modules/@apostrophecms/ui/ui/apos/components/AposSlat.vue +15 -2
  129. package/modules/@apostrophecms/ui/ui/apos/components/AposSlatList.vue +3 -1
  130. package/modules/@apostrophecms/ui/ui/apos/components/AposSpinner.vue +33 -7
  131. package/modules/@apostrophecms/ui/ui/apos/components/AposSubformPreview.vue +3 -2
  132. package/modules/@apostrophecms/ui/ui/apos/components/AposTag.vue +5 -3
  133. package/modules/@apostrophecms/ui/ui/apos/components/AposTagApply.vue +5 -2
  134. package/modules/@apostrophecms/ui/ui/apos/components/AposTagList.vue +5 -1
  135. package/modules/@apostrophecms/ui/ui/apos/components/AposTagListItem.vue +9 -1
  136. package/modules/@apostrophecms/ui/ui/apos/components/AposToggle.vue +13 -13
  137. package/modules/@apostrophecms/ui/ui/apos/components/AposTree.vue +1 -0
  138. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeRows.vue +17 -7
  139. package/modules/@apostrophecms/ui/ui/apos/lib/vue.js +4 -0
  140. package/modules/@apostrophecms/ui/ui/apos/scss/global/_admin.scss +1 -1
  141. package/modules/@apostrophecms/ui/ui/apos/scss/global/_inputs.scss +28 -5
  142. package/modules/@apostrophecms/ui/ui/apos/scss/global/_scrollbars.scss +16 -0
  143. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tables.scss +8 -3
  144. package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +9 -8
  145. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tooltips.scss +13 -7
  146. package/modules/@apostrophecms/ui/ui/apos/scss/global/import-all.scss +1 -1
  147. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_input_mixins.scss +5 -3
  148. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_mixins.scss +1 -0
  149. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_responsive.scss +4 -3
  150. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_theme_mixins.scss +6 -0
  151. package/modules/@apostrophecms/ui/ui/apos/scss/shared/_table-rows.scss +6 -3
  152. package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +180 -0
  153. package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +2 -2
  154. package/package.json +4 -4
  155. package/test/modules/@apostrophecms/search/views/index.html +1 -0
  156. package/test/pages.js +227 -0
  157. package/test/schemas.js +184 -0
  158. package/test/search.js +49 -13
@@ -248,18 +248,22 @@ export default {
248
248
  <style lang="scss" scoped>
249
249
  .apos-media-uploader {
250
250
  @include apos-button-reset();
251
- box-sizing: border-box;
251
+ @include apos-transition();
252
+
252
253
  display: flex;
254
+ box-sizing: border-box;
253
255
  align-items: center;
254
256
  justify-content: center;
255
257
  border: 2px dashed var(--a-base-3);
258
+ color: inherit;
256
259
  grid-column: 1 / 3;
257
260
  grid-row: 1 / 3;
258
- @include apos-transition();
259
- color: inherit;
260
261
  }
262
+
261
263
  .apos-media-uploader--enabled {
262
264
  &::after {
265
+ @include apos-transition($duration: 0.3s);
266
+
263
267
  z-index: $z-index-under;
264
268
  position: absolute;
265
269
  content: '';
@@ -276,7 +280,6 @@ export default {
276
280
  5% 100%;
277
281
  background-repeat: no-repeat;
278
282
  filter: blur(10px);
279
- @include apos-transition($duration: 0.3s);
280
283
  }
281
284
 
282
285
  &:hover,
@@ -289,8 +292,9 @@ export default {
289
292
  width: 102%;
290
293
  height: 102%;
291
294
  }
295
+
292
296
  .apos-media-uploader__icon {
293
- fill: url(#apos-upload-gradient);
297
+ fill: url("#apos-upload-gradient");
294
298
  transform: translateY(-2px);
295
299
  }
296
300
  }
@@ -303,21 +307,22 @@ export default {
303
307
 
304
308
  .apos-media-uploader__inner {
305
309
  display: flex;
306
- width: 100%;
307
- height: 100%;
308
310
  flex-direction: column;
309
311
  align-items: center;
310
312
  justify-content: center;
313
+ width: 100%;
314
+ height: 100%;
311
315
  background-color: var(--a-background-primary);
312
316
  }
313
317
 
314
318
  .apos-media-uploader__icon {
319
+ @include apos-transition($duration: 0.2s);
320
+
315
321
  width: 57px;
316
322
  max-width: 50%;
317
323
  height: auto;
318
324
  margin-bottom: 5px;
319
325
  fill: var(--a-text-primary);
320
- @include apos-transition($duration: 0.2s);
321
326
  }
322
327
 
323
328
  .apos-media-uploader__instructions {
@@ -327,13 +332,17 @@ export default {
327
332
  .apos-media-uploader__primary,
328
333
  .apos-media-uploader__secondary {
329
334
  @include apos-p-reset();
335
+
330
336
  text-align: center;
331
337
  }
338
+
332
339
  .apos-media-uploader__secondary {
333
340
  @include type-small;
334
341
  }
342
+
335
343
  .apos-media-uploader__primary {
336
344
  @include type-large;
345
+
337
346
  max-width: 100px;
338
347
  margin: 5px auto 10px;
339
348
  }
@@ -7,7 +7,7 @@ module.exports = {
7
7
  autopublish: true,
8
8
  editRole: 'editor',
9
9
  publishRole: 'editor',
10
- shortcut: 'G,o',
10
+ shortcut: 'G,Shift+I',
11
11
  relationshipSuggestionIcon: 'tag-icon'
12
12
  },
13
13
  fields: {
@@ -99,6 +99,7 @@ export default {
99
99
 
100
100
  &__link {
101
101
  @include type-large;
102
+
102
103
  position: relative;
103
104
  // AposSchema adds $spacing-quadruple margin bottom
104
105
  top: -$spacing-triple;
@@ -64,6 +64,7 @@ export default {
64
64
  flex-direction: column;
65
65
  }
66
66
  }
67
+
67
68
  .apos-login-form__submit :deep(.apos-button) {
68
69
  height: 47px;
69
70
  }
@@ -81,8 +81,8 @@ export default {
81
81
  }
82
82
 
83
83
  .fade-stage-enter-active {
84
- transition: opacity 0.2s linear;
85
- transition-delay: 0.3s;
84
+ transition: opacity 200ms linear;
85
+ transition-delay: 300ms;
86
86
  }
87
87
 
88
88
  .fade-stage-enter-to,
@@ -100,12 +100,12 @@ export default {
100
100
  }
101
101
 
102
102
  .fade-body-enter-active {
103
- transition: all 0.25s linear;
104
- transition-delay: 0.6s;
103
+ transition: all 250ms linear;
104
+ transition-delay: 600ms;
105
105
  }
106
106
 
107
107
  .fade-body-leave-active {
108
- transition: all 0.25s linear;
108
+ transition: all 250ms linear;
109
109
  }
110
110
 
111
111
  .fade-body-enter-to, .fade-body-leave {
@@ -117,8 +117,8 @@ export default {
117
117
  }
118
118
 
119
119
  .fade-outer-enter-active {
120
- transition: opacity 0.4s linear;
121
- transition-delay: 1s;
120
+ transition: opacity 400ms linear;
121
+ transition-delay: 1000ms;
122
122
  }
123
123
 
124
124
  .apos-login {
@@ -134,13 +134,14 @@ export default {
134
134
  right: 0;
135
135
  left: 0;
136
136
  display: flex;
137
- justify-content: space-between;
138
137
  align-items: center;
138
+ justify-content: space-between;
139
139
  padding: $spacing-triple;
140
140
  }
141
141
 
142
142
  &__link {
143
143
  @include type-large;
144
+
144
145
  display: inline-block;
145
146
  text-decoration: underline;
146
147
  text-underline-offset: 2px;
@@ -200,25 +201,26 @@ export default {
200
201
 
201
202
  &__footer {
202
203
  @include type-base;
204
+
203
205
  position: absolute;
204
206
  right: 0;
205
207
  bottom: 32px;
206
208
  left: 0;
207
209
  display: flex;
208
- width: 100%;
209
- max-width: $login-container;
210
- margin: auto;
211
210
  align-items: center;
212
211
  justify-content: flex-start;
212
+ width: 100%;
213
+ margin: auto;
214
+ max-width: $login-container;
213
215
  }
214
216
 
215
217
  &__project-version {
216
218
  overflow: hidden;
217
- text-overflow: clip;
218
- white-space: nowrap;
219
- color: var(--a-base-5);
220
219
  margin-right: 0;
221
220
  margin-left: auto;
221
+ color: var(--a-base-5);
222
+ text-overflow: clip;
223
+ white-space: nowrap;
222
224
  }
223
225
  }
224
226
  </style>
@@ -71,8 +71,8 @@ export default {
71
71
  z-index: $z-index-manager-display;
72
72
  display: flex;
73
73
  flex-direction: column;
74
- justify-content: center;
75
74
  align-items: flex-start;
75
+ justify-content: center;
76
76
  }
77
77
 
78
78
  &__project-header {
@@ -84,6 +84,7 @@ export default {
84
84
 
85
85
  &__project-subtitle {
86
86
  @include type-title;
87
+
87
88
  margin: 0;
88
89
  opacity: 0.6;
89
90
  line-height: 1;
@@ -93,6 +94,7 @@ export default {
93
94
 
94
95
  &__project-name {
95
96
  @include type-display;
97
+
96
98
  margin: 0;
97
99
  color: var(--a-text-primary);
98
100
  text-transform: capitalize;
@@ -100,6 +102,7 @@ export default {
100
102
 
101
103
  &__project-env {
102
104
  @include type-base;
105
+
103
106
  text-transform: capitalize;
104
107
  padding: 6px 12px;
105
108
  color: var(--a-white);
@@ -117,6 +120,7 @@ export default {
117
120
 
118
121
  &--help {
119
122
  @include type-label;
123
+
120
124
  margin-top: $spacing-double;
121
125
  text-align: center;
122
126
  white-space: pre-line;
@@ -124,10 +128,11 @@ export default {
124
128
 
125
129
  &--error {
126
130
  @include type-help;
127
- color: var(--a-danger);
128
- min-height: 13px;
131
+
129
132
  margin-top: 20px;
130
133
  margin-bottom: 15px;
134
+ color: var(--a-danger);
135
+ min-height: 13px;
131
136
  }
132
137
 
133
138
  &__header--center {
@@ -148,7 +153,7 @@ export default {
148
153
  }
149
154
 
150
155
  .apos-login__project-name {
151
- // stylelint-disable-next-line scale-unlimited/declaration-strict-value
156
+ // stylelint-disable-next-line declaration-property-unit-allowed-list
152
157
  font-size: 21px;
153
158
  }
154
159
 
@@ -1,4 +1,5 @@
1
1
  import createApp from 'Modules/@apostrophecms/ui/lib/vue';
2
+ import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
2
3
 
3
4
  export default function() {
4
5
  const component = apos.vueComponents.TheAposModals;
@@ -6,65 +7,16 @@ export default function() {
6
7
  if (!el) {
7
8
  return;
8
9
  }
9
- const app = createApp(component, {
10
- modals: apos.modal.modals
11
- });
12
- const theAposModals = app.mount(el);
10
+ const app = createApp(component);
11
+ app.mount(el);
13
12
 
14
- apos.modal.execute = theAposModals.execute;
15
- apos.modal.getAt = theAposModals.getAt;
16
- apos.modal.getProperties = theAposModals.getProperties;
17
- apos.modal.onTopOf = onTopOf;
18
- apos.modal.stack = [];
19
- apos.confirm = theAposModals.confirm;
20
- apos.alert = theAposModals.alert;
21
- }
13
+ const modalStore = useModalStore();
22
14
 
23
- // Returns true if el1 is "on top of" el2 in the
24
- // modal stack, as viewed by the user. If el1 is a
25
- // modal that appears later in the stack than el2
26
- // (visually stacked on top), this method returns true.
27
- // If el2 is `document` and el1 is a modal, this
28
- // method returns true. For convenenience, if el1
29
- // or el2 is not a modal, it is treated as its DOM
30
- // parent modal, or as `document`. If el1 has no
31
- // parent modal this method always returns false.
32
- //
33
- // If el1 is no longer connected to the DOM then it
34
- // is also considered to be "on top" e.g. not something
35
- // that should concern `v-click-outside-element` and
36
- // similar functionality. This is necessary because
37
- // sometimes Vue removes elements from the DOM before
38
- // we can examine their relationships.
39
- function onTopOf(el1, el2) {
40
- if (el2.matches('[data-apos-menu]')) {
41
- return false;
42
- }
43
- if (!el1.isConnected) {
44
- // If el1 is no longer in the DOM we can't make a proper determination,
45
- // returning true prevents unwanted things like click-outside-element
46
- // events from firing
47
- return true;
48
- }
49
- if (!el1.matches('[data-apos-modal]')) {
50
- el1 = el1.closest('[data-apos-modal]') || document;
51
- }
52
- if (!el2.matches('[data-apos-modal]')) {
53
- el2 = el2.closest('[data-apos-modal]') || document;
54
- }
55
- if (el1 === document) {
56
- return false;
57
- }
58
- if (el2 === document) {
59
- return true;
60
- }
61
- const index1 = apos.modal.stack.findIndex(modal => modal.modalEl === el1);
62
- const index2 = apos.modal.stack.findIndex(modal => modal.modalEl === el2);
63
- if (index1 === -1) {
64
- throw new Error('apos.modal.onTopOf: el1 is not in the modal stack');
65
- }
66
- if (index2 === -1) {
67
- throw new Error('apos.modal.onTopOf: el2 is not in the modal stack');
68
- }
69
- return index1 > index2;
15
+ apos.modal.execute = modalStore.execute;
16
+ apos.modal.get = modalStore.get;
17
+ apos.modal.getAt = modalStore.getAt;
18
+ apos.modal.getProperties = modalStore.getProperties;
19
+ apos.modal.onTopOf = modalStore.onTopOf;
20
+ apos.confirm = modalStore.confirm;
21
+ apos.alert = modalStore.alert;
70
22
  }
@@ -330,6 +330,7 @@ export default {
330
330
  :deep(.apos-field--search) {
331
331
  width: 250px;
332
332
  }
333
+
333
334
  :deep(.apos-input) {
334
335
  height: 32px;
335
336
  }
@@ -11,16 +11,17 @@
11
11
  :class="classes"
12
12
  role="dialog"
13
13
  aria-modal="true"
14
- :aria-labelledby="state.id"
14
+ :aria-labelledby="props.modalId"
15
15
  data-apos-modal
16
16
  @focus.capture="storeFocusedElement"
17
- @keydown="onKeydown"
17
+ @esc="close"
18
+ @keydown.tab="onTab"
18
19
  >
19
20
  <transition :name="transitionType">
20
21
  <div
21
22
  v-if="modal.showModal"
22
23
  class="apos-modal__overlay"
23
- @click="close"
24
+ @click="emit('esc')"
24
25
  />
25
26
  </transition>
26
27
  <transition :name="transitionType" @after-leave="$emit('inactive')">
@@ -44,7 +45,7 @@
44
45
  <div v-if="hasSlot('secondaryControls')" class="apos-modal__controls--secondary">
45
46
  <slot name="secondaryControls" />
46
47
  </div>
47
- <h2 :id="state.id" class="apos-modal__heading">
48
+ <h2 :id="props.modalId" class="apos-modal__heading">
48
49
  <span v-if="modal.a11yTitle" class="apos-sr-only">
49
50
  {{ $t(modal.a11yTitle) }}
50
51
  </span>
@@ -96,17 +97,15 @@
96
97
  // transition.
97
98
 
98
99
  import {
99
- ref, reactive, onMounted, computed, watch, nextTick, useSlots
100
+ ref, onMounted, onUnmounted, computed, watch, nextTick, useSlots
100
101
  } from 'vue';
101
102
  import { useAposFocus } from 'Modules/@apostrophecms/modal/composables/AposFocus';
102
- import cuid from 'cuid';
103
+ import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
103
104
 
104
105
  const {
105
106
  cycleElementsToFocus,
106
- elementsToFocus,
107
107
  focusElement,
108
108
  focusLastModalFocusedElement,
109
- focusedElement,
110
109
  isElementVisible,
111
110
  storeFocusedElement
112
111
  } = useAposFocus();
@@ -119,18 +118,18 @@ const props = defineProps({
119
118
  modalTitle: {
120
119
  type: [ String, Object ],
121
120
  default: ''
121
+ },
122
+ modalId: {
123
+ type: String,
124
+ required: true
122
125
  }
123
126
  });
124
127
 
128
+ const store = useModalStore();
129
+
125
130
  const slots = useSlots();
126
131
  const emit = defineEmits([ 'inactive', 'esc', 'show-modal', 'no-modal', 'ready' ]);
127
132
  const modalEl = ref(null);
128
- const state = reactive({
129
- id: `modal:${cuid()}`,
130
- elementsToFocus,
131
- focusedElement,
132
- modalEl
133
- });
134
133
 
135
134
  const transitionType = computed(() => {
136
135
  if (props.modal.type !== 'slide') {
@@ -212,10 +211,17 @@ watch(triggerFocusRefresh, (newVal) => {
212
211
  }
213
212
  });
214
213
 
215
- onMounted(() => {
214
+ onMounted(async () => {
215
+ await nextTick();
216
216
  if (shouldTrapFocus.value) {
217
- nextTick(trapFocus);
217
+ trapFocus();
218
218
  }
219
+ store.updateModalData(props.modalId, { modalEl: modalEl.value });
220
+ window.addEventListener('keydown', onKeydown);
221
+ });
222
+
223
+ onUnmounted(() => {
224
+ window.removeEventListener('keydown', onKeydown);
219
225
  });
220
226
 
221
227
  function onKeydown(e) {
@@ -223,25 +229,24 @@ function onKeydown(e) {
223
229
  if (hasPressedEsc) {
224
230
  close(e);
225
231
  }
226
- cycleElementsToFocus(e);
232
+ }
233
+
234
+ function onTab(e) {
235
+ const currentModal = store.get(props.modalId);
236
+ cycleElementsToFocus(e, currentModal.elementsToFocus);
227
237
  }
228
238
 
229
239
  async function onEnter() {
230
240
  emit('show-modal');
231
- apos.modal.stack = apos.modal.stack || [];
232
241
 
233
- apos.modal.stack.push(state);
234
242
  await nextTick();
235
243
  emit('ready');
236
244
  }
237
245
 
238
246
  function onLeave() {
239
- emit('no-modal');
240
-
241
- apos.modal.stack = apos.modal.stack
242
- .filter(modal => modal.id !== state.id);
243
-
247
+ store.remove(props.modalId);
244
248
  focusLastModalFocusedElement();
249
+ emit('no-modal');
245
250
  }
246
251
 
247
252
  function trapFocus() {
@@ -258,10 +263,13 @@ function trapFocus() {
258
263
  .map(addExcludingAttributes)
259
264
  .join(', ');
260
265
 
261
- elementsToFocus.value = [ ...modalEl.value.querySelectorAll(selector) ]
266
+ const elementsToFocus = [ ...modalEl.value.querySelectorAll(selector) ]
262
267
  .filter(isElementVisible);
263
268
 
264
- focusElement(focusedElement.value, elementsToFocus.value[0]);
269
+ store.updateModalData(props.modalId, { elementsToFocus });
270
+ const currentModal = store.get(props.modalId);
271
+
272
+ focusElement(currentModal.focusedElement, currentModal.elementsToFocus[0]);
265
273
 
266
274
  function addExcludingAttributes(element) {
267
275
  return `${element}:not([tabindex="-1"]):not([disabled]):not([type="hidden"]):not([aria-hidden])`;
@@ -269,10 +277,10 @@ function trapFocus() {
269
277
  }
270
278
 
271
279
  function close() {
272
- if (apos.modal.stack.at(-1)?.id !== state.id) {
273
- return;
280
+ const activeModalId = store.activeModal?.id;
281
+ if (activeModalId === props.modalId) {
282
+ emit('esc');
274
283
  }
275
- emit('esc');
276
284
  }
277
285
  </script>
278
286
 
@@ -282,10 +290,7 @@ function close() {
282
290
  .apos-modal__inner {
283
291
  z-index: $z-index-modal;
284
292
  position: fixed;
285
- top: $spacing-base;
286
- right: $spacing-base;
287
- bottom: $spacing-base;
288
- left: $spacing-base;
293
+ inset: $spacing-base $spacing-base $spacing-base $spacing-base;
289
294
  display: grid;
290
295
  grid-template-rows: auto 1fr auto;
291
296
  height: calc(100vh - #{$spacing-base * 2});
@@ -295,24 +300,21 @@ function close() {
295
300
  color: var(--a-text-primary);
296
301
 
297
302
  @include media-up(lap) {
298
- top: $spacing-double;
299
- right: $spacing-double;
300
- bottom: $spacing-double;
301
- left: $spacing-double;
303
+ inset: $spacing-double $spacing-double $spacing-double $spacing-double;
302
304
  height: calc(100vh - #{$spacing-double * 2});
303
305
  }
304
306
 
305
307
  .apos-modal--slide & {
306
308
  position: fixed;
307
- transition: transform 0.15s ease;
308
309
  top: 0;
309
310
  bottom: 0;
310
- transform: translateX(0);
311
311
  width: 100%;
312
- border-radius: 0;
313
312
  height: 100vh;
313
+ transition: transform 200ms ease;
314
+ transform: translateX(0);
315
+ border-radius: 0;
314
316
 
315
- @media screen and (min-width: 800px) {
317
+ @include media-up(hands-wide) {
316
318
  max-width: 540px;
317
319
  }
318
320
  }
@@ -328,19 +330,19 @@ function close() {
328
330
  }
329
331
 
330
332
  &.apos-modal__inner--two-thirds {
331
- @media screen and (min-width: 800px) {
333
+ @include media-up(hands-wide) {
332
334
  max-width: 66%;
333
335
  }
334
336
  }
335
337
 
336
338
  &.apos-modal__inner--half {
337
- @media screen and (min-width: 800px) {
339
+ @include media-up(hands-wide) {
338
340
  max-width: 50%;
339
341
  }
340
342
  }
341
343
 
342
344
  &.apos-modal__inner--full {
343
- @media screen and (min-width: 800px) {
345
+ @include media-up(hands-wide) {
344
346
  max-width: 100%;
345
347
  }
346
348
  }
@@ -357,7 +359,7 @@ function close() {
357
359
 
358
360
  .apos-modal--overlay & {
359
361
  transform: scale(1);
360
- transition: opacity 0.15s ease, transform 0.15s ease;
362
+ transition: opacity 200ms ease, transform 200ms ease;
361
363
  }
362
364
 
363
365
  &.fade-enter-from,
@@ -384,15 +386,12 @@ function close() {
384
386
  .apos-modal__overlay {
385
387
  z-index: $z-index-modal;
386
388
  position: fixed;
387
- top: 0;
388
- right: 0;
389
- bottom: 0;
390
- left: 0;
389
+ inset: 0;
391
390
  background-color: var(--a-overlay-modal);
392
391
 
393
392
  .apos-modal--slide &,
394
393
  .apos-modal--overlay & {
395
- transition: opacity 0.15s ease;
394
+ transition: opacity 200ms ease;
396
395
  }
397
396
 
398
397
  &.slide-left-enter-from,
@@ -425,8 +424,8 @@ function close() {
425
424
  .apos-modal__footer__inner,
426
425
  .apos-modal__header__main {
427
426
  display: flex;
428
- padding: $spacing-double;
429
427
  align-items: center;
428
+ padding: $spacing-double;
430
429
  }
431
430
 
432
431
  .apos-modal__header__main {
@@ -453,9 +452,10 @@ function close() {
453
452
  }
454
453
 
455
454
  .apos-modal__controls--header {
456
- justify-content: flex-end;
457
455
  flex-grow: 1;
456
+ justify-content: flex-end;
458
457
  }
458
+
459
459
  :deep(.apos-modal__controls--primary) {
460
460
  & > .apos-button__wrapper,
461
461
  & > .apos-context-menu {
@@ -465,6 +465,7 @@ function close() {
465
465
 
466
466
  .apos-modal__locale {
467
467
  @include type-base;
468
+
468
469
  margin-right: $spacing-double;
469
470
  font-weight: var(--a-weight-bold);
470
471
  }
@@ -475,6 +476,7 @@ function close() {
475
476
 
476
477
  .apos-modal__heading {
477
478
  @include type-title;
479
+
478
480
  margin: 0;
479
481
  }
480
482
 
@@ -484,6 +486,7 @@ function close() {
484
486
 
485
487
  .apos-modal__main--with-rails {
486
488
  grid-template-columns: 15% 1fr minmax(200px, 10%);
489
+
487
490
  @include media-up(lap) {
488
491
  grid-template-columns: 15% 1fr minmax(250px, $modal-rail-right-w);
489
492
  }
@@ -499,14 +502,15 @@ function close() {
499
502
 
500
503
  .apos-modal--busy .apos-modal__inner {
501
504
  $height: 190px;
505
+
502
506
  top: 50%;
503
507
  bottom: -50%;
504
508
  display: flex;
505
- height: $height;
506
- transform: translateY(math.div($height, 2) * -1);
507
- justify-content: center;
508
509
  align-items: center;
510
+ justify-content: center;
511
+ height: $height;
509
512
  text-align: center;
513
+ transform: translateY(math.div($height, 2) * -1);
510
514
  }
511
515
 
512
516
  .apos-modal__busy-text {
@@ -29,6 +29,7 @@ export default {
29
29
  .apos-modal__body {
30
30
  overflow-y: auto;
31
31
  padding: $spacing-double;
32
+
32
33
  @include media-up(lap) {
33
34
  padding: $spacing-quadruple;
34
35
  }