apostrophe 3.63.1 → 4.0.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 (150) hide show
  1. package/.eslintrc +13 -4
  2. package/CHANGELOG.md +35 -0
  3. package/defaults.js +1 -0
  4. package/modules/@apostrophecms/admin-bar/ui/apos/apps/AposAdminBar.js +7 -17
  5. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBar.vue +14 -16
  6. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +1 -1
  7. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarMenu.vue +22 -15
  8. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarUser.vue +2 -2
  9. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +13 -8
  10. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +18 -10
  11. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +4 -4
  12. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextUndoRedo.vue +14 -8
  13. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposSavingIndicator.vue +2 -1
  14. package/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js +36 -54
  15. package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +20 -25
  16. package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +5 -12
  17. package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +11 -3
  18. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +6 -6
  19. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenuItem.vue +3 -2
  20. package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +31 -44
  21. package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +6 -6
  22. package/modules/@apostrophecms/asset/index.js +25 -12
  23. package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +3 -3
  24. package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.vue.js +7 -1
  25. package/modules/@apostrophecms/busy/ui/apos/apps/AposBusy.js +8 -7
  26. package/modules/@apostrophecms/busy/ui/apos/components/TheAposBusy.vue +1 -1
  27. package/modules/@apostrophecms/command-menu/ui/apos/apps/AposCommandMenu.js +11 -29
  28. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuShortcut.vue +6 -6
  29. package/modules/@apostrophecms/command-menu/ui/apos/components/TheAposCommandMenu.vue +10 -7
  30. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +20 -15
  31. package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +1 -1
  32. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +36 -27
  33. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalizeErrors.vue +3 -3
  34. package/modules/@apostrophecms/image/ui/apos/components/AposImageCropper.vue +5 -5
  35. package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +6 -6
  36. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +23 -16
  37. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerDisplay.vue +11 -11
  38. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +28 -21
  39. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerSelections.vue +1 -1
  40. package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploader.vue +5 -4
  41. package/modules/@apostrophecms/login/ui/apos/apps/AposLogin.js +6 -7
  42. package/modules/@apostrophecms/login/ui/apos/components/AposForgotPasswordForm.vue +3 -3
  43. package/modules/@apostrophecms/login/ui/apos/components/AposLoginForm.vue +10 -10
  44. package/modules/@apostrophecms/login/ui/apos/components/AposResetPasswordForm.vue +1 -1
  45. package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +2 -2
  46. package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +60 -87
  47. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +15 -11
  48. package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +8 -2
  49. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBreadcrumbs.vue +7 -4
  50. package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +5 -5
  51. package/modules/@apostrophecms/modal/ui/apos/components/AposModalShareDraft.vue +8 -8
  52. package/modules/@apostrophecms/modal/ui/apos/components/AposModalToolbar.vue +7 -7
  53. package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +22 -4
  54. package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +95 -0
  55. package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +2 -3
  56. package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +6 -0
  57. package/modules/@apostrophecms/multisite-i18n/i18n/aposMultisite/en.json +48 -0
  58. package/modules/@apostrophecms/multisite-i18n/index.js +7 -0
  59. package/modules/@apostrophecms/notification/index.js +4 -4
  60. package/modules/@apostrophecms/notification/ui/apos/apps/AposNotification.js +6 -9
  61. package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +12 -8
  62. package/modules/@apostrophecms/oembed/index.js +10 -3
  63. package/modules/@apostrophecms/oembed-field/ui/apos/components/AposInputOembed.vue +4 -4
  64. package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +15 -11
  65. package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +1 -1
  66. package/modules/@apostrophecms/permission/ui/apos/components/AposInputRole.vue +3 -3
  67. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +25 -17
  68. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerDisplay.vue +24 -20
  69. package/modules/@apostrophecms/piece-type/ui/apos/components/AposRelationshipEditor.vue +15 -11
  70. package/modules/@apostrophecms/polymorphic-type/index.js +0 -19
  71. package/modules/@apostrophecms/rich-text-widget/index.js +1 -0
  72. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposImageControlDialog.vue +7 -6
  73. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +31 -30
  74. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapAnchor.vue +12 -10
  75. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapLink.vue +9 -8
  76. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +3 -3
  77. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapTable.vue +3 -3
  78. package/modules/@apostrophecms/schema/index.js +30 -1
  79. package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +10 -8
  80. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +5 -3
  81. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +81 -277
  82. package/modules/@apostrophecms/schema/ui/apos/components/AposInputAttachment.vue +4 -2
  83. package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +24 -14
  84. package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +7 -6
  85. package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +10 -7
  86. package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +3 -3
  87. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +5 -4
  88. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +15 -12
  89. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +1 -1
  90. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +16 -12
  91. package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +19 -11
  92. package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +1 -1
  93. package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +65 -21
  94. package/modules/@apostrophecms/schema/ui/apos/components/AposSubform.vue +2 -2
  95. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +0 -4
  96. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArea.js +3 -3
  97. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArray.js +15 -4
  98. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputAttachment.js +3 -3
  99. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputCheckboxes.js +7 -7
  100. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputColor.js +5 -8
  101. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputDateAndTime.js +1 -1
  102. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputObject.js +1 -1
  103. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRadio.js +1 -1
  104. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +12 -9
  105. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSelect.js +2 -2
  106. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +6 -8
  107. package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +39 -13
  108. package/modules/@apostrophecms/schema/ui/apos/logic/AposSubform.js +1 -1
  109. package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +9 -9
  110. package/modules/@apostrophecms/schema/ui/apos/scss/AposInputArray.scss +205 -0
  111. package/modules/@apostrophecms/settings/ui/apos/components/AposSettingsManager.vue +4 -4
  112. package/modules/@apostrophecms/settings/ui/apos/logic/AposSettingsManager.js +4 -4
  113. package/modules/@apostrophecms/submitted-draft/ui/apos/components/AposSubmittedDraftIcon.vue +5 -4
  114. package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +4 -4
  115. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonGroup.vue +6 -6
  116. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonSplit.vue +120 -113
  117. package/modules/@apostrophecms/ui/ui/apos/components/AposCheckbox.vue +19 -19
  118. package/modules/@apostrophecms/ui/ui/apos/components/AposCombo.vue +15 -15
  119. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +216 -191
  120. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +77 -65
  121. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +1 -1
  122. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuTip.vue +28 -50
  123. package/modules/@apostrophecms/ui/ui/apos/components/AposFile.vue +5 -5
  124. package/modules/@apostrophecms/ui/ui/apos/components/AposFilterMenu.vue +4 -4
  125. package/modules/@apostrophecms/ui/ui/apos/components/AposMinMaxCount.vue +5 -5
  126. package/modules/@apostrophecms/ui/ui/apos/components/AposPager.vue +14 -8
  127. package/modules/@apostrophecms/ui/ui/apos/components/AposSlat.vue +2 -2
  128. package/modules/@apostrophecms/ui/ui/apos/components/AposSlatList.vue +53 -59
  129. package/modules/@apostrophecms/ui/ui/apos/components/AposSubformPreview.vue +2 -2
  130. package/modules/@apostrophecms/ui/ui/apos/components/AposTagApply.vue +40 -35
  131. package/modules/@apostrophecms/ui/ui/apos/components/AposToggle.vue +2 -2
  132. package/modules/@apostrophecms/ui/ui/apos/components/AposTree.vue +9 -11
  133. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeHeader.vue +5 -3
  134. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeRows.vue +129 -129
  135. package/modules/@apostrophecms/ui/ui/apos/composables/AposTheme.js +11 -0
  136. package/modules/@apostrophecms/ui/ui/apos/lib/click-outside-element.js +4 -4
  137. package/modules/@apostrophecms/ui/ui/apos/lib/i18next.js +56 -50
  138. package/modules/@apostrophecms/ui/ui/apos/lib/tooltip.js +191 -0
  139. package/modules/@apostrophecms/ui/ui/apos/lib/vue.js +19 -10
  140. package/modules/@apostrophecms/ui/ui/apos/mixins/AposAdvisoryLockMixin.js +1 -1
  141. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tables.scss +1 -1
  142. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tooltips.scss +6 -22
  143. package/modules/@apostrophecms/ui/ui/apos/scss/shared/_table-rows.scss +1 -1
  144. package/modules/@apostrophecms/widget-type/index.js +8 -2
  145. package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +26 -22
  146. package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +4 -4
  147. package/package.json +31 -44
  148. package/test/schemas.js +10 -4
  149. package/modules/@apostrophecms/ui/ui/apos/lib/localized-v-tooltip.js +0 -63
  150. package/modules/@apostrophecms/ui/ui/apos/lib/tooltip-options.js +0 -13
