@conduction/nextcloud-vue 2.114.0 → 2.115.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 (118) hide show
  1. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
  2. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +1 -1
  3. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
  5. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  6. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +6 -2
  7. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  8. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  9. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
  10. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +2 -1
  11. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
  12. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
  13. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  14. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +19 -2
  15. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -3
  17. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  19. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +2 -2
  20. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  21. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  22. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +37 -1
  23. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  24. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  25. package/dist/esm/components/CnIndexPage/rowsToCsv.js +90 -0
  26. package/dist/esm/components/CnIndexPage/rowsToCsv.js.map +1 -0
  27. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue.js +9 -0
  28. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue.js.map +1 -0
  29. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue2.js +161 -0
  30. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue2.js.map +1 -0
  31. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue3.js +97 -0
  32. package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue3.js.map +1 -0
  33. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue.js +9 -0
  34. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue.js.map +1 -0
  35. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue2.js +63 -0
  36. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue2.js.map +1 -0
  37. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue3.js +54 -0
  38. package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue3.js.map +1 -0
  39. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +1 -1
  40. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js +15 -9
  41. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -1
  42. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js +55 -63
  43. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -1
  44. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue.js +1 -1
  45. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js +2 -1
  46. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  47. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  48. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
  49. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +13 -4
  50. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  51. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +2 -1
  52. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  53. package/dist/esm/components/CnStepper/CnStepper.vue.js +1 -1
  54. package/dist/esm/components/CnStepper/CnStepper.vue2.js.map +1 -1
  55. package/dist/esm/components/CnStepper/CnStepper.vue3.js.map +1 -1
  56. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  57. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +10 -5
  58. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  59. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +1 -1
  60. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  61. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue.js +1 -1
  62. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  63. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +2 -2
  64. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  65. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +32 -20
  66. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  67. package/dist/esm/composables/indexSources.js +43 -11
  68. package/dist/esm/composables/indexSources.js.map +1 -1
  69. package/dist/esm/composables/useTaskInboxStore.js +41 -0
  70. package/dist/esm/composables/useTaskInboxStore.js.map +1 -1
  71. package/dist/esm/index.js +1 -0
  72. package/dist/esm/index.js.map +1 -1
  73. package/dist/esm/l10n/en.json.js +4 -1
  74. package/dist/esm/l10n/en.json.js.map +1 -1
  75. package/dist/esm/l10n/nl.json.js +9 -1
  76. package/dist/esm/l10n/nl.json.js.map +1 -1
  77. package/dist/esm/library-style.js +1 -1
  78. package/dist/esm/nextcloud-vue.css +482 -330
  79. package/dist/esm/utils/contentHeaderLink.js +37 -1
  80. package/dist/esm/utils/contentHeaderLink.js.map +1 -1
  81. package/dist/esm/utils/declaredMacros.js +31 -0
  82. package/dist/esm/utils/declaredMacros.js.map +1 -0
  83. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  84. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  85. package/dist/nextcloud-vue.cjs.js +2673 -1977
  86. package/dist/nextcloud-vue.cjs.js.map +2 -2
  87. package/dist/nextcloud-vue.css +482 -330
  88. package/l10n/en.json +4 -1
  89. package/l10n/nl.json +9 -1
  90. package/package.json +1 -1
  91. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +1 -1
  92. package/src/components/CnCellRenderer/CnCellRenderer.vue +6 -2
  93. package/src/components/CnChoiceCards/CnChoiceCards.vue +2 -1
  94. package/src/components/CnDashboardPage/CnDashboardPage.vue +45 -3
  95. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
  96. package/src/components/CnIndexPage/CnIndexPage.vue +37 -1
  97. package/src/components/CnIndexPage/rowsToCsv.js +87 -0
  98. package/src/components/CnMacrosWidget/CnMacrosWidget.md +30 -0
  99. package/src/components/CnMacrosWidget/CnMacrosWidget.vue +266 -0
  100. package/src/components/CnMacrosWidget/index.js +6 -0
  101. package/src/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue +104 -0
  102. package/src/components/CnRetentionWidget/CnRetentionWidget.vue +53 -38
  103. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +2 -1
  104. package/src/components/CnSetupWizard/CnSetupWizard.vue +28 -4
  105. package/src/components/CnStepper/CnStepper.vue +2 -1
  106. package/src/components/CnTabsWidget/CnTabsWidget.vue +11 -6
  107. package/src/components/CnTasksWidget/CnTasksWidget.vue +2 -2
  108. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
  109. package/src/components/index.js +1 -0
  110. package/src/composables/indexSources.js +43 -11
  111. package/src/composables/useTaskInboxStore.js +41 -0
  112. package/src/css/look-board-detail.css +4 -3
  113. package/src/css/look-board-index.css +62 -0
  114. package/src/css/look-board.css +20 -0
  115. package/src/index.js +1 -0
  116. package/src/utils/contentHeaderLink.js +35 -0
  117. package/src/utils/declaredMacros.js +28 -0
  118. package/src/utils/libraryWidgetKeys.js +1 -0
