@conduction/nextcloud-vue 2.119.0 → 2.121.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 (179) hide show
  1. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js +9 -0
  2. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js.map +1 -0
  3. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js +226 -0
  4. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js.map +1 -0
  5. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js +211 -0
  6. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js.map +1 -0
  7. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js +9 -0
  8. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js.map +1 -0
  9. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js +64 -0
  10. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js.map +1 -0
  11. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js +89 -0
  12. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js.map +1 -0
  13. package/dist/esm/components/CnIcon/semanticIcons.js +2 -2
  14. package/dist/esm/components/CnIcon/semanticIcons.js.map +1 -1
  15. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +53 -1
  16. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  17. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +546 -523
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  19. package/dist/esm/components/CnIndexPage/useNamedSource.js +9 -0
  20. package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
  21. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js +9 -0
  22. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js.map +1 -0
  23. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js +257 -0
  24. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js.map +1 -0
  25. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js +266 -0
  26. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js.map +1 -0
  27. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue.js +1 -1
  28. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js +14 -7
  29. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js.map +1 -1
  30. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue3.js.map +1 -1
  31. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js +9 -0
  32. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js.map +1 -0
  33. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js +278 -0
  34. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js.map +1 -0
  35. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js +128 -0
  36. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js.map +1 -0
  37. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js +9 -0
  38. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js.map +1 -0
  39. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js +214 -0
  40. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js.map +1 -0
  41. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js +125 -0
  42. package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js.map +1 -0
  43. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js +9 -0
  44. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js.map +1 -0
  45. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js +163 -0
  46. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js.map +1 -0
  47. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js +131 -0
  48. package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js.map +1 -0
  49. package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js +127 -0
  50. package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js.map +1 -0
  51. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js +9 -0
  52. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js.map +1 -0
  53. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js +82 -0
  54. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js.map +1 -0
  55. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js +61 -0
  56. package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js.map +1 -0
  57. package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js +60 -0
  58. package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js.map +1 -0
  59. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js +10 -0
  60. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js.map +1 -0
  61. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js +226 -0
  62. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js.map +1 -0
  63. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js +126 -0
  64. package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js.map +1 -0
  65. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js +10 -0
  66. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js.map +1 -0
  67. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js +944 -0
  68. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js.map +1 -0
  69. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js +276 -0
  70. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js.map +1 -0
  71. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js +9 -0
  72. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js.map +1 -0
  73. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js +354 -0
  74. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js.map +1 -0
  75. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js +392 -0
  76. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js.map +1 -0
  77. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js +9 -0
  78. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js.map +1 -0
  79. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js +180 -0
  80. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js.map +1 -0
  81. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js +208 -0
  82. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js.map +1 -0
  83. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js +9 -0
  84. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js.map +1 -0
  85. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js +244 -0
  86. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js.map +1 -0
  87. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js +76 -0
  88. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js.map +1 -0
  89. package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js +290 -0
  90. package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js.map +1 -0
  91. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js +9 -0
  92. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js.map +1 -0
  93. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js +448 -0
  94. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js.map +1 -0
  95. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js +303 -0
  96. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js.map +1 -0
  97. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
  98. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +19 -2
  99. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  100. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +73 -62
  101. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  102. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +6 -0
  103. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
  104. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +42 -32
  105. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  106. package/dist/esm/composables/indexSources.js +116 -16
  107. package/dist/esm/composables/indexSources.js.map +1 -1
  108. package/dist/esm/index.js +9 -0
  109. package/dist/esm/index.js.map +1 -1
  110. package/dist/esm/l10n/en.json.js +207 -1
  111. package/dist/esm/l10n/en.json.js.map +1 -1
  112. package/dist/esm/l10n/nl.json.js +207 -1
  113. package/dist/esm/l10n/nl.json.js.map +1 -1
  114. package/dist/esm/library-style.js +1 -1
  115. package/dist/esm/nextcloud-vue.css +951 -16
  116. package/dist/esm/utils/aiFeatures.js +245 -0
  117. package/dist/esm/utils/aiFeatures.js.map +1 -0
  118. package/dist/esm/utils/aiSuggestionTracker.js +182 -0
  119. package/dist/esm/utils/aiSuggestionTracker.js.map +1 -0
  120. package/dist/esm/utils/libraryWidgetKeys.js +2 -0
  121. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  122. package/dist/esm/utils/objectPermissions.js +552 -0
  123. package/dist/esm/utils/objectPermissions.js.map +1 -0
  124. package/dist/esm/utils/objectTranslations.js +180 -0
  125. package/dist/esm/utils/objectTranslations.js.map +1 -0
  126. package/dist/esm/utils/stateMachineValidation.js +254 -0
  127. package/dist/esm/utils/stateMachineValidation.js.map +1 -0
  128. package/dist/esm/utils/widgetDispatch.js +3 -1
  129. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  130. package/dist/nextcloud-vue.cjs.js +23038 -14567
  131. package/dist/nextcloud-vue.cjs.js.map +2 -2
  132. package/dist/nextcloud-vue.css +951 -16
  133. package/l10n/en.json +207 -1
  134. package/l10n/nl.json +207 -1
  135. package/package.json +1 -1
  136. package/src/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue +416 -0
  137. package/src/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue +136 -0
  138. package/src/components/CnAiFeaturesWidget/__tests__/CnAiFeaturesWidget.spec.js +213 -0
  139. package/src/components/CnAiFeaturesWidget/index.js +14 -0
  140. package/src/components/CnIndexPage/CnIndexPage.vue +74 -3
  141. package/src/components/CnIndexPage/useNamedSource.js +9 -0
  142. package/src/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue +499 -0
  143. package/src/components/CnObjectPermissionsTab/__tests__/CnObjectPermissionsTab.spec.js +186 -0
  144. package/src/components/CnObjectPermissionsTab/index.js +13 -0
  145. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +8 -1
  146. package/src/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue +424 -0
  147. package/src/components/CnObjectTranslationsWidget/__tests__/CnObjectTranslationsWidget.spec.js +189 -0
  148. package/src/components/CnObjectTranslationsWidget/index.js +13 -0
  149. package/src/components/CnReadinessChecklist/CnReadinessChecklist.vue +335 -0
  150. package/src/components/CnReadinessChecklist/index.js +9 -0
  151. package/src/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue +300 -0
  152. package/src/components/CnSchemaRulesWidget/index.js +10 -0
  153. package/src/components/CnSchemaRulesWidget/schemaRules.js +123 -0
  154. package/src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue +160 -0
  155. package/src/components/CnSearchIndexStatus/index.js +10 -0
  156. package/src/components/CnSearchIndexStatus/searchIndexStatus.js +56 -0
  157. package/src/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue +328 -0
  158. package/src/components/CnShippedConfigurationSection/index.js +9 -0
  159. package/src/components/CnStateMachineEditor/CnStateMachineEditor.vue +1332 -0
  160. package/src/components/CnStateMachineEditor/CnStateMachineFields.vue +791 -0
  161. package/src/components/CnStateMachineEditor/CnStateMachineNode.vue +442 -0
  162. package/src/components/CnStateMachineEditor/CnStateMachinePanel.vue +326 -0
  163. package/src/components/CnStateMachineEditor/index.js +8 -0
  164. package/src/components/CnStateMachineEditor/stateMachineFields.js +287 -0
  165. package/src/components/CnTimelineWidget/CnTimelineManage.vue +827 -0
  166. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +29 -3
  167. package/src/components/CnWidgetGrid/builtInWidgets.js +6 -0
  168. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +10 -0
  169. package/src/components/index.js +8 -0
  170. package/src/composables/indexSources.js +116 -16
  171. package/src/css/index-page.css +7 -0
  172. package/src/index.js +9 -0
  173. package/src/utils/aiFeatures.js +241 -0
  174. package/src/utils/aiSuggestionTracker.js +178 -0
  175. package/src/utils/libraryWidgetKeys.js +2 -0
  176. package/src/utils/objectPermissions.js +548 -0
  177. package/src/utils/objectTranslations.js +176 -0
  178. package/src/utils/stateMachineValidation.js +250 -0
  179. package/src/utils/widgetDispatch.js +3 -1