@@ -0,0 +1,191 @@
1
+ // Vue plugin. Create a new directive with i18n support by applying the decorator
2
+ import { $t } from './i18next';
3
+ import {
4
+ computePosition, arrow, offset, shift
5
+ } from '@floating-ui/dom';
6
+ import cuid from 'cuid';
7
+ import { isEqual } from 'lodash';
8
+
9
+ const getTooltipHtml = (id, tooltip) =>
10
+ `<div id="${id}" class="apos-tooltip" role="tooltip">
11
+ <div class="apos-tooltip__wrapper">
12
+ <div class="apos-tooltip__arrow"></div>
13
+ <div class="apos-tooltip__inner">
14
+ ${tooltip}
15
+ </div>
16
+ </div>
17
+ </div>`;
18
+
19
+ export default {
20
+ install(app) {
21
+ app.directive('apos-tooltip', {
22
+ mounted(el, binding, vnodes) {
23
+ addEventListeners(el, binding);
24
+ },
25
+ updated(el, binding) {
26
+ const contentValue = Object.hasOwn(binding.value || {}, 'content')
27
+ ? binding.value.content
28
+ : binding.value;
29
+ const oldValue = Object.hasOwn(binding.oldValue || {}, 'content')
30
+ ? binding.oldValue.content
31
+ : binding.oldValue;
32
+
33
+ if (isEqual(contentValue, oldValue)) {
34
+ return;
35
+ }
36
+
37
+ if (el.aposShowTooltipListener) {
38
+ removeEventListeners(el);
39
+ }
40
+
41
+ addEventListeners(el, binding);
42
+ },
43
+ beforeUnmount(el, binding) {
44
+ removeEventListeners(el);
45
+ }
46
+ });
47
+
48
+ function addEventListeners(el, binding) {
49
+ let tooltipTimeout;
50
+ let delayTimeout;
51
+ if (!binding.value && !binding.value?.content) {
52
+ return;
53
+ }
54
+
55
+ const delay = binding.value?.delay;
56
+ const localized = localize(binding.value, app);
57
+ if (!localized) {
58
+ return;
59
+ }
60
+ const tooltipId = `tooltip__${cuid()}`;
61
+
62
+ // Attach event listeners to elements to retrieve them in beforeUnmount
63
+ el.aposShowTooltipListener = setupShowTooltip({
64
+ el,
65
+ value: binding.value,
66
+ tooltipTimeout,
67
+ delayTimeout,
68
+ tooltipId,
69
+ localized
70
+ });
71
+ el.aposHideTooltipListener = setupHideTooltip({
72
+ tooltipId,
73
+ tooltipTimeout,
74
+ delayTimeout,
75
+ delay
76
+ });
77
+
78
+ el.addEventListener('mouseenter', el.aposShowTooltipListener);
79
+ el.addEventListener('mouseleave', el.aposHideTooltipListener);
80
+ el.addEventListener('click', el.aposHideTooltipListener);
81
+
82
+ }
83
+
84
+ function removeEventListeners(el) {
85
+ if (el.aposHideTooltipListener) {
86
+ el.aposHideTooltipListener(true);
87
+ }
88
+ el.removeEventListener('mouseenter', el.aposShowTooltipListener);
89
+ el.removeEventListener('mouseleave', el.aposHideTooltipListener);
90
+ el.removeEventListener('click', el.aposHideTooltipListener);
91
+ }
92
+
93
+ function setupShowTooltip({
94
+ el, value, tooltipTimeout, delayTimeout, tooltipId, localized
95
+ }) {
96
+ return async () => {
97
+ if (tooltipTimeout) {
98
+ clearTimeout(tooltipTimeout);
99
+ }
100
+ if (delayTimeout) {
101
+ clearTimeout(delayTimeout);
102
+ }
103
+
104
+ const existingEl = document.querySelector(`#${tooltipId}`);
105
+ if (!existingEl) {
106
+ document.body.insertAdjacentHTML('beforeend', getTooltipHtml(tooltipId, localized));
107
+ } else {
108
+ existingEl.setAttribute('aria-hidden', false);
109
+ }
110
+
111
+ const tooltipEl = existingEl || document.querySelector(`#${tooltipId}`);
112
+ if (!tooltipEl) {
113
+ return;
114
+ }
115
+
116
+ const arrowEl = tooltipEl.querySelector('.apos-tooltip__arrow');
117
+
118
+ const {
119
+ x, y, middlewareData, placement
120
+ } = await computePosition(el, tooltipEl, {
121
+ placement: value.placement || 'bottom-end',
122
+ middleware: [
123
+ offset(11),
124
+ shift({ padding: 5 }),
125
+ arrow({
126
+ element: arrowEl,
127
+ padding: 10
128
+ })
129
+ ]
130
+ });
131
+
132
+ const [ sidePosition ] = placement.split('-');
133
+
134
+ const { x: arrowX, y: arrowY } = middlewareData.arrow;
135
+ if (!existingEl) {
136
+ tooltipEl.setAttribute('x-placement', sidePosition);
137
+ tooltipEl.setAttribute('aria-hidden', false);
138
+ }
139
+ Object.assign(tooltipEl.style, {
140
+ left: `${x}px`,
141
+ top: `${y}px`
142
+ });
143
+
144
+ Object.assign(arrowEl.style, {
145
+ ...arrowX && { left: `${arrowX}px` },
146
+ ...arrowY && { top: `${arrowY}px` }
147
+ });
148
+ };
149
+ }
150
+
151
+ function setupHideTooltip({
152
+ tooltipId, tooltipTimeout, delayTimeout, delay
153
+ }) {
154
+ return (immediate = false) => {
155
+ const tooltipEl = document.querySelector(`#${tooltipId}`);
156
+ if (!tooltipEl) {
157
+ return;
158
+ }
159
+
160
+ if (immediate) {
161
+ tooltipEl.remove();
162
+ return;
163
+ }
164
+
165
+ if (delay) {
166
+ delayTimeout = setTimeout(() => {
167
+ tooltipEl.setAttribute('aria-hidden', true);
168
+ }, delay);
169
+ } else {
170
+ tooltipEl.setAttribute('aria-hidden', true);
171
+ }
172
+
173
+ tooltipTimeout = setTimeout(() => {
174
+ tooltipEl.remove();
175
+ }, 5000);
176
+ };
177
+ }
178
+
179
+ function localize(value) {
180
+ if (!value) {
181
+ return;
182
+ }
183
+
184
+ if (value.content) {
185
+ return (value.localize === false) ? value.content : $t(value.content);
186
+ }
187
+
188
+ return $t(value);
189
+ }
190
+ }
191
+ };
@@ -1,14 +1,23 @@
1
- import Vue from 'vue';
1
+ import { createApp } from 'vue';
2
2
  import ClickOutsideElement from './click-outside-element';