@@ -1,3 +1,5 @@
1
+ import { resolveDeepTokens } from './resolveFilterTokens.js';
2
+
1
3
  /**
2
4
  * SPDX-FileCopyrightText: 2026 Conduction B.V.
3
5
  * SPDX-License-Identifier: EUPL-1.2
@@ -9,6 +11,7 @@
9
11
  * @module utils/contentHeaderLink
10
12
  */
11
13
 
14
+
12
15
  /**
13
16
  * The header link a widget's `content` declares, in the shape
14
17
  * CnWidgetWrapper's `headerLink` takes, or null when it declares none.
@@ -94,5 +97,38 @@ function headerLinkTarget(link, hasRouter) {
94
97
  return { tag: '', attrs: {} }
95
98
  }
96
99
 
97
- export { contentHeaderLink, headerLinkTarget, widgetHeaderLink };
100
+ /**
101
+ * A header link with the `@objectId` and `@object.<path>` tokens in its
102
+ * `params` and `query` resolved against the record the page shows
103
+ * (`{ route: 'WorkflowDefinitionDetail', params: { id: '@object.workflowDefinition' } }`).
104
+ * A link whose route params do not all resolve is no link: the record does
105
+ * not name the page it would open.
106
+ *
107
+ * @param {object|null|undefined} link A link `{ label, route?, params?, query?, href? }`.
108
+ * @param {{objectId?: (string|number), object?: object}} ctx The record.
109
+ * @return {object|null} The link with its tokens resolved, or null.
110
+ * @spec openspec/changes/header-link-param-tokens/specs/header-link-param-tokens/spec.md#requirement-a-header-links-route-params-read-the-record
111
+ */
112
+ function resolveHeaderLink(link, ctx) {
113
+ if (!link || typeof link !== 'object') {
114
+ return null
115
+ }
116
+ if (!link.params && !link.query) {
117
+ return link
118
+ }
119
+ const out = { ...link };
120
+ if (link.params && typeof link.params === 'object') {
121
+ out.params = resolveDeepTokens(link.params, ctx || {});
122
+ const filled = Object.values(out.params).every((value) => value !== null && value !== undefined && value !== '' && !(typeof value === 'string' && value.startsWith('@')));
123
+ if (!filled) {
124
+ return null
125
+ }
126
+ }
127
+ if (link.query && typeof link.query === 'object') {
128
+ out.query = resolveDeepTokens(link.query, ctx || {});
129
+ }
130
+ return out
131
+ }
132
+
133
+ export { contentHeaderLink, headerLinkTarget, resolveHeaderLink, widgetHeaderLink };
98
134
  //# sourceMappingURL=contentHeaderLink.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contentHeaderLink.js","sources":["../../../src/utils/contentHeaderLink.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * contentHeaderLink — the text link a widget's content asks its card header\n * to carry: `content.headerLink`, or the shorter `viewAllRoute` (with an\n * optional `viewAllLabel`) that an inbox-style widget uses for its \"View all\".\n *\n * @module utils/contentHeaderLink\n */\n\n/**\n * The header link a widget's `content` declares, in the shape\n * CnWidgetWrapper's `headerLink` takes, or null when it declares none.\n * The label is left as written: the wrapper translates it.\n *\n * `viewAllRoute` is a route name, or a location `{ name, params?, query? }`.\n *\n * @param {object|null|undefined} content The widget's content.\n * @return {{label: string, route?: string, params?: object, query?: object, href?: string}|null}\n */\nexport function contentHeaderLink(content) {\n\tif (!content || typeof content !== 'object') {\n\t\treturn null\n\t}\n\tconst declared = content.headerLink\n\tif (declared && typeof declared === 'object' && typeof declared.label === 'string' && declared.label !== '') {\n\t\treturn declared\n\t}\n\tconst view = content.viewAllRoute\n\tconst name = typeof view === 'string' ? view : (view && typeof view === 'object' ? view.name : '')\n\tif (typeof name !== 'string' || name === '') {\n\t\treturn null\n\t}\n\tconst link = {\n\t\tlabel: typeof content.viewAllLabel === 'string' && content.viewAllLabel !== '' ? content.viewAllLabel : 'View all',\n\t\troute: name,\n\t}\n\tif (view && typeof view === 'object') {\n\t\tif (view.params && typeof view.params === 'object') {\n\t\t\tlink.params = view.params\n\t\t}\n\t\tif (view.query && typeof view.query === 'object') {\n\t\t\tlink.query = view.query\n\t\t}\n\t}\n\treturn link\n}\n\n/**\n * The header link a widget DEFINITION declares: `headerLink` on the\n * definition itself, else what its content asks for (see contentHeaderLink).\n *\n * @param {object|null|undefined} widget A widget definition.\n * @return {{label: string, route?: string, params?: object, query?: object, href?: string}|null}\n */\nexport function widgetHeaderLink(widget) {\n\tif (!widget || typeof widget !== 'object') {\n\t\treturn null\n\t}\n\tconst declared = widget.headerLink\n\tif (declared && typeof declared === 'object' && typeof declared.label === 'string' && declared.label !== '') {\n\t\treturn declared\n\t}\n\treturn contentHeaderLink(widget.content)\n}\n\n/**\n * How to draw a header link: the tag and its attributes. A `route` is a\n * `router-link` (only when a router is mounted), an `href` a plain anchor.\n * An empty tag means there is nothing usable to draw.\n *\n * @param {object|null|undefined} link A link `{ label, route?, params?, query?, href? }`.\n * @param {boolean} hasRouter Whether a router is mounted.\n * @return {{tag: string, attrs: object}}\n */\nexport function headerLinkTarget(link, hasRouter) {\n\tif (!link || typeof link.label !== 'string' || link.label === '') {\n\t\treturn { tag: '', attrs: {} }\n\t}\n\tif (link.route && hasRouter) {\n\t\tconst to = { name: link.route }\n\t\tif (link.params && typeof link.params === 'object') {\n\t\t\tto.params = link.params\n\t\t}\n\t\tif (link.query && typeof link.query === 'object') {\n\t\t\tto.query = link.query\n\t\t}\n\t\treturn { tag: 'router-link', attrs: { to } }\n\t}\n\tif (typeof link.href === 'string' && link.href !== '') {\n\t\treturn { tag: 'a', attrs: { href: link.href } }\n\t}\n\treturn { tag: '', attrs: {} }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contentHeaderLink.js","sources":["../../../src/utils/contentHeaderLink.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * contentHeaderLink — the text link a widget's content asks its card header\n * to carry: `content.headerLink`, or the shorter `viewAllRoute` (with an\n * optional `viewAllLabel`) that an inbox-style widget uses for its \"View all\".\n *\n * @module utils/contentHeaderLink\n */\n\nimport { resolveDeepTokens } from './resolveFilterTokens.js'\n\n/**\n * The header link a widget's `content` declares, in the shape\n * CnWidgetWrapper's `headerLink` takes, or null when it declares none.\n * The label is left as written: the wrapper translates it.\n *\n * `viewAllRoute` is a route name, or a location `{ name, params?, query? }`.\n *\n * @param {object|null|undefined} content The widget's content.\n * @return {{label: string, route?: string, params?: object, query?: object, href?: string}|null}\n */\nexport function contentHeaderLink(content) {\n\tif (!content || typeof content !== 'object') {\n\t\treturn null\n\t}\n\tconst declared = content.headerLink\n\tif (declared && typeof declared === 'object' && typeof declared.label === 'string' && declared.label !== '') {\n\t\treturn declared\n\t}\n\tconst view = content.viewAllRoute\n\tconst name = typeof view === 'string' ? view : (view && typeof view === 'object' ? view.name : '')\n\tif (typeof name !== 'string' || name === '') {\n\t\treturn null\n\t}\n\tconst link = {\n\t\tlabel: typeof content.viewAllLabel === 'string' && content.viewAllLabel !== '' ? content.viewAllLabel : 'View all',\n\t\troute: name,\n\t}\n\tif (view && typeof view === 'object') {\n\t\tif (view.params && typeof view.params === 'object') {\n\t\t\tlink.params = view.params\n\t\t}\n\t\tif (view.query && typeof view.query === 'object') {\n\t\t\tlink.query = view.query\n\t\t}\n\t}\n\treturn link\n}\n\n/**\n * The header link a widget DEFINITION declares: `headerLink` on the\n * definition itself, else what its content asks for (see contentHeaderLink).\n *\n * @param {object|null|undefined} widget A widget definition.\n * @return {{label: string, route?: string, params?: object, query?: object, href?: string}|null}\n */\nexport function widgetHeaderLink(widget) {\n\tif (!widget || typeof widget !== 'object') {\n\t\treturn null\n\t}\n\tconst declared = widget.headerLink\n\tif (declared && typeof declared === 'object' && typeof declared.label === 'string' && declared.label !== '') {\n\t\treturn declared\n\t}\n\treturn contentHeaderLink(widget.content)\n}\n\n/**\n * How to draw a header link: the tag and its attributes. A `route` is a\n * `router-link` (only when a router is mounted), an `href` a plain anchor.\n * An empty tag means there is nothing usable to draw.\n *\n * @param {object|null|undefined} link A link `{ label, route?, params?, query?, href? }`.\n * @param {boolean} hasRouter Whether a router is mounted.\n * @return {{tag: string, attrs: object}}\n */\nexport function headerLinkTarget(link, hasRouter) {\n\tif (!link || typeof link.label !== 'string' || link.label === '') {\n\t\treturn { tag: '', attrs: {} }\n\t}\n\tif (link.route && hasRouter) {\n\t\tconst to = { name: link.route }\n\t\tif (link.params && typeof link.params === 'object') {\n\t\t\tto.params = link.params\n\t\t}\n\t\tif (link.query && typeof link.query === 'object') {\n\t\t\tto.query = link.query\n\t\t}\n\t\treturn { tag: 'router-link', attrs: { to } }\n\t}\n\tif (typeof link.href === 'string' && link.href !== '') {\n\t\treturn { tag: 'a', attrs: { href: link.href } }\n\t}\n\treturn { tag: '', attrs: {} }\n}\n\n/**\n * A header link with the `@objectId` and `@object.<path>` tokens in its\n * `params` and `query` resolved against the record the page shows\n * (`{ route: 'WorkflowDefinitionDetail', params: { id: '@object.workflowDefinition' } }`).\n * A link whose route params do not all resolve is no link: the record does\n * not name the page it would open.\n *\n * @param {object|null|undefined} link A link `{ label, route?, params?, query?, href? }`.\n * @param {{objectId?: (string|number), object?: object}} ctx The record.\n * @return {object|null} The link with its tokens resolved, or null.\n * @spec openspec/changes/header-link-param-tokens/specs/header-link-param-tokens/spec.md#requirement-a-header-links-route-params-read-the-record\n */\nexport function resolveHeaderLink(link, ctx) {\n\tif (!link || typeof link !== 'object') {\n\t\treturn null\n\t}\n\tif (!link.params && !link.query) {\n\t\treturn link\n\t}\n\tconst out = { ...link }\n\tif (link.params && typeof link.params === 'object') {\n\t\tout.params = resolveDeepTokens(link.params, ctx || {})\n\t\tconst filled = Object.values(out.params).every((value) => value !== null && value !== undefined && value !== '' && !(typeof value === 'string' && value.startsWith('@')))\n\t\tif (!filled) {\n\t\t\treturn null\n\t\t}\n\t}\n\tif (link.query && typeof link.query === 'object') {\n\t\tout.query = resolveDeepTokens(link.query, ctx || {})\n\t}\n\treturn out\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ * SPDX-License-Identifier: EUPL-1.2