@@ -0,0 +1,944 @@
1
+ import { translate, translatePlural } from '@nextcloud/l10n';
2
+ import { NcButton } from '@nextcloud/vue';
3
+ import Alert from 'vue-material-design-icons/Alert.vue';
4
+ import AlertCircle from 'vue-material-design-icons/AlertCircle.vue';
5
+ import Plus from 'vue-material-design-icons/Plus.vue';
6
+ import SquareOutline from 'vue-material-design-icons/SquareOutline.vue';
7
+ import __sfc_main from '../CnDeleteDialog/CnDeleteDialog.vue.js';
8
+ import __sfc_main$1 from '../CnGraphCanvas/CnGraphCanvas.vue.js';
9
+ import __sfc_main$2 from './CnStateMachineNode.vue.js';
10
+ import __sfc_main$3 from './CnStateMachinePanel.vue.js';
11
+ import { validateStateMachine } from '../../utils/stateMachineValidation.js';
12
+
13
+ /** The drag type a palette state carries, so other drops are ignored. */
14
+ const PALETTE_TYPE = 'application/x-cn-state-machine-state';
15
+
16
+ /** Record keys by role. A host passes its own names through `config.keys`. */
17
+ const DEFAULT_STATE_MACHINE_EDITOR_KEYS = Object.freeze({
18
+ stateLabel: 'label',
19
+ stateFinal: 'final',
20
+ transitionFrom: 'from',
21
+ transitionTo: 'to',
22
+ transitionLabel: 'label',
23
+ stepState: 'state',
24
+ stepTitle: 'title',
25
+ stepOrder: 'order',
26
+ stepRequired: 'required',
27
+ stepBadge: '',
28
+ });
29
+
30
+ let editorCount = 0;
31
+
32
+ /**
33
+ * Fill `{name}` placeholders.
34
+ *
35
+ * @param {string} text The text.
36
+ * @param {object} [vars] Values by placeholder.
37
+ * @return {string} The filled text.
38
+ */
39
+ function fill(text, vars) {
40
+ if (!vars) {
41
+ return String(text ?? '')
42
+ }
43
+ return String(text ?? '').replace(/\{(\w+)\}/g, (match, name) => (Object.hasOwn(vars, name) ? String(vars[name]) : match))
44
+ }
45
+
46
+ /**
47
+ * An editor for a state machine: states drawn on a canvas, the transitions
48
+ * between them, the steps inside each state, and a property panel for whichever
49
+ * of those is selected. What a state, step or transition carries is described
50
+ * by field descriptors in `config`, so the component has no domain words of its
51
+ * own.
52
+ *
53
+ * The editor never changes the records it is given. Every edit is an event;
54
+ * the host stores the change and passes the records back down, the same rule
55
+ * CnGraphCanvas holds for positions.
56
+ *
57
+ * Every pointer gesture has a keyboard route: the palette's add button instead
58
+ * of a drag, a state's actions menu (or `c` on two states) instead of drawing a
59
+ * line, arrow keys instead of dragging a state, Alt with an arrow or the panel's
60
+ * move buttons instead of dragging a step or list item.
61
+ */
62
+ var script = {
63
+ name: 'CnStateMachineEditor',
64
+
65
+ components: {
66
+ NcButton,
67
+ Alert,
68
+ AlertCircle,
69
+ Plus,
70
+ SquareOutline,
71
+ CnDeleteDialog: __sfc_main,
72
+ CnGraphCanvas: __sfc_main$1,
73
+ CnStateMachineNode: __sfc_main$2,
74
+ CnStateMachinePanel: __sfc_main$3,
75
+ },
76
+
77
+ inject: {
78
+ cnTranslate: { default: null },
79
+ },
80
+
81
+ props: {
82
+ /** The states. Each has an `id`; its name and final flag sit under `config.keys`. */
83
+ states: {
84
+ type: Array,
85
+ required: true,
86
+ },
87
+
88
+ /** The transitions, each `{ id }` plus a from and to state id under `config.keys`. */
89
+ transitions: {
90
+ type: Array,
91
+ default: () => [],
92
+ },
93
+
94
+ /** The steps inside states, each `{ id }` plus its state id under `config.keys.stepState`. */
95
+ steps: {
96
+ type: Array,
97
+ default: () => [],
98
+ },
99
+
100
+ /** Canvas positions by state id: `{ [id]: { x, y } }`. A state without one is placed on a grid. */
101
+ positions: {
102
+ type: Object,
103
+ default: () => ({}),
104
+ },
105
+
106
+ /**
107
+ * What the machine's records carry and what the editor says.
108
+ *
109
+ * - `keys`: record keys by role, see DEFAULT_STATE_MACHINE_EDITOR_KEYS.
110
+ * - `stateFields`, `stepFields`, `transitionFields`: field descriptors for
111
+ * each property panel (see the docs page for the descriptor types).
112
+ * - `steps`: false to leave steps out of the machine. On by default when
113
+ * `stepFields` is given.
114
+ * - `labels`: the editor's own texts by name, overriding the defaults.
115
+ * - `paletteHelp`, `controlsHelp`: the help under the palette.
116
+ * - `messages`: validation messages by rule code.
117
+ * - `requireFinal`: refuse to delete the last final state (default true).
118
+ * - `blockOnWarnings`: let warnings fail validate() too (default false).
119
+ * - `canvasHeight`: the canvas height in px (default 540).
120
+ *
121
+ * Texts are translated through `translate`, or the app's `cnTranslate`.
122
+ */
123
+ config: {
124
+ type: Object,
125
+ default: () => ({}),
126
+ },
127
+
128
+ /** Named option lists a select or checkboxes field points at with `optionSet`. */
129
+ optionSets: {
130
+ type: Object,
131
+ default: () => ({}),
132
+ },
133
+
134
+ /** Disable the panel fields marked `lockable`, and step deletion. */
135
+ locked: {
136
+ type: Boolean,
137
+ default: false,
138
+ },
139
+
140
+ /** Show the machine without any editing control. */
141
+ readOnly: {
142
+ type: Boolean,
143
+ default: false,
144
+ },
145
+
146
+ /** Frame the whole machine when the canvas first renders. */
147
+ fitView: {
148
+ type: Boolean,
149
+ default: true,
150
+ },
151
+
152
+ /** Translates configured texts. Falls back to the injected `cnTranslate`. */
153
+ translate: {
154
+ type: Function,
155
+ default: null,
156
+ },
157
+ },
158
+
159
+ emits: [
160
+ 'state-add',
161
+ 'state-move',
162
+ 'state-update',
163
+ 'state-remove',
164
+ 'transition-add',
165
+ 'transition-update',
166
+ 'transition-remove',
167
+ 'step-add',
168
+ 'step-update',
169
+ 'step-remove',
170
+ 'step-reorder',
171
+ 'validated',
172
+ ],
173
+
174
+ data() {
175
+ editorCount += 1;
176
+ return {
177
+ uid: `cn-state-machine-${editorCount}`,
178
+ selection: { kind: null, id: null },
179
+ issues: [],
180
+ menuOpenFor: null,
181
+ pendingRemoval: null,
182
+ labelPositions: {},
183
+ syncTick: 0,
184
+ }
185
+ },
186
+
187
+ computed: {
188
+ /**
189
+ * @return {object} Record keys by role.
190
+ */
191
+ keys() {
192
+ return { ...DEFAULT_STATE_MACHINE_EDITOR_KEYS, ...(this.config.keys || {}) }
193
+ },
194
+
195
+ /**
196
+ * @return {object} The step keys the node reads.
197
+ */
198
+ stepKeys() {
199
+ return { title: this.keys.stepTitle, required: this.keys.stepRequired, badge: this.keys.stepBadge }
200
+ },
201
+
202
+ /**
203
+ * @return {Array<object>} The step panel's fields.
204
+ */
205
+ stepFields() {
206
+ return Array.isArray(this.config.stepFields) ? this.config.stepFields : []
207
+ },
208
+
209
+ /**
210
+ * @return {Array<object>} The transition panel's fields.
211
+ */
212
+ transitionFields() {
213
+ return Array.isArray(this.config.transitionFields) ? this.config.transitionFields : []
214
+ },
215
+
216
+ /**
217
+ * @return {Array<object>} The state panel's fields.
218
+ */
219
+ stateFields() {
220
+ return Array.isArray(this.config.stateFields) ? this.config.stateFields : []
221
+ },
222
+
223
+ /**
224
+ * @return {boolean} Whether states hold steps.
225
+ */
226
+ showSteps() {
227
+ if (this.config.steps === false) {
228
+ return false
229
+ }
230
+ return this.config.steps === true || this.stepFields.length > 0
231
+ },
232
+
233
+ /**
234
+ * @return {object} The root's style.
235
+ */
236
+ rootStyle() {
237
+ const height = Number(this.config.canvasHeight);
238
+ return { '--cn-state-machine-canvas-height': `${Number.isFinite(height) && height > 0 ? height : 540}px` }
239
+ },
240
+
241
+ /**
242
+ * @return {boolean} Whether any issue is an error.
243
+ */
244
+ hasErrors() {
245
+ return this.issues.some((issue) => issue.type === 'error')
246
+ },
247
+
248
+ /**
249
+ * @return {Array<string>} The palette's help lines.
250
+ */
251
+ paletteHelp() {
252
+ if (Array.isArray(this.config.paletteHelp)) {
253
+ return this.config.paletteHelp.map((line) => this.tr(line))
254
+ }
255
+ return [
256
+ translate('nextcloud-vue', 'Drag a state onto the canvas to add it, or use the add button.'),
257
+ translate('nextcloud-vue', 'Connect states by dragging from one port to another, by pressing c on one state and then on another, or through a state\'s actions menu.'),
258
+ translate('nextcloud-vue', 'Click a state, a step or a transition to see its properties.'),
259
+ ]
260
+ },
261
+
262
+ /**
263
+ * @return {Array<{term: string, text: string}>} The canvas controls help.
264
+ */
265
+ controlsHelp() {
266
+ if (Array.isArray(this.config.controlsHelp)) {
267
+ return this.config.controlsHelp.map((control) => ({ term: this.tr(control.term), text: this.tr(control.text) }))
268
+ }
269
+ return [
270
+ { term: translate('nextcloud-vue', 'Pan'), text: translate('nextcloud-vue', 'Drag the empty canvas') },
271
+ { term: translate('nextcloud-vue', 'Zoom'), text: translate('nextcloud-vue', 'Scroll wheel or the zoom buttons') },
272
+ { term: translate('nextcloud-vue', 'Move'), text: translate('nextcloud-vue', 'Arrow keys on a focused state') },
273
+ ]
274
+ },
275
+
276
+ /**
277
+ * @return {Map<string, object>} States by id.
278
+ */
279
+ stateById() {
280
+ return new Map(this.states.map((state) => [state.id, state]))
281
+ },
282
+
283
+ /**
284
+ * @return {Array<object>} The canvas nodes.
285
+ */
286
+ canvasNodes() {
287
+ // `sync` changes when a refused removal must re-send the graph Vue Flow
288
+ // already dropped, so the nodes are rebuilt.
289
+ const sync = this.syncTick;
290
+ return this.states.map((state, index) => ({
291
+ id: state.id,
292
+ type: 'default',
293
+ position: this.positionOf(state.id, index),
294
+ selected: this.selection.kind === 'state' && this.selection.id === state.id,
295
+ style: { width: '200px' },
296
+ data: { label: this.say('stateAria', { name: this.stateLabel(state.id) }), sync },
297
+ }))
298
+ },
299
+
300
+ /**
301
+ * @return {Array<object>} The canvas edges.
302
+ */
303
+ canvasEdges() {
304
+ const sync = this.syncTick;
305
+ return this.transitions
306
+ .filter((transition) => this.stateById.has(this.fromOf(transition)) && this.stateById.has(this.toOf(transition)))
307
+ .map((transition) => ({
308
+ id: transition.id,
309
+ source: this.fromOf(transition),
310
+ target: this.toOf(transition),
311
+ selected: this.selection.kind === 'transition' && this.selection.id === transition.id,
312
+ markerEnd: { type: 'arrowclosed', width: 22, height: 22 },
313
+ data: {
314
+ animated: false,
315
+ sync,
316
+ labelT: this.labelPositions[transition.id],
317
+ labelAriaLabel: `${this.say('transitionAria', { from: this.stateLabel(this.fromOf(transition)), to: this.stateLabel(this.toOf(transition)) })}: ${this.transitionText(transition.id)}`,
318
+ },
319
+ }))
320
+ },
321
+
322
+ /**
323
+ * @return {object|null} The selected step.
324
+ */
325
+ selectedStep() {
326
+ return this.selection.kind === 'step' ? (this.steps.find((step) => step.id === this.selection.id) || null) : null
327
+ },
328
+
329
+ /**
330
+ * @return {object|null} The selected transition.
331
+ */
332
+ selectedTransition() {
333
+ return this.selection.kind === 'transition' ? (this.transitions.find((transition) => transition.id === this.selection.id) || null) : null
334
+ },
335
+
336
+ /**
337
+ * @return {object|null} The selected state.
338
+ */
339
+ selectedState() {
340
+ return this.selection.kind === 'state' ? (this.stateById.get(this.selection.id) || null) : null
341
+ },
342
+ },
343
+
344
+ methods: {
345
+ t: translate,
346
+
347
+ /**
348
+ * Hand the panel's edited step to the host.
349
+ *
350
+ * @param {object} record The edited step, complete.
351
+ */
352
+ updateStep(record) {
353
+ /** @event step-update The edited step, complete, as the panel returns it. */
354
+ this.$emit('step-update', record);
355
+ },
356
+
357
+ /**
358
+ * Hand the panel's edited transition to the host.
359
+ *
360
+ * @param {object} record The edited transition, complete.
361
+ */
362
+ updateTransition(record) {
363
+ /** @event transition-update The edited transition, complete, as the panel returns it. */
364
+ this.$emit('transition-update', record);
365
+ },
366
+
367
+ /**
368
+ * Hand the panel's edited state to the host.
369
+ *
370
+ * @param {object} record The edited state, complete.
371
+ */
372
+ updateState(record) {
373
+ /** @event state-update The edited state, complete, as the panel returns it. */
374
+ this.$emit('state-update', record);
375
+ },
376
+
377
+ /**
378
+ * Translate a configured text.
379
+ *
380
+ * @param {string} text The text.
381
+ * @return {string} The translation, or the text.
382
+ */
383
+ tr(text) {
384
+ if (typeof text !== 'string' || text === '') {
385
+ return text || ''
386
+ }
387
+ const translate = this.translate || this.cnTranslate;
388
+ const answer = typeof translate === 'function' ? translate(text) : text;
389
+ return typeof answer === 'string' && answer !== '' ? answer : text
390
+ },
391
+
392
+ /**
393
+ * One of the editor's own texts: the config's, translated, or the default.
394
+ *
395
+ * @param {string} name The text's name.
396
+ * @param {object} [vars] Placeholder values.
397
+ * @return {string} The text.
398
+ */
399
+ say(name, vars) {
400
+ const own = this.config.labels && this.config.labels[name];
401
+ if (typeof own === 'string' && own !== '') {
402
+ return fill(this.tr(own), vars)
403
+ }
404
+ if (name === 'stepCount') {
405
+ return translatePlural('nextcloud-vue', '%n step', '%n steps', vars?.count ?? 0)
406
+ }
407
+ return fill(this.defaultText(name), vars)
408
+ },
409
+
410
+ /**
411
+ * @param {string} name A text's name.
412
+ * @return {string} Its default, in the library's domain.
413
+ */
414
+ defaultText(name) {
415
+ const texts = {
416
+ paletteTitle: translate('nextcloud-vue', 'Elements'),
417
+ paletteItem: translate('nextcloud-vue', 'State'),
418
+ addState: translate('nextcloud-vue', 'Add state'),
419
+ controlsTitle: translate('nextcloud-vue', 'Controls'),
420
+ canvasLabel: translate('nextcloud-vue', 'States and transitions'),
421
+ propertiesLabel: translate('nextcloud-vue', 'Properties'),
422
+ emptyPanel: translate('nextcloud-vue', 'Select a state, a step or a transition to see its properties.'),
423
+ final: translate('nextcloud-vue', 'Final'),
424
+ stateAria: translate('nextcloud-vue', 'State: {name}'),
425
+ required: translate('nextcloud-vue', 'required'),
426
+ stateActions: translate('nextcloud-vue', 'Actions for state {name}'),
427
+ connectTo: translate('nextcloud-vue', 'Connect to {name}'),
428
+ disconnectFrom: translate('nextcloud-vue', 'Disconnect from {name}'),
429
+ editTransitionTo: translate('nextcloud-vue', 'Edit transition to {name}'),
430
+ addStep: translate('nextcloud-vue', 'Add step'),
431
+ deleteState: translate('nextcloud-vue', 'Delete state'),
432
+ statePanelTitle: translate('nextcloud-vue', 'State'),
433
+ closeStatePanel: translate('nextcloud-vue', 'Close state properties'),
434
+ stepPanelTitle: translate('nextcloud-vue', 'Step'),
435
+ closeStepPanel: translate('nextcloud-vue', 'Close step properties'),
436
+ deleteStep: translate('nextcloud-vue', 'Delete step'),
437
+ transitionPanelTitle: translate('nextcloud-vue', 'Transition'),
438
+ closeTransitionPanel: translate('nextcloud-vue', 'Close transition properties'),
439
+ deleteTransition: translate('nextcloud-vue', 'Delete transition'),
440
+ deleteTransitionConfirm: translate('nextcloud-vue', 'Delete the transition {name}?'),
441
+ deleteStateConfirm: translate('nextcloud-vue', 'Delete state "{name}"? Its steps and transitions go with it.'),
442
+ needsFinal: translate('nextcloud-vue', 'At least one state must stay final'),
443
+ deleteStateFailed: translate('nextcloud-vue', 'The state could not be deleted'),
444
+ unnamedTransition: translate('nextcloud-vue', 'Transition'),
445
+ transitionAria: translate('nextcloud-vue', 'Transition from {from} to {to}'),
446
+ dismiss: translate('nextcloud-vue', 'Dismiss'),
447
+ };
448
+ return texts[name] ?? name
449
+ },
450
+
451
+ /**
452
+ * @param {object} transition A transition.
453
+ * @return {string} Its source state id.
454
+ */
455
+ fromOf(transition) {
456
+ return transition[this.keys.transitionFrom]
457
+ },
458
+
459
+ /**
460
+ * @param {object} transition A transition.
461
+ * @return {string} Its target state id.
462
+ */
463
+ toOf(transition) {
464
+ return transition[this.keys.transitionTo]
465
+ },
466
+
467
+ /**
468
+ * @param {string} id A state id.
469
+ * @return {string} Its name, or the id.
470
+ */
471
+ stateLabel(id) {
472
+ const state = this.stateById.get(id);
473
+ return (state && state[this.keys.stateLabel]) || id || ''
474
+ },
475
+
476
+ /**
477
+ * @param {string} id A state id.
478
+ * @return {boolean} Whether it is final.
479
+ */
480
+ isFinal(id) {
481
+ const state = this.stateById.get(id);
482
+ return !!state && state[this.keys.stateFinal] === true
483
+ },
484
+
485
+ /**
486
+ * @param {string} id A transition id.
487
+ * @return {string} The text its label shows.
488
+ */
489
+ transitionText(id) {
490
+ const transition = this.transitions.find((candidate) => candidate.id === id);
491
+ const label = transition ? transition[this.keys.transitionLabel] : '';
492
+ return label || this.say('unnamedTransition')
493
+ },
494
+
495
+ /**
496
+ * @param {object} transition A transition.
497
+ * @return {string} `From → To`.
498
+ */
499
+ transitionRoute(transition) {
500
+ return `${this.stateLabel(this.fromOf(transition))} → ${this.stateLabel(this.toOf(transition))}`
501
+ },
502
+
503
+ /**
504
+ * @param {string} id A state id.
505
+ * @param {number} index Its position in `states`.
506
+ * @return {{x: number, y: number}} Its stored position, or its grid slot.
507
+ */
508
+ positionOf(id, index) {
509
+ const stored = this.positions && this.positions[id];
510
+ if (stored && Number.isFinite(stored.x) && Number.isFinite(stored.y)) {
511
+ return { x: stored.x, y: stored.y }
512
+ }
513
+ return this.gridSlot(index)
514
+ },
515
+
516
+ /**
517
+ * @param {number} index A slot number.
518
+ * @return {{x: number, y: number}} Four states to a row, 250 by 200 apart.
519
+ */
520
+ gridSlot(index) {
521
+ return { x: 100 + (index % 4) * 250, y: 100 + Math.floor(index / 4) * 200 }
522
+ },
523
+
524
+ /**
525
+ * @param {string} id A state id.
526
+ * @return {Array<object>} Its steps in order.
527
+ */
528
+ stepsOf(id) {
529
+ const order = this.keys.stepOrder;
530
+ return this.steps
531
+ .filter((step) => step[this.keys.stepState] === id)
532
+ .sort((a, b) => (Number(a[order]) || 0) - (Number(b[order]) || 0))
533
+ },
534
+
535
+ /**
536
+ * @param {string} id A state id.
537
+ * @return {Array<{id: string, label: string}>} States it has no transition to yet.
538
+ */
539
+ connectTargetsOf(id) {
540
+ const connected = new Set(this.transitions.filter((transition) => this.fromOf(transition) === id).map(this.toOf));
541
+ return this.states
542
+ .filter((state) => state.id !== id && !connected.has(state.id))
543
+ .map((state) => ({ id: state.id, label: this.stateLabel(state.id) }))
544
+ },
545
+
546
+ /**
547
+ * @param {string} id A state id.
548
+ * @return {Array<{id: string, targetLabel: string}>} Its outgoing transitions.
549
+ */
550
+ outgoingOf(id) {
551
+ return this.transitions
552
+ .filter((transition) => this.fromOf(transition) === id)
553
+ .map((transition) => ({ id: transition.id, targetLabel: this.stateLabel(this.toOf(transition)) }))
554
+ },
555
+
556
+ /**
557
+ * @param {string} id A state id.
558
+ * @return {void}
559
+ */
560
+ selectState(id) {
561
+ this.selection = { kind: 'state', id };
562
+ },
563
+
564
+ /**
565
+ * @param {string} id A transition id.
566
+ * @return {void}
567
+ */
568
+ selectTransition(id) {
569
+ this.selection = { kind: 'transition', id };
570
+ },
571
+
572
+ /**
573
+ * @param {string} id A step id.
574
+ * @return {void}
575
+ */
576
+ selectStep(id) {
577
+ this.selection = { kind: 'step', id };
578
+ },
579
+
580
+ /**
581
+ * @return {void}
582
+ */
583
+ clearSelection() {
584
+ this.selection = { kind: null, id: null };
585
+ },
586
+
587
+ /**
588
+ * @param {object} event CnGraphCanvas's node event.
589
+ * @return {void}
590
+ */
591
+ onNodeSelect(event) {
592
+ if (event && event.node) {
593
+ this.selectState(event.node.id);
594
+ }
595
+ },
596
+
597
+ /**
598
+ * @param {object} event CnGraphCanvas's edge event.
599
+ * @return {void}
600
+ */
601
+ onEdgeSelect(event) {
602
+ if (event && event.edge) {
603
+ this.selectTransition(event.edge.id);
604
+ }
605
+ },
606
+
607
+ /**
608
+ * @param {string} id A state id.
609
+ * @param {boolean} open Whether its menu opened.
610
+ * @return {void}
611
+ */
612
+ onMenuToggle(id, open) {
613
+ if (open) {
614
+ this.menuOpenFor = id;
615
+ } else if (this.menuOpenFor === id) {
616
+ this.menuOpenFor = null;
617
+ }
618
+ },
619
+
620
+ /**
621
+ * Report moves; Vue Flow reports a drag once per frame and a keyboard
622
+ * move once per key.
623
+ *
624
+ * @param {Array<object>} changes Vue Flow's node changes.
625
+ * @return {void}
626
+ */
627
+ onNodesChange(changes) {
628
+ for (const change of changes || []) {
629
+ if (change.type === 'position' && change.position) {
630
+ /**
631
+ * @event state-move A state was moved: `{ id, x, y }`.
632
+ */
633
+ this.$emit('state-move', { id: change.id, x: Math.round(change.position.x), y: Math.round(change.position.y) });
634
+ } else if (change.type === 'remove') {
635
+ this.requestStateRemoval(change.id);
636
+ }
637
+ }
638
+ },
639
+
640
+ /**
641
+ * @param {Array<object>} changes Vue Flow's edge changes.
642
+ * @return {void}
643
+ */
644
+ onEdgesChange(changes) {
645
+ for (const change of changes || []) {
646
+ if (change.type === 'remove') {
647
+ this.requestTransitionRemoval(change.id);
648
+ }
649
+ }
650
+ },
651
+
652
+ /**
653
+ * @param {{source: string, target: string}} connection A new connection.
654
+ * @return {void}
655
+ */
656
+ onConnect(connection) {
657
+ if (connection && connection.source && connection.target) {
658
+ this.connect(connection.source, connection.target);
659
+ }
660
+ },
661
+
662
+ /**
663
+ * @param {string} from The source state.
664
+ * @param {string} to The target state.
665
+ * @return {void}
666
+ */
667
+ connect(from, to) {
668
+ if (this.readOnly || from === to) {
669
+ return
670
+ }
671
+ /**
672
+ * @event transition-add A transition should be added: `{ from, to }`.
673
+ */
674
+ this.$emit('transition-add', { from, to });
675
+ },
676
+
677
+ /**
678
+ * @param {{id: string, labelT: number}} payload The label and its place on the line.
679
+ * @return {void}
680
+ */
681
+ onEdgeLabelMove(payload) {
682
+ this.labelPositions = { ...this.labelPositions, [payload.id]: payload.labelT };
683
+ },
684
+
685
+ /**
686
+ * @param {DragEvent} event The palette drag.
687
+ * @return {void}
688
+ */
689
+ onPaletteDragStart(event) {
690
+ if (event.dataTransfer) {
691
+ event.dataTransfer.setData(PALETTE_TYPE, 'state');
692
+ event.dataTransfer.setData('text/plain', 'state');
693
+ event.dataTransfer.effectAllowed = 'copy';
694
+ }
695
+ },
696
+
697
+ /**
698
+ * @param {{position: object, event: DragEvent}} payload The drop.
699
+ * @return {void}
700
+ */
701
+ onCanvasDrop({ position, event }) {
702
+ const types = event && event.dataTransfer ? Array.from(event.dataTransfer.types || []) : [];
703
+ if (!types.includes(PALETTE_TYPE)) {
704
+ return
705
+ }
706
+ this.addState({ x: Math.round(position.x), y: Math.round(position.y) }, false);
707
+ },
708
+
709
+ /**
710
+ * The keyboard route to a new state: the next free grid slot, and the
711
+ * new state selected so its panel opens.
712
+ *
713
+ * @return {void}
714
+ */
715
+ addStateFromKeyboard() {
716
+ this.addState(this.gridSlot(this.states.length), true);
717
+ },
718
+
719
+ /**
720
+ * @param {{x: number, y: number}} position Where the state goes.
721
+ * @param {boolean} select Whether to select it once added.
722
+ * @return {void}
723
+ */
724
+ addState(position, select) {
725
+ if (this.readOnly) {
726
+ return
727
+ }
728
+ /**
729
+ * @event state-add A state should be added at `position`. The host
730
+ * creates it and calls `done(id)`; the editor then selects it when
731
+ * it was added from the keyboard.
732
+ */
733
+ this.$emit('state-add', {
734
+ position,
735
+ done: (id) => {
736
+ if (select && id) {
737
+ this.selectState(id);
738
+ }
739
+ },
740
+ });
741
+ },
742
+
743
+ /**
744
+ * @param {string} stateId The state.
745
+ * @return {void}
746
+ */
747
+ addStep(stateId) {
748
+ if (this.readOnly) {
749
+ return
750
+ }
751
+ /**
752
+ * @event step-add A step should be added to a state:
753
+ * `{ state, done }`. The host calls `done(id)` and the editor opens
754
+ * the new step.
755
+ */
756
+ this.$emit('step-add', {
757
+ state: stateId,
758
+ done: (id) => {
759
+ if (id) {
760
+ this.selectStep(id);
761
+ }
762
+ },
763
+ });
764
+ },
765
+
766
+ /**
767
+ * @param {string} id A step.
768
+ * @return {void}
769
+ */
770
+ removeStep(id) {
771
+ if (this.selection.kind === 'step' && this.selection.id === id) {
772
+ this.clearSelection();
773
+ }
774
+ /**
775
+ * @event step-remove A step should be removed, by id.
776
+ */
777
+ this.$emit('step-remove', id);
778
+ },
779
+
780
+ /**
781
+ * @param {string} stateId The state the step is in.
782
+ * @param {{from: number, to: number}} move The step's old and new place.
783
+ * @return {void}
784
+ */
785
+ moveStep(stateId, { from, to }) {
786
+ const ids = this.stepsOf(stateId).map((step) => step.id);
787
+ if (from < 0 || to < 0 || from >= ids.length || to >= ids.length) {
788
+ return
789
+ }
790
+ const [moved] = ids.splice(from, 1);
791
+ ids.splice(to, 0, moved);
792
+ /**
793
+ * @event step-reorder The steps of a state in their new order:
794
+ * `{ state, ids }`.
795
+ */
796
+ this.$emit('step-reorder', { state: stateId, ids });
797
+ },
798
+
799
+ /**
800
+ * @param {string} id A transition.
801
+ * @return {void}
802
+ */
803
+ removeTransition(id) {
804
+ if (this.selection.kind === 'transition' && this.selection.id === id) {
805
+ this.clearSelection();
806
+ }
807
+ /**
808
+ * @event transition-remove A transition should be removed, by id.
809
+ */
810
+ this.$emit('transition-remove', id);
811
+ },
812
+
813
+ /**
814
+ * Ask before removing a transition.
815
+ *
816
+ * @param {string} id A transition.
817
+ * @return {void}
818
+ */
819
+ requestTransitionRemoval(id) {
820
+ const transition = this.transitions.find((candidate) => candidate.id === id);
821
+ if (!transition || this.readOnly || this.pendingRemoval) {
822
+ this.syncTick += 1;
823
+ return
824
+ }
825
+ this.pendingRemoval = {
826
+ kind: 'transition',
827
+ id,
828
+ name: this.transitionRoute(transition),
829
+ title: this.say('deleteTransition'),
830
+ warning: this.say('deleteTransitionConfirm', { name: this.transitionRoute(transition) }),
831
+ };
832
+ },
833
+
834
+ /**
835
+ * Ask before removing a state, unless it is the last final one.
836
+ *
837
+ * @param {string} id A state.
838
+ * @return {void}
839
+ */
840
+ requestStateRemoval(id) {
841
+ const state = this.stateById.get(id);
842
+ if (!state || this.readOnly || (this.pendingRemoval && this.pendingRemoval.id === id)) {
843
+ this.syncTick += 1;
844
+ return
845
+ }
846
+ this.menuOpenFor = null;
847
+ if (this.config.requireFinal !== false && this.isFinal(id)
848
+ && !this.states.some((other) => other.id !== id && this.isFinal(other.id))) {
849
+ this.issues = [{ type: 'error', code: 'LAST_FINAL_STATE', message: this.say('needsFinal') }];
850
+ this.syncTick += 1;
851
+ return
852
+ }
853
+ this.pendingRemoval = {
854
+ kind: 'state',
855
+ id,
856
+ name: this.stateLabel(id),
857
+ title: this.say('deleteState'),
858
+ warning: this.say('deleteStateConfirm'),
859
+ };
860
+ },
861
+
862
+ /**
863
+ * The removal was confirmed: hand it to the host.
864
+ *
865
+ * @return {void}
866
+ */
867
+ confirmRemoval() {
868
+ const pending = this.pendingRemoval;
869
+ if (!pending) {
870
+ return
871
+ }
872
+ if (pending.kind === 'transition') {
873
+ this.removeTransition(pending.id);
874
+ this.pendingRemoval = null;
875
+ return
876
+ }
877
+ /**
878
+ * @event state-remove A state should be removed: `{ id, done }`. The
879
+ * host removes the state with its steps and transitions and calls
880
+ * `done(true)`, or `done(false)` when it could not.
881
+ */
882
+ this.$emit('state-remove', {
883
+ id: pending.id,
884
+ done: (ok) => {
885
+ if (ok) {
886
+ if (this.selection.id === pending.id) {
887
+ this.clearSelection();
888
+ }
889
+ this.pendingRemoval = null;
890
+ return
891
+ }
892
+ if (this.$refs.removeDialog) {
893
+ this.$refs.removeDialog.setResult({ error: this.say('deleteStateFailed') });
894
+ }
895
+ },
896
+ });
897
+ },
898
+
899
+ /**
900
+ * The removal dialog closed without a removal.
901
+ *
902
+ * @return {void}
903
+ */
904
+ cancelRemoval() {
905
+ this.pendingRemoval = null;
906
+ this.syncTick += 1;
907
+ },
908
+
909
+ /**
910
+ * Check the machine and show what is wrong with it.
911
+ *
912
+ * @return {boolean} True when nothing blocks: no errors, and no warnings
913
+ * either when `config.blockOnWarnings` is set.
914
+ * @public
915
+ */
916
+ validate() {
917
+ this.issues = validateStateMachine(
918
+ { states: this.states, transitions: this.transitions },
919
+ {
920
+ keys: {
921
+ label: this.keys.stateLabel,
922
+ final: this.keys.stateFinal,
923
+ from: this.keys.transitionFrom,
924
+ to: this.keys.transitionTo,
925
+ transitionLabel: this.keys.transitionLabel,
926
+ },
927
+ messages: this.config.messages,
928
+ translate: (text) => this.tr(text),
929
+ },
930
+ );
931
+ /**
932
+ * @event validated The issues validate() found.
933
+ */
934
+ this.$emit('validated', this.issues);
935
+ const blocking = this.config.blockOnWarnings === true
936
+ ? this.issues
937
+ : this.issues.filter((issue) => issue.type === 'error');
938
+ return blocking.length === 0
939
+ },
940
+ },
941
+ };
942
+
943
+ export { DEFAULT_STATE_MACHINE_EDITOR_KEYS, script as default };
944
+ //# sourceMappingURL=CnStateMachineEditor.vue2.js.map