3
- import LocalizedVTooltip from './localized-v-tooltip';
4
- import tooltipOptions from './tooltip-options';
3
+ import Tooltip from './tooltip';
5
4
  import VueAposI18Next from './i18next';
6
5
 
7
- Vue.use(LocalizedVTooltip, tooltipOptions);
8
- Vue.use(ClickOutsideElement);
9
- Vue.use(VueAposI18Next, {
10
- // Module aliases are not available yet when this code executes
11
- i18n: apos.modules['@apostrophecms/i18n']
12
- });
6
+ export default (appConfig, props = {}) => {
7
+ const app = createApp(appConfig, props);
13
8
 
14
- export default Vue;
9
+ app.use(VueAposI18Next, {
10
+ // Module aliases are not available yet when this code executes
11
+ i18n: apos.modules['@apostrophecms/i18n']
12
+ });
13
+ app.use(Tooltip);
14
+ app.use(ClickOutsideElement);
15
+
16
+ const sources = [ window.apos.vueComponents, window.apos.iconComponents ];
17
+ for (const source of sources) {
18
+ for (const [ name, component ] of Object.entries(source)) {
19
+ app.component(name, component);
20
+ }
21
+ }
22
+ return app;
23
+ };
@@ -12,7 +12,7 @@ export default {
12
12
  lockApiUrl: null
13
13
  };