4
+ *
5
+ * The macros an OpenRegister schema declares: declared actions
6
+ * (`configuration['x-openregister-action']`) with `macro: true` and a bound
7
+ * flow. A declared action without a flow is not a macro and is left out.
8
+ */
9
+
10
+ /**
11
+ * The macros a schema declares, in declaration order.
12
+ *
13
+ * @param {object|null} schema The schema, as OpenRegister returns it.
14
+ * @return {Array<{key: string, name: string, description: string}>} The macros.
15
+ */
16
+ function declaredMacros(schema) {
17
+ const declared = schema?.configuration?.['x-openregister-action'];
18
+ if (!declared || typeof declared !== 'object' || Array.isArray(declared)) {
19
+ return []
20
+ }
21
+ return Object.entries(declared)
22
+ .filter(([, entry]) => entry && typeof entry === 'object' && entry.macro === true && typeof entry.flow === 'string' && entry.flow !== '')
23
+ .map(([key, entry]) => ({
24
+ key,
25
+ name: typeof entry.name === 'string' && entry.name !== '' ? entry.name : key,
26
+ description: typeof entry.description === 'string' ? entry.description : '',
27
+ }))
28
+ }
29
+
30
+ export { declaredMacros };
31
+ //# sourceMappingURL=declaredMacros.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declaredMacros.js","sources":["../../../src/utils/declaredMacros.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * The macros an OpenRegister schema declares: declared actions\n * (`configuration['x-openregister-action']`) with `macro: true` and a bound\n * flow. A declared action without a flow is not a macro and is left out.\n */\n\n/**\n * The macros a schema declares, in declaration order.\n *\n * @param {object|null} schema The schema, as OpenRegister returns it.\n * @return {Array<{key: string, name: string, description: string}>} The macros.\n */\nexport function declaredMacros(schema) {\n\tconst declared = schema?.configuration?.['x-openregister-action']\n\tif (!declared || typeof declared !== 'object' || Array.isArray(declared)) {\n\t\treturn []\n\t}\n\treturn Object.entries(declared)\n\t\t.filter(([, entry]) => entry && typeof entry === 'object' && entry.macro === true && typeof entry.flow === 'string' && entry.flow !== '')\n\t\t.map(([key, entry]) => ({\n\t\t\tkey,\n\t\t\tname: typeof entry.name === 'string' && entry.name !== '' ? entry.name : key,\n\t\t\tdescription: typeof entry.description === 'string' ? entry.description : '',\n\t\t}))\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc,CAAC,MAAM,EAAE;AACvC,CAAC,MAAM,QAAQ,GAAG,MAAM,EAAE,aAAa,GAAG,uBAAuB,EAAC;AAClE,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AAC3E,EAAE,OAAO,EAAE;AACX,EAAE;AACF,CAAC,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;AAChC,GAAG,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;AAC3I,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM;AAC1B,GAAG,GAAG;AACN,GAAG,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG;AAC/E,GAAG,WAAW,EAAE,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,GAAG,KAAK,CAAC,WAAW,GAAG,EAAE;AAC9E,GAAG,CAAC,CAAC;AACL;;;;"}
@@ -124,6 +124,7 @@ const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([
124
124
  'link',
125
125
  'linked',
126
126
  'links',
127
+ 'macros',
127
128
  'mail',
128
129
  'map',
129
130
  'markdown',
@@ -1 +1 @@
1
- {"version":3,"file":"libraryWidgetKeys.js","sources":["../../../src/utils/libraryWidgetKeys.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * libraryWidgetKeys — the one vocabulary of widget keys the LIBRARY itself\n * renders, and the only list `validateManifestV2` is allowed to consult.\n *\n * WHY THIS MODULE EXISTS\n * ----------------------\n * The validator used to carry its own hand-written array of \"library built-in\n * widget keys\", with a comment instructing whoever added a built-in to append\n * it \"in the same PR\". That instruction was followed for five keys and missed\n * for six, so the validator knew 11 keys while the library actually rendered\n * 45. Nothing failed when the two disagreed, because the only consumer is an\n * exemption: a key the validator does not recognise is treated as a CUSTOM\n * registry component, which makes a legitimate single-widget library dashboard\n * fail the ADR-036 Decision 1 anti-pattern rule with advice (\"declare it as\n * type:'custom'\") that is wrong for a library widget.\n *\n * A comment cannot enforce anything, so the array moved here and\n * `tests/utils/libraryWidgetKeys.spec.js` now binds it to the two registries\n * that actually resolve a key at runtime:\n *\n * 1. `BUILT_IN_WIDGETS` (components/CnWidgetGrid/builtInWidgets.js) — the v2\n * manifest widget set `CnWidgetGrid` resolves a `widgetKey` against.\n * 2. The dashboard widget catalog (`dashboardWidgetRegistry`), populated by\n * `registerDashboardWidgets.js`. `CnWidgetGrid` falls back to it (third in\n * the chain, after the consumer registry and `BUILT_IN_WIDGETS`), so a\n * catalog key renders on a v2 page exactly like a `BUILT_IN_WIDGETS` one.\n *\n * The test asserts SET EQUALITY in both directions against the live registries,\n * so adding a widget to either registry without touching this file fails CI,\n * and deleting one without removing it here fails too. The lists below are the\n * validator's view; the registries are the truth the test holds them to.\n *\n * THE CATALOG IS NOT LEGACY. It is a live half of the same vocabulary, and the\n * old array already conceded the point by exempting `chart` and `stats-block`,\n * which are catalog-only keys that `BUILT_IN_WIDGETS` has never held. What it\n * got wrong was doing that for two keys and not the other thirty-seven.\n * `widgetDispatch.js` unified the two resolution paths for the same reason: a\n * widget authored against one vocabulary was invisible to the other and said\n * nothing about why (101 of 236 detail widgets on hrmq).\n *\n * @module utils/libraryWidgetKeys\n */\n\nimport { WIDGET_TYPE_ALIASES } from './widgetTypeAliases.js'\n\n/**\n * Keys of `BUILT_IN_WIDGETS` — the v2 manifest widget set.\n *\n * Kept in the registry's own declaration order so a diff against\n * `builtInWidgets.js` reads straight down.\n *\n * @type {string[]} Frozen.\n */\nexport const BUILT_IN_WIDGET_KEYS = Object.freeze([\n\t'object-table',\n\t'form-renderer',\n\t'map-viewer',\n\t'notice',\n\t'decision-list',\n\t'object-geo',\n\t'card-grid',\n\t'nav-card-grid',\n\t'data',\n\t'metadata',\n\t'related',\n\t'integration',\n\t'banner',\n\t'audit-trail',\n\t'timeline',\n\t'header',\n\t'text',\n\t'divider',\n\t'saved-view-alert',\n\t'exports',\n])\n\n/**\n * Widget types the LIBRARY registers into the dashboard catalog at import time\n * (`registerDashboardWidgets.js` and the widget `index.js` modules it pulls in).\n *\n * Deliberately a static list rather than a read of `dashboardWidgetRegistry`:\n * that object is mutable and consumer-extensible, so deriving the exemption\n * from it at call time would let an app register its own full-page component in\n * the catalog and walk straight through the ADR-036 Decision 1 rule the\n * exemption exists to enforce. Only keys the library itself ships are exempt.\n *\n * Sorted, because unlike `BUILT_IN_WIDGETS` these registrations are spread over\n * ~30 files and have no meaningful declaration order.\n *\n * @type {string[]} Frozen.\n */\nexport const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([\n\t'ai-chat',\n\t'audit-trail',\n\t'banner',\n\t'calendar',\n\t'chart',\n\t'checklist-run',\n\t'chips-field',\n\t'choice-picker',\n\t'container',\n\t'conversation',\n\t'countdown',\n\t'data',\n\t'delta',\n\t'device-frames',\n\t'divider',\n\t'document-review',\n\t'facts',\n\t'field-list',\n\t'files',\n\t'flow-runs',\n\t'gauge',\n\t'grouped-cards',\n\t'header',\n\t'image',\n\t'interaction-form',\n\t'kb-search',\n\t'label',\n\t'link',\n\t'linked',\n\t'links',\n\t'mail',\n\t'map',\n\t'markdown',\n\t'menu',\n\t'nc-widget',\n\t'next-step',\n\t'notepad',\n\t// `news` was here until the widget moved to LaunchPad, which owns the feed\n\t// fetching. An app that renders one now gets it from LaunchPad's registry.\n\t'object-geo',\n\t'object-list',\n\t'object-table',\n\t'party-actions',\n\t'people',\n\t'plan',\n\t'quicklinks',\n\t'radio-cards',\n\t'record-list',\n\t'related',\n\t'retention',\n\t'saved-view',\n\t'saved-views',\n\t'sections',\n\t'settings-form',\n\t'spend-analytics',\n\t'stacked-bar',\n\t'stages',\n\t'stat',\n\t'stats-block',\n\t'switch-rows',\n\t'table',\n\t'tabs',\n\t'tasks',\n\t'team-workload',\n\t'text',\n\t'tile',\n\t'timeline',\n\t'toggle-table',\n\t'video',\n\t'week-strip',\n\t'working-calendar',\n\t'work-queue',\n\t'workspace-filter',\n])\n\n/**\n * Expand a key set over `WIDGET_TYPE_ALIASES` so both spellings of an aliased\n * widget are present whenever either one is.\n *\n * `CnWidgetGrid` resolves a key and its canonical form (`object-table` ⇄\n * `table`, `map-viewer` ⇄ `map`), so both spellings render and both must be\n * exempt. Today each registry happens to hold one side of each pair, which is\n * exactly the accident that would silently stop being true when the next alias\n * lands.\n *\n * @param {Set<string>} keys The key set to expand, mutated in place.\n * @return {Set<string>} The same set.\n */\nfunction expandAliases(keys) {\n\tfor (const [alias, canonical] of Object.entries(WIDGET_TYPE_ALIASES)) {\n\t\tif (keys.has(alias) || keys.has(canonical)) {\n\t\t\tkeys.add(alias)\n\t\t\tkeys.add(canonical)\n\t\t}\n\t}\n\treturn keys\n}\n\n/**\n * Every widget key the library renders itself: both registries, plus both\n * spellings of every alias.\n *\n * A `widgetKey` in this list is served by a library `Cn*` SFC and does NOT\n * count as a custom registry component for the single-12×12-widget dashboard\n * rule (ADR-036 Decision 1).\n *\n * @type {string[]} Frozen.\n */\nexport const LIBRARY_WIDGET_KEYS = Object.freeze([\n\t...expandAliases(new Set([\n\t\t...BUILT_IN_WIDGET_KEYS,\n\t\t...DASHBOARD_CATALOG_WIDGET_KEYS,\n\t])),\n])\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;AAClD,CAAC,cAAc;AACf,CAAC,eAAe;AAChB,CAAC,YAAY;AACb,CAAC,QAAQ;AACT,CAAC,eAAe;AAChB,CAAC,YAAY;AACb,CAAC,WAAW;AACZ,CAAC,eAAe;AAChB,CAAC,MAAM;AACP,CAAC,UAAU;AACX,CAAC,SAAS;AACV,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,aAAa;AACd,CAAC,UAAU;AACX,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,SAAS;AACV,CAAC,kBAAkB;AACnB,CAAC,SAAS;AACV,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,6BAA6B,GAAG,MAAM,CAAC,MAAM,CAAC;AAC3D,CAAC,SAAS;AACV,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,UAAU;AACX,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,aAAa;AACd,CAAC,eAAe;AAChB,CAAC,WAAW;AACZ,CAAC,cAAc;AACf,CAAC,WAAW;AACZ,CAAC,MAAM;AACP,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,SAAS;AACV,CAAC,iBAAiB;AAClB,CAAC,OAAO;AACR,CAAC,YAAY;AACb,CAAC,OAAO;AACR,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,QAAQ;AACT,CAAC,OAAO;AACR,CAAC,kBAAkB;AACnB,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,QAAQ;AACT,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,KAAK;AACN,CAAC,UAAU;AACX,CAAC,MAAM;AACP,CAAC,WAAW;AACZ,CAAC,WAAW;AACZ,CAAC,SAAS;AACV;AACA;AACA,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,cAAc;AACf,CAAC,eAAe;AAChB,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,SAAS;AACV,CAAC,WAAW;AACZ,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,UAAU;AACX,CAAC,eAAe;AAChB,CAAC,iBAAiB;AAClB,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,MAAM;AACP,CAAC,MAAM;AACP,CAAC,UAAU;AACX,CAAC,cAAc;AACf,CAAC,OAAO;AACR,CAAC,YAAY;AACb,CAAC,kBAAkB;AACnB,CAAC,YAAY;AACb,CAAC,kBAAkB;AACnB,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,IAAI,EAAE;AAC7B,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE;AACvE,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AAC9C,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAC;AAClB,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAC;AACtB,GAAG;AACH,EAAE;AACF,CAAC,OAAO,IAAI;AACZ,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;AACjD,CAAC,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC;AAC1B,EAAE,GAAG,oBAAoB;AACzB,EAAE,GAAG,6BAA6B;AAClC,EAAE,CAAC,CAAC;AACJ,CAAC;;;;"}
1
+ {"version":3,"file":"libraryWidgetKeys.js","sources":["../../../src/utils/libraryWidgetKeys.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * libraryWidgetKeys — the one vocabulary of widget keys the LIBRARY itself\n * renders, and the only list `validateManifestV2` is allowed to consult.\n *\n * WHY THIS MODULE EXISTS\n * ----------------------\n * The validator used to carry its own hand-written array of \"library built-in\n * widget keys\", with a comment instructing whoever added a built-in to append\n * it \"in the same PR\". That instruction was followed for five keys and missed\n * for six, so the validator knew 11 keys while the library actually rendered\n * 45. Nothing failed when the two disagreed, because the only consumer is an\n * exemption: a key the validator does not recognise is treated as a CUSTOM\n * registry component, which makes a legitimate single-widget library dashboard\n * fail the ADR-036 Decision 1 anti-pattern rule with advice (\"declare it as\n * type:'custom'\") that is wrong for a library widget.\n *\n * A comment cannot enforce anything, so the array moved here and\n * `tests/utils/libraryWidgetKeys.spec.js` now binds it to the two registries\n * that actually resolve a key at runtime:\n *\n * 1. `BUILT_IN_WIDGETS` (components/CnWidgetGrid/builtInWidgets.js) — the v2\n * manifest widget set `CnWidgetGrid` resolves a `widgetKey` against.\n * 2. The dashboard widget catalog (`dashboardWidgetRegistry`), populated by\n * `registerDashboardWidgets.js`. `CnWidgetGrid` falls back to it (third in\n * the chain, after the consumer registry and `BUILT_IN_WIDGETS`), so a\n * catalog key renders on a v2 page exactly like a `BUILT_IN_WIDGETS` one.\n *\n * The test asserts SET EQUALITY in both directions against the live registries,\n * so adding a widget to either registry without touching this file fails CI,\n * and deleting one without removing it here fails too. The lists below are the\n * validator's view; the registries are the truth the test holds them to.\n *\n * THE CATALOG IS NOT LEGACY. It is a live half of the same vocabulary, and the\n * old array already conceded the point by exempting `chart` and `stats-block`,\n * which are catalog-only keys that `BUILT_IN_WIDGETS` has never held. What it\n * got wrong was doing that for two keys and not the other thirty-seven.\n * `widgetDispatch.js` unified the two resolution paths for the same reason: a\n * widget authored against one vocabulary was invisible to the other and said\n * nothing about why (101 of 236 detail widgets on hrmq).\n *\n * @module utils/libraryWidgetKeys\n */\n\nimport { WIDGET_TYPE_ALIASES } from './widgetTypeAliases.js'\n\n/**\n * Keys of `BUILT_IN_WIDGETS` — the v2 manifest widget set.\n *\n * Kept in the registry's own declaration order so a diff against\n * `builtInWidgets.js` reads straight down.\n *\n * @type {string[]} Frozen.\n */\nexport const BUILT_IN_WIDGET_KEYS = Object.freeze([\n\t'object-table',\n\t'form-renderer',\n\t'map-viewer',\n\t'notice',\n\t'decision-list',\n\t'object-geo',\n\t'card-grid',\n\t'nav-card-grid',\n\t'data',\n\t'metadata',\n\t'related',\n\t'integration',\n\t'banner',\n\t'audit-trail',\n\t'timeline',\n\t'header',\n\t'text',\n\t'divider',\n\t'saved-view-alert',\n\t'exports',\n])\n\n/**\n * Widget types the LIBRARY registers into the dashboard catalog at import time\n * (`registerDashboardWidgets.js` and the widget `index.js` modules it pulls in).\n *\n * Deliberately a static list rather than a read of `dashboardWidgetRegistry`:\n * that object is mutable and consumer-extensible, so deriving the exemption\n * from it at call time would let an app register its own full-page component in\n * the catalog and walk straight through the ADR-036 Decision 1 rule the\n * exemption exists to enforce. Only keys the library itself ships are exempt.\n *\n * Sorted, because unlike `BUILT_IN_WIDGETS` these registrations are spread over\n * ~30 files and have no meaningful declaration order.\n *\n * @type {string[]} Frozen.\n */\nexport const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([\n\t'ai-chat',\n\t'audit-trail',\n\t'banner',\n\t'calendar',\n\t'chart',\n\t'checklist-run',\n\t'chips-field',\n\t'choice-picker',\n\t'container',\n\t'conversation',\n\t'countdown',\n\t'data',\n\t'delta',\n\t'device-frames',\n\t'divider',\n\t'document-review',\n\t'facts',\n\t'field-list',\n\t'files',\n\t'flow-runs',\n\t'gauge',\n\t'grouped-cards',\n\t'header',\n\t'image',\n\t'interaction-form',\n\t'kb-search',\n\t'label',\n\t'link',\n\t'linked',\n\t'links',\n\t'macros',\n\t'mail',\n\t'map',\n\t'markdown',\n\t'menu',\n\t'nc-widget',\n\t'next-step',\n\t'notepad',\n\t// `news` was here until the widget moved to LaunchPad, which owns the feed\n\t// fetching. An app that renders one now gets it from LaunchPad's registry.\n\t'object-geo',\n\t'object-list',\n\t'object-table',\n\t'party-actions',\n\t'people',\n\t'plan',\n\t'quicklinks',\n\t'radio-cards',\n\t'record-list',\n\t'related',\n\t'retention',\n\t'saved-view',\n\t'saved-views',\n\t'sections',\n\t'settings-form',\n\t'spend-analytics',\n\t'stacked-bar',\n\t'stages',\n\t'stat',\n\t'stats-block',\n\t'switch-rows',\n\t'table',\n\t'tabs',\n\t'tasks',\n\t'team-workload',\n\t'text',\n\t'tile',\n\t'timeline',\n\t'toggle-table',\n\t'video',\n\t'week-strip',\n\t'working-calendar',\n\t'work-queue',\n\t'workspace-filter',\n])\n\n/**\n * Expand a key set over `WIDGET_TYPE_ALIASES` so both spellings of an aliased\n * widget are present whenever either one is.\n *\n * `CnWidgetGrid` resolves a key and its canonical form (`object-table` ⇄\n * `table`, `map-viewer` ⇄ `map`), so both spellings render and both must be\n * exempt. Today each registry happens to hold one side of each pair, which is\n * exactly the accident that would silently stop being true when the next alias\n * lands.\n *\n * @param {Set<string>} keys The key set to expand, mutated in place.\n * @return {Set<string>} The same set.\n */\nfunction expandAliases(keys) {\n\tfor (const [alias, canonical] of Object.entries(WIDGET_TYPE_ALIASES)) {\n\t\tif (keys.has(alias) || keys.has(canonical)) {\n\t\t\tkeys.add(alias)\n\t\t\tkeys.add(canonical)\n\t\t}\n\t}\n\treturn keys\n}\n\n/**\n * Every widget key the library renders itself: both registries, plus both\n * spellings of every alias.\n *\n * A `widgetKey` in this list is served by a library `Cn*` SFC and does NOT\n * count as a custom registry component for the single-12×12-widget dashboard\n * rule (ADR-036 Decision 1).\n *\n * @type {string[]} Frozen.\n */\nexport const LIBRARY_WIDGET_KEYS = Object.freeze([\n\t...expandAliases(new Set([\n\t\t...BUILT_IN_WIDGET_KEYS,\n\t\t...DASHBOARD_CATALOG_WIDGET_KEYS,\n\t])),\n])\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;AAClD,CAAC,cAAc;AACf,CAAC,eAAe;AAChB,CAAC,YAAY;AACb,CAAC,QAAQ;AACT,CAAC,eAAe;AAChB,CAAC,YAAY;AACb,CAAC,WAAW;AACZ,CAAC,eAAe;AAChB,CAAC,MAAM;AACP,CAAC,UAAU;AACX,CAAC,SAAS;AACV,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,aAAa;AACd,CAAC,UAAU;AACX,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,SAAS;AACV,CAAC,kBAAkB;AACnB,CAAC,SAAS;AACV,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,6BAA6B,GAAG,MAAM,CAAC,MAAM,CAAC;AAC3D,CAAC,SAAS;AACV,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,UAAU;AACX,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,aAAa;AACd,CAAC,eAAe;AAChB,CAAC,WAAW;AACZ,CAAC,cAAc;AACf,CAAC,WAAW;AACZ,CAAC,MAAM;AACP,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,SAAS;AACV,CAAC,iBAAiB;AAClB,CAAC,OAAO;AACR,CAAC,YAAY;AACb,CAAC,OAAO;AACR,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,QAAQ;AACT,CAAC,OAAO;AACR,CAAC,kBAAkB;AACnB,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,QAAQ;AACT,CAAC,OAAO;AACR,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,KAAK;AACN,CAAC,UAAU;AACX,CAAC,MAAM;AACP,CAAC,WAAW;AACZ,CAAC,WAAW;AACZ,CAAC,SAAS;AACV;AACA;AACA,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,cAAc;AACf,CAAC,eAAe;AAChB,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,SAAS;AACV,CAAC,WAAW;AACZ,CAAC,YAAY;AACb,CAAC,aAAa;AACd,CAAC,UAAU;AACX,CAAC,eAAe;AAChB,CAAC,iBAAiB;AAClB,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,OAAO;AACR,CAAC,eAAe;AAChB,CAAC,MAAM;AACP,CAAC,MAAM;AACP,CAAC,UAAU;AACX,CAAC,cAAc;AACf,CAAC,OAAO;AACR,CAAC,YAAY;AACb,CAAC,kBAAkB;AACnB,CAAC,YAAY;AACb,CAAC,kBAAkB;AACnB,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,IAAI,EAAE;AAC7B,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE;AACvE,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AAC9C,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAC;AAClB,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAC;AACtB,GAAG;AACH,EAAE;AACF,CAAC,OAAO,IAAI;AACZ,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;AACjD,CAAC,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC;AAC1B,EAAE,GAAG,oBAAoB;AACzB,EAAE,GAAG,6BAA6B;AAClC,EAAE,CAAC,CAAC;AACJ,CAAC;;;;"}