14
14
  },
15
- async destroyed () {
15
+ async unmounted () {
16
16
  await this.unlock();
17
17
  },
18
18
  methods: {
@@ -43,7 +43,7 @@ span.apos-table__header-label:hover {
43
43
  cursor: auto;
44
44
  }
45
45
 
46
- .apos-table ::v-deep .apos-choice-label {
46
+ .apos-table :deep(.apos-choice-label) {
47
47
  margin-top: 0;
48
48
  }
49
49
 
@@ -2,7 +2,9 @@
2
2
  // https://github.com/Akryum/v-tooltip/blob/83615e394c96ca491a4df04b892ae87e833beb97/demo-src/src/App.vue#L179-L303
3
3
  .apos-tooltip {
4
4
  z-index: $z-index-notifications;
5
+ position: absolute;
5
6
  display: block;
7
+ width: max-content;
6
8
  max-width: 285px;
7
9
  /* stylelint-disable-next-line time-min-milliseconds */
8
10
  transition-delay: 0.1s;
@@ -32,6 +34,7 @@
32
34
 
33
35
  .apos-tooltip__inner {
34
36
  @include type-small;
37
+
35
38
  z-index: $z-index-default;
36
39
  position: relative;
37
40
  padding: 8px 10px;
@@ -46,7 +49,6 @@
46
49
  position: absolute;
47
50
  width: 8px;
48
51
  height: 8px;
49
- margin: 5px;
50
52
  border-radius: 1px;
51
53
  // Solid border style needed to work with v-apos-tooltip placement.
52
54
  border-style: solid;
@@ -56,50 +58,31 @@
56
58
  }
57
59
 
58
60
  &[x-placement^='top'] {
59
- margin-bottom: 5px;
60
-
61
61
  .apos-tooltip__arrow {
62
62
  bottom: -4px;
63
- left: calc(50% - 5px);
64
- margin-top: 0;
65
- margin-bottom: 0;
66
63
  }
67
64
  }
68
65
 
69
66
  &[x-placement^='bottom'] {
70
- margin-top: 5px;
71
-
72
67
  .apos-tooltip__arrow {
73
68
  top: -3px;
74
- left: calc(50% - 5px);
75
- margin-top: 0;
76
- margin-bottom: 0;
77
69
  }
78
70
  }
79
71
 
80
72
  &[x-placement^='right'] {
81
- margin-left: 5px;
82
-
83
73
  .apos-tooltip__arrow {
84
- top: calc(50% - 5px);
85
74
  left: -3px;
86
- margin-left: 0;
87
- margin-right: 0;
88
75
  }
89
76
  }
90
77
 
91
78
  &[x-placement^='left'] {
92
- margin-right: 5px;
93
-
94
79
  .apos-tooltip__arrow {
95
- top: calc(50% - 5px);
96
80
  right: -3px;
97
- margin-left: 0;
98
- margin-right: 0;
99
81
  }
100
82
  }
101
83
 
102
84
  &[aria-hidden='true'] {
85
+ display: none;
103
86
  visibility: hidden;
104
87
  opacity: 0;
105
88
  transition: opacity 0.15s, visibilty 0.15s;
@@ -109,6 +92,7 @@
109
92
  }
110
93
 
111
94
  &[aria-hidden='false'] {
95
+ display: initial;
112
96
  visibility: visible;
113
97
  opacity: 1;
114
98
  transition: opacity 0.15s;
@@ -123,4 +107,4 @@
123
107
  /* stylelint-disable-next-line time-min-milliseconds */
124
108
  transition-delay: 0.1s;
125
109
  transform: scale(0.8);
126
- }
110
+ }
@@ -26,7 +26,7 @@ span.apos-tree__cell:first-of-type {
26
26
  margin-left: 5px;
27
27
  }
28
28
 
29
- .apos-tree__cell[disabled] {
29
+ .apos-tree__cell[disabled='true'] {
30
30
  color: $input-color-disabled;
31
31
  &:hover {
32
32
  cursor: not-allowed;
@@ -100,7 +100,11 @@ module.exports = {
100
100
  neverLoadSelf: true,
101
101
  initialModal: true,
102
102
  placeholder: false,
103
- placeholderClass: 'apos-placeholder'
103
+ placeholderClass: 'apos-placeholder',
104
+ // two-thirds, half or full:
105
+ width: '',
106
+ // left or right:
107
+ origin: 'right'
104
108
  },
105
109
  init(self) {
106
110
  const badFieldName = Object.keys(self.fields).indexOf('type') !== -1;
@@ -400,7 +404,9 @@ module.exports = {
400
404
  contextual: self.options.contextual,
401
405
  placeholderClass: self.options.placeholderClass,
402
406
  className: self.options.className,
403
- components: self.options.components
407
+ components: self.options.components,
408
+ width: self.options.width,
409
+ origin: self.options.origin
404
410
  });
405
411
  return result;
406
412
  }
@@ -1,13 +1,17 @@
1
1
  <template>
2
2
  <AposModal
3
3
  class="apos-widget-editor"
4
- :modal="modal" :modal-title="editLabel"
5
- @inactive="modal.active = false" @show-modal="modal.showModal = true"
6
- @esc="confirmAndCancel" @no-modal="$emit('safe-close')"
4
+ :modal="modal"
5
+ :modal-title="editLabel"
6
+ @inactive="modal.active = false"
7
+ @show-modal="modal.showModal = true"
8
+ @esc="confirmAndCancel"
9
+ @no-modal="$emit('safe-close')"
7
10
  >
8
11
  <template #breadcrumbs>
9
12
  <AposModalBreadcrumbs
10
- v-if="breadcrumbs && breadcrumbs.length" :items="breadcrumbs"
13
+ v-if="breadcrumbs && breadcrumbs.length"
14
+ :items="breadcrumbs"
11
15
  />
12
16
  </template>
13
17
  <template #main>
@@ -15,15 +19,15 @@
15
19
  <template #bodyMain>
16
20
  <div class="apos-widget-editor__body">
17
21
  <AposSchema
22
+ ref="schema"
18
23
  :trigger-validation="triggerValidation"
19
24
  :schema="schema"
20
- :value="docFields"
25
+ :model-value="docFields"
21
26
  :meta="meta"
22
- @input="updateDocFields"
23
- @validate="triggerValidate"
24
27
  :following-values="followingValues()"
25
28
  :conditional-fields="conditionalFields"
26
- ref="schema"
29
+ @update:model-value="updateDocFields"
30
+ @validate="triggerValidate"
27
31
  />
28
32
  </div>
29
33
  </template>
@@ -31,13 +35,15 @@
31
35
  </template>
32
36
  <template #footer>
33
37
  <AposButton
34
- type="default" label="apostrophe:cancel"
38
+ type="default"
39
+ label="apostrophe:cancel"
35
40
  @click="confirmAndCancel"
36
41
  />
37
42
  <AposButton
38
- type="primary" @click="save"
43
+ type="primary"
39
44
  :label="saveLabel"
40
45
  :disabled="docFields.hasErrors"
46
+ @click="save"
41
47
  />
42
48
  </template>
43
49
  </AposModal>
@@ -68,7 +74,7 @@ export default {
68
74
  required: true,
69
75
  type: Object
70
76
  },
71
- value: {
77
+ modelValue: {
72
78
  required: false,
73
79
  type: Object,
74
80
  default() {
@@ -92,8 +98,10 @@ export default {
92
98
  },
93
99
  emits: [ 'safe-close', 'modal-result' ],
94
100
  data() {
101
+ const moduleOptions = window.apos.modules[apos.area.widgetManagers[this.type]];
102
+
95
103
  return {
96
- id: this.value && this.value._id,
104
+ id: this.modelValue && this.modelValue._id,
97
105
  original: null,
98
106
  docFields: {
99
107
  data: {},
@@ -103,6 +111,8 @@ export default {
103
111
  title: this.editLabel,
104
112
  active: false,
105
113
  type: 'slide',
114
+ width: moduleOptions.width,
115
+ origin: moduleOptions.origin,
106
116
  showModal: false
107
117
  },
108
118
  triggerValidation: false
@@ -151,17 +161,17 @@ export default {
151
161
  ...apos.area.widgetOptions
152
162
  ];
153
163
  },
154
- destroyed() {
164
+ unmounted() {
155
165
  apos.area.widgetOptions = apos.area.widgetOptions.slice(1);
156
166
  },
157
167
  created() {
158
168
  const defaults = this.getDefault();
159
169
 
160
- if (this.value) {
161
- this.original = klona(this.value);
170
+ if (this.modelValue) {
171
+ this.original = klona(this.modelValue);
162
172
  this.docFields.data = {
163
173
  ...defaults,
164
- ...this.value
174
+ ...this.modelValue
165
175
  };
166
176
  return;
167
177
  }
@@ -218,9 +228,3 @@ export default {
218
228
  }
219
229
  };
220
230
  </script>
221
-
222
- <style lang="scss" scoped>
223
- .apos-widget-editor ::v-deep .apos-modal__inner {
224
- max-width: 458px;
225
- }
226
- </style>
@@ -6,7 +6,7 @@ export default {
6
6
  docId: String,
7
7
  type: String,
8
8
  areaFieldId: String,
9
- value: Object,
9
+ modelValue: Object,
10
10
  meta: {
11
11
  type: Object,
12
12
  default() {
@@ -26,7 +26,7 @@ export default {
26
26
  }
27
27
  },
28
28
  watch: {
29
- value: {
29
+ modelValue: {
30
30
  handler() {
31
31
  this.renderContent();
32
32
  }
@@ -50,7 +50,7 @@ export default {
50
50
  apos.bus.$emit('widget-rendering');
51
51
  const parameters = {
52
52
  _docId: this.docId,
53
- widget: this.value,
53
+ widget: this.modelValue,
54
54
  areaFieldId: this.areaFieldId,
55
55
  type: this.type
56
56
  };
@@ -83,7 +83,7 @@ export default {
83
83
  }
84
84
 
85
85
  return {
86
- [placeholderClass]: this.value.aposPlaceholder === true
86
+ [placeholderClass]: this.modelValue.aposPlaceholder === true
87
87
  };
88
88
  }
89
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apostrophe",
3
- "version": "3.63.1",
3
+ "version": "4.0.0",
4
4
  "description": "The Apostrophe Content Management System.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -31,41 +31,28 @@
31
31
  "author": "Apostrophe Technologies, Inc.",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@apostrophecms/vue-color": "^2.8.2",
34
+ "@apostrophecms/vue-material-design-icons": "^1.0.0",
35
+ "@ckpack/vue-color": "^1.4.1",
36
+ "@floating-ui/dom": "^1.5.3",
35
37
  "@opentelemetry/api": "^1.0.4",
36
38
  "@opentelemetry/semantic-conventions": "^1.0.1",
37
- "@tiptap/core": "^2.0.0-beta.220",
38
- "@tiptap/extension-blockquote": "^2.0.0-beta.220",
39
- "@tiptap/extension-bold": "^2.0.0-beta.220",
40
- "@tiptap/extension-bullet-list": "^2.0.0-beta.220",
41
- "@tiptap/extension-code": "^2.0.0-beta.220",
42
- "@tiptap/extension-code-block": "^2.0.0-beta.220",
43
- "@tiptap/extension-dropcursor": "^2.0.0-beta.220",
44
- "@tiptap/extension-floating-menu": "^2.0.0-beta.220",
45
- "@tiptap/extension-gapcursor": "^2.0.0-beta.220",
46
- "@tiptap/extension-hard-break": "^2.0.0-beta.220",
47
- "@tiptap/extension-heading": "^2.0.0-beta.220",
48
- "@tiptap/extension-highlight": "^2.0.0-beta.220",
49
- "@tiptap/extension-history": "^2.0.0-beta.220",
50
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.220",
51
- "@tiptap/extension-italic": "^2.0.0-beta.220",
52
- "@tiptap/extension-link": "^2.0.0-beta.220",
53
- "@tiptap/extension-list-item": "^2.0.0-beta.220",
54
- "@tiptap/extension-ordered-list": "^2.0.0-beta.220",
55
- "@tiptap/extension-paragraph": "^2.0.0-beta.220",
56
- "@tiptap/extension-placeholder": "^2.0.0-beta.220",
57
- "@tiptap/extension-strike": "^2.0.0-beta.220",
58
- "@tiptap/extension-subscript": "^2.0.0-beta.220",
59
- "@tiptap/extension-superscript": "^2.0.0-beta.220",
60
- "@tiptap/extension-table": "^2.0.0-beta.220",
61
- "@tiptap/extension-table-cell": "^2.0.0-beta.220",
62
- "@tiptap/extension-table-header": "^2.0.0-beta.220",
63
- "@tiptap/extension-table-row": "^2.0.0-beta.220",
64
- "@tiptap/extension-text": "^2.0.0-beta.220",
65
- "@tiptap/extension-text-align": "^2.0.0-beta.220",
66
- "@tiptap/extension-text-style": "^2.0.0-beta.220",
67
- "@tiptap/extension-underline": "^2.0.0-beta.220",
68
- "@tiptap/vue-2": "^2.0.0-beta.220",
39
+ "@tiptap/extension-floating-menu": "^2.0.3",
40
+ "@tiptap/extension-highlight": "^2.0.3",
41
+ "@tiptap/extension-link": "^2.0.3",
42
+ "@tiptap/extension-placeholder": "^2.0.3",
43
+ "@tiptap/extension-subscript": "^2.0.3",
44
+ "@tiptap/extension-superscript": "^2.0.3",
45
+ "@tiptap/extension-table": "^2.0.3",
46
+ "@tiptap/extension-table-cell": "^2.0.3",
47
+ "@tiptap/extension-table-header": "^2.0.3",
48
+ "@tiptap/extension-table-row": "^2.0.3",
49
+ "@tiptap/extension-text-align": "^2.0.3",
50
+ "@tiptap/extension-text-style": "^2.0.3",
51
+ "@tiptap/extension-underline": "^2.0.3",
52
+ "@tiptap/starter-kit": "^2.0.3",
53
+ "@tiptap/vue-3": "^2.0.3",
54
+ "@vue/compat": "^3.3.8",
55
+ "@vue/compiler-sfc": "^3.3.8",
69
56
  "autoprefixer": "^10.4.1",
70
57
  "bluebird": "^3.7.2",
71
58
  "body-parser": "^1.18.2",
@@ -127,18 +114,17 @@
127
114
  "sass-loader": "^10.1.1",
128
115
  "server-destroy": "^1.0.1",
129
116
  "sluggo": "^1.0.0",
117
+ "sortablejs": "^1.15.0",
118
+ "sortablejs-vue3": "^1.2.11",
119
+ "tiny-emitter": "^2.1.0",
130
120
  "tinycolor2": "^1.4.2",
131
121
  "tough-cookie": "^4.0.0",
132
122
  "underscore.string": "^3.3.4",
133
123
  "uploadfs": "^1.22.3",
134
- "v-tooltip": "^2.0.3",
135
- "vue": "2.7.15",
136
- "vue-advanced-cropper": "^1.10.1",
137
- "vue-loader": "^15.10.0",
138
- "vue-material-design-icons": "~4.12.1",
139
- "vue-style-loader": "^4.1.2",
140
- "vue-template-compiler": "^2.6.14",
141
- "vuedraggable": "^2.24.3",
124
+ "vue": "^3.3.8",
125
+ "vue-advanced-cropper": "^2.8.8",
126
+ "vue-loader": "^17.1.0",
127
+ "vue-style-loader": "^4.1.3",
142
128
  "webpack": "^5.72.0",
143
129
  "webpack-merge": "^5.7.3",
144
130
  "xregexp": "^2.0.0"
@@ -157,9 +143,10 @@
157
143
  "stylelint": "^14.6.1",
158
144
  "stylelint-declaration-strict-value": "^1.8.0",
159
145
  "stylelint-order": "^5.0.0",
160
- "vue-eslint-parser": "^7.1.1"
146
+ "vue-eslint-parser": "^7.1.1",
147
+ "vue-template-compiler": "^2.7.14"
161
148
  },
162
149
  "browserslist": [
163
150
  "ie >= 10"
164
151
  ]
165
- }
152
+ }
package/test/schemas.js CHANGED
@@ -2052,7 +2052,10 @@ describe('Schemas', function() {
2052
2052
  it('should call the evaluate-external-condition API successfully', async function() {
2053
2053
  apos.schema.fieldsById['some-field-id'] = {
2054
2054
  name: 'someField',
2055
- moduleName: 'external-condition'
2055
+ moduleName: 'external-condition',
2056
+ if: {
2057
+ 'externalCondition()': 'yes'
2058
+ }
2056
2059
  };
2057
2060
 
2058
2061
  const res = await apos.http.get('/api/v1/@apostrophecms/schema/evaluate-external-condition?fieldId=some-field-id&docId=some-doc-id&conditionKey=externalCondition()', {});
@@ -2062,7 +2065,10 @@ describe('Schemas', function() {
2062
2065
  it('should warn when an argument is passed in the external condition key via the evaluate-external-condition API', async function() {
2063
2066
  apos.schema.fieldsById['some-field-id'] = {
2064
2067
  name: 'someField',
2065
- moduleName: 'external-condition'
2068
+ moduleName: 'external-condition',
2069
+ if: {
2070
+ 'externalCondition()': 'yes'
2071
+ }
2066
2072
  };
2067
2073
 
2068
2074
  const res = await apos.http.get('/api/v1/@apostrophecms/schema/evaluate-external-condition?fieldId=some-field-id&docId=some-doc-id&conditionKey=externalCondition(letsNotArgue)', {});
@@ -2081,7 +2087,7 @@ describe('Schemas', function() {
2081
2087
  await apos.http.get('/api/v1/@apostrophecms/schema/evaluate-external-condition?fieldId=some-field-id&docId=some-doc-id&conditionKey=externalCondition()', {});
2082
2088
  } catch (error) {
2083
2089
  assert(error.status = 400);
2084
- assert(error.body.message === 'The "unknown-module" module defined in the "someField" field does not exist.');
2090
+ assert.strictEqual(error.body.message, 'externalCondition() is not registered as an external condition.');
2085
2091
  return;
2086
2092
  }
2087
2093
  throw new Error('should have thrown');
@@ -2097,7 +2103,7 @@ describe('Schemas', function() {
2097
2103
  await apos.http.get('/api/v1/@apostrophecms/schema/evaluate-external-condition?fieldId=some-field-id&docId=some-doc-id&conditionKey=unknownMethod()', {});
2098
2104
  } catch (error) {
2099
2105
  assert(error.status = 400);
2100
- assert(error.body.message === 'The "unknownMethod" method from "external-condition" module defined in the "someField" field does not exist.');
2106
+ assert.strictEqual(error.body.message, 'unknownMethod() is not registered as an external condition.');
2101
2107
  return;
2102
2108
  }
2103
2109
  throw new Error('should have thrown');