@limetech/lime-crm-building-blocks 1.125.0 → 1.126.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 (245) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cjs/lime-crm-building-blocks.cjs.js +1 -1
  3. package/dist/cjs/limebb-alert-dialog.cjs.entry.js +1 -1
  4. package/dist/cjs/limebb-browser.cjs.entry.js +2 -2
  5. package/dist/cjs/limebb-chat-icon-list_3.cjs.entry.js +4 -4
  6. package/dist/cjs/limebb-chat-list.cjs.entry.js +1 -1
  7. package/dist/cjs/limebb-color-palette-picker.cjs.entry.js +1 -1
  8. package/dist/cjs/limebb-color-palette-swatches.cjs.entry.js +1 -1
  9. package/dist/cjs/limebb-component-config.cjs.entry.js +2 -14
  10. package/dist/cjs/limebb-composer-toolbar.cjs.entry.js +3 -3
  11. package/dist/cjs/limebb-currency-picker.cjs.entry.js +1 -1
  12. package/dist/cjs/limebb-dashboard-widget.cjs.entry.js +1 -1
  13. package/dist/cjs/limebb-date-picker.cjs.entry.js +1 -1
  14. package/dist/cjs/limebb-date-range.cjs.entry.js +1 -1
  15. package/dist/cjs/limebb-document-chips.cjs.entry.js +1 -1
  16. package/dist/cjs/limebb-document-item.cjs.entry.js +2 -2
  17. package/dist/cjs/limebb-document-picker.cjs.entry.js +1 -1
  18. package/dist/cjs/limebb-feed-item-thumbnail-file-info.cjs.entry.js +1 -1
  19. package/dist/cjs/limebb-feed-timeline-item.cjs.entry.js +1 -1
  20. package/dist/cjs/limebb-feed.cjs.entry.js +1 -1
  21. package/dist/cjs/limebb-icon-picker.cjs.entry.js +1 -1
  22. package/dist/cjs/limebb-info-tile-format.cjs.entry.js +1 -1
  23. package/dist/cjs/limebb-info-tile.cjs.entry.js +1 -1
  24. package/dist/cjs/limebb-kanban-group.cjs.entry.js +1 -1
  25. package/dist/cjs/limebb-kanban-item.cjs.entry.js +1 -1
  26. package/dist/cjs/limebb-lime-query-builder.cjs.entry.js +1 -1
  27. package/dist/cjs/limebb-lime-query-filter-builder_3.cjs.entry.js +2 -2
  28. package/dist/cjs/limebb-lime-query-filter-comparison_2.cjs.entry.js +1 -1
  29. package/dist/cjs/limebb-lime-query-filter-group_3.cjs.entry.js +3 -3
  30. package/dist/cjs/limebb-lime-query-order-by-item.cjs.entry.js +2 -2
  31. package/dist/cjs/limebb-lime-query-response-format-builder.cjs.entry.js +1 -1
  32. package/dist/cjs/limebb-lime-query-response-format-editor_2.cjs.entry.js +1 -1
  33. package/dist/cjs/limebb-live-docs-info.cjs.entry.js +2 -2
  34. package/dist/cjs/limebb-locale-picker.cjs.entry.js +1 -1
  35. package/dist/cjs/limebb-mention-group-counter.cjs.entry.js +2 -2
  36. package/dist/cjs/limebb-navigation-button_2.cjs.entry.js +2 -2
  37. package/dist/cjs/limebb-notification-item.cjs.entry.js +1 -1
  38. package/dist/cjs/limebb-percentage-visualizer.cjs.entry.js +2 -2
  39. package/dist/cjs/limebb-rule-chip-popover.cjs.entry.js +59 -0
  40. package/dist/cjs/limebb-rule-editor.cjs.entry.js +646 -0
  41. package/dist/cjs/limebb-rule-gate.cjs.entry.js +5 -1
  42. package/dist/cjs/limebb-text-editor.cjs.entry.js +1 -1
  43. package/dist/cjs/limebb-trend-indicator.cjs.entry.js +1 -1
  44. package/dist/cjs/loader.cjs.js +1 -1
  45. package/dist/cjs/web-component-template-BWCutZB6.js +18 -0
  46. package/dist/collection/collection-manifest.json +2 -0
  47. package/dist/collection/components/alert-dialog/alert-dialog.js +1 -1
  48. package/dist/collection/components/browser/browser.js +2 -2
  49. package/dist/collection/components/chat-list/chat-icon-list/chat-icon-list.js +1 -1
  50. package/dist/collection/components/chat-list/chat-item/chat-item.js +2 -2
  51. package/dist/collection/components/chat-list/chat-list.js +1 -1
  52. package/dist/collection/components/chat-list/typing-indicator/typing-indicator.js +1 -1
  53. package/dist/collection/components/color-palette-picker/color-palette-picker.js +1 -1
  54. package/dist/collection/components/color-palette-picker/color-palette-swatches/color-palette-swatches.js +1 -1
  55. package/dist/collection/components/composer-toolbar/composer-toolbar.js +3 -3
  56. package/dist/collection/components/currency-picker/currency-picker.js +1 -1
  57. package/dist/collection/components/dashboard-widget/dashboard-widget.js +1 -1
  58. package/dist/collection/components/date-picker/date-picker.js +1 -1
  59. package/dist/collection/components/date-range/date-range.js +1 -1
  60. package/dist/collection/components/document-chips/document-chips.js +1 -1
  61. package/dist/collection/components/document-picker/document-item/document-item.js +2 -2
  62. package/dist/collection/components/document-picker/document-picker.js +1 -1
  63. package/dist/collection/components/feed/feed-item/feed-timeline-item.js +1 -1
  64. package/dist/collection/components/feed/feed-item-thumbnail-file-info/feed-item-thumbnail-file-info.js +1 -1
  65. package/dist/collection/components/feed/feed.js +1 -1
  66. package/dist/collection/components/icon-picker/icon-picker.js +1 -1
  67. package/dist/collection/components/info-tile/format/config/info-tile-format.js +1 -1
  68. package/dist/collection/components/info-tile/info-tile.js +1 -1
  69. package/dist/collection/components/kanban/kanban-group/kanban-group.js +1 -1
  70. package/dist/collection/components/kanban/kanban-item/kanban-item.js +1 -1
  71. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-comparison.js +1 -1
  72. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-group.js +2 -2
  73. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-not.js +1 -1
  74. package/dist/collection/components/lime-query-builder/lime-query-builder.js +1 -1
  75. package/dist/collection/components/lime-query-builder/lime-query-response-format-builder.js +1 -1
  76. package/dist/collection/components/lime-query-builder/limetype-field/limetype-field.js +1 -1
  77. package/dist/collection/components/lime-query-builder/order-by/order-by-editor.js +1 -1
  78. package/dist/collection/components/lime-query-builder/order-by/order-by-item.js +2 -2
  79. package/dist/collection/components/lime-query-builder/response-format/response-format-item.js +1 -1
  80. package/dist/collection/components/limeobject/file-viewer/live-docs-info.js +2 -2
  81. package/dist/collection/components/locale-picker/locale-picker.js +1 -1
  82. package/dist/collection/components/notification-list/notification-item/notification-item.js +1 -1
  83. package/dist/collection/components/percentage-visualizer/percentage-visualizer.js +2 -2
  84. package/dist/collection/components/rule-editor/chip-picker-view.js +141 -0
  85. package/dist/collection/components/rule-editor/group-node-view.js +79 -0
  86. package/dist/collection/components/rule-editor/rule-chip-popover/rule-chip-popover.css +36 -0
  87. package/dist/collection/components/rule-editor/rule-chip-popover/rule-chip-popover.js +301 -0
  88. package/dist/collection/components/rule-editor/rule-editor-views.js +43 -0
  89. package/dist/collection/components/rule-editor/rule-editor.css +96 -0
  90. package/dist/collection/components/rule-editor/rule-editor.js +457 -0
  91. package/dist/collection/components/rule-editor/rule-operations.js +132 -0
  92. package/dist/collection/components/rule-editor/view-helpers.js +70 -0
  93. package/dist/collection/components/rule-gate/rule-gate.js +9 -4
  94. package/dist/collection/components/summary-popover/summary-popover.js +2 -2
  95. package/dist/collection/components/text-editor/mention-group-counter.js +2 -2
  96. package/dist/collection/components/text-editor/text-editor.js +1 -1
  97. package/dist/collection/components/trend-indicator/trend-indicator.js +1 -1
  98. package/dist/components/chat-icon-list.js +1 -1
  99. package/dist/components/chat-item.js +1 -1
  100. package/dist/components/currency-picker.js +1 -1
  101. package/dist/components/date-picker.js +1 -1
  102. package/dist/components/document-item.js +1 -1
  103. package/dist/components/feed-item-thumbnail-file-info.js +1 -1
  104. package/dist/components/feed-timeline-item.js +1 -1
  105. package/dist/components/kanban-group.js +1 -1
  106. package/dist/components/kanban-item.js +1 -1
  107. package/dist/components/lime-query-filter-comparison.js +1 -1
  108. package/dist/components/lime-query-filter-expression.js +1 -1
  109. package/dist/components/limebb-alert-dialog.js +1 -1
  110. package/dist/components/limebb-browser.js +1 -1
  111. package/dist/components/limebb-chat-list.js +1 -1
  112. package/dist/components/limebb-color-palette-picker.js +1 -1
  113. package/dist/components/limebb-color-palette-swatches.js +1 -1
  114. package/dist/components/limebb-component-config.js +1 -1
  115. package/dist/components/limebb-composer-toolbar.js +1 -1
  116. package/dist/components/limebb-dashboard-widget.js +1 -1
  117. package/dist/components/limebb-date-range.js +1 -1
  118. package/dist/components/limebb-document-chips.js +1 -1
  119. package/dist/components/limebb-document-picker.js +1 -1
  120. package/dist/components/limebb-feed.js +1 -1
  121. package/dist/components/limebb-icon-picker.js +1 -1
  122. package/dist/components/limebb-info-tile-format.js +1 -1
  123. package/dist/components/limebb-info-tile.js +1 -1
  124. package/dist/components/limebb-lime-query-builder.js +1 -1
  125. package/dist/components/limebb-lime-query-response-format-builder.js +1 -1
  126. package/dist/components/limebb-locale-picker.js +1 -1
  127. package/dist/components/limebb-mention-group-counter.js +1 -1
  128. package/dist/components/limebb-rule-chip-popover.d.ts +11 -0
  129. package/dist/components/limebb-rule-chip-popover.js +1 -0
  130. package/dist/components/limebb-rule-editor.d.ts +11 -0
  131. package/dist/components/limebb-rule-editor.js +1 -0
  132. package/dist/components/limebb-rule-gate.js +1 -1
  133. package/dist/components/limebb-text-editor.js +1 -1
  134. package/dist/components/limebb-trend-indicator.js +1 -1
  135. package/dist/components/limetype-field.js +1 -1
  136. package/dist/components/live-docs-info.js +1 -1
  137. package/dist/components/notification-item.js +1 -1
  138. package/dist/components/order-by-editor.js +1 -1
  139. package/dist/components/order-by-item.js +1 -1
  140. package/dist/components/percentage-visualizer.js +1 -1
  141. package/dist/components/response-format-item.js +1 -1
  142. package/dist/components/rule-chip-popover.js +1 -0
  143. package/dist/components/summary-popover.js +1 -1
  144. package/dist/components/typing-indicator.js +1 -1
  145. package/dist/components/web-component-template.js +1 -0
  146. package/dist/esm/lime-crm-building-blocks.js +1 -1
  147. package/dist/esm/limebb-alert-dialog.entry.js +1 -1
  148. package/dist/esm/limebb-browser.entry.js +2 -2
  149. package/dist/esm/limebb-chat-icon-list_3.entry.js +4 -4
  150. package/dist/esm/limebb-chat-list.entry.js +1 -1
  151. package/dist/esm/limebb-color-palette-picker.entry.js +1 -1
  152. package/dist/esm/limebb-color-palette-swatches.entry.js +1 -1
  153. package/dist/esm/limebb-component-config.entry.js +2 -14
  154. package/dist/esm/limebb-composer-toolbar.entry.js +3 -3
  155. package/dist/esm/limebb-currency-picker.entry.js +1 -1
  156. package/dist/esm/limebb-dashboard-widget.entry.js +1 -1
  157. package/dist/esm/limebb-date-picker.entry.js +1 -1
  158. package/dist/esm/limebb-date-range.entry.js +1 -1
  159. package/dist/esm/limebb-document-chips.entry.js +1 -1
  160. package/dist/esm/limebb-document-item.entry.js +2 -2
  161. package/dist/esm/limebb-document-picker.entry.js +1 -1
  162. package/dist/esm/limebb-feed-item-thumbnail-file-info.entry.js +1 -1
  163. package/dist/esm/limebb-feed-timeline-item.entry.js +1 -1
  164. package/dist/esm/limebb-feed.entry.js +1 -1
  165. package/dist/esm/limebb-icon-picker.entry.js +1 -1
  166. package/dist/esm/limebb-info-tile-format.entry.js +1 -1
  167. package/dist/esm/limebb-info-tile.entry.js +1 -1
  168. package/dist/esm/limebb-kanban-group.entry.js +1 -1
  169. package/dist/esm/limebb-kanban-item.entry.js +1 -1
  170. package/dist/esm/limebb-lime-query-builder.entry.js +1 -1
  171. package/dist/esm/limebb-lime-query-filter-builder_3.entry.js +2 -2
  172. package/dist/esm/limebb-lime-query-filter-comparison_2.entry.js +1 -1
  173. package/dist/esm/limebb-lime-query-filter-group_3.entry.js +3 -3
  174. package/dist/esm/limebb-lime-query-order-by-item.entry.js +2 -2
  175. package/dist/esm/limebb-lime-query-response-format-builder.entry.js +1 -1
  176. package/dist/esm/limebb-lime-query-response-format-editor_2.entry.js +1 -1
  177. package/dist/esm/limebb-live-docs-info.entry.js +2 -2
  178. package/dist/esm/limebb-locale-picker.entry.js +1 -1
  179. package/dist/esm/limebb-mention-group-counter.entry.js +2 -2
  180. package/dist/esm/limebb-navigation-button_2.entry.js +2 -2
  181. package/dist/esm/limebb-notification-item.entry.js +1 -1
  182. package/dist/esm/limebb-percentage-visualizer.entry.js +2 -2
  183. package/dist/esm/limebb-rule-chip-popover.entry.js +57 -0
  184. package/dist/esm/limebb-rule-editor.entry.js +644 -0
  185. package/dist/esm/limebb-rule-gate.entry.js +5 -1
  186. package/dist/esm/limebb-text-editor.entry.js +1 -1
  187. package/dist/esm/limebb-trend-indicator.entry.js +1 -1
  188. package/dist/esm/loader.js +1 -1
  189. package/dist/esm/web-component-template-6zRYia86.js +16 -0
  190. package/dist/lime-crm-building-blocks/lime-crm-building-blocks.esm.js +1 -1
  191. package/dist/lime-crm-building-blocks/{p-f3c412b3.entry.js → p-057e1638.entry.js} +1 -1
  192. package/dist/lime-crm-building-blocks/{p-b35ebf4d.entry.js → p-0c572fe9.entry.js} +1 -1
  193. package/dist/lime-crm-building-blocks/{p-8b11a02c.entry.js → p-11494f30.entry.js} +1 -1
  194. package/dist/lime-crm-building-blocks/{p-fc1aec12.entry.js → p-1747221f.entry.js} +1 -1
  195. package/dist/lime-crm-building-blocks/p-1831e571.entry.js +1 -0
  196. package/dist/lime-crm-building-blocks/{p-a4584260.entry.js → p-184ae23d.entry.js} +1 -1
  197. package/dist/lime-crm-building-blocks/{p-0be33708.entry.js → p-20206710.entry.js} +1 -1
  198. package/dist/lime-crm-building-blocks/{p-fa7597f7.entry.js → p-24fc049c.entry.js} +1 -1
  199. package/dist/lime-crm-building-blocks/{p-900b74c0.entry.js → p-277b6ad4.entry.js} +1 -1
  200. package/dist/lime-crm-building-blocks/{p-b74fe1ed.entry.js → p-2cb31064.entry.js} +1 -1
  201. package/dist/lime-crm-building-blocks/{p-c93314a6.entry.js → p-3313e357.entry.js} +1 -1
  202. package/dist/lime-crm-building-blocks/{p-593340d9.entry.js → p-3781a766.entry.js} +1 -1
  203. package/dist/lime-crm-building-blocks/{p-a3d4f2e1.entry.js → p-43a7facd.entry.js} +1 -1
  204. package/dist/lime-crm-building-blocks/{p-152b4f92.entry.js → p-6cceabf1.entry.js} +1 -1
  205. package/dist/lime-crm-building-blocks/{p-c5f0582c.entry.js → p-6d3a9ed3.entry.js} +1 -1
  206. package/dist/lime-crm-building-blocks/{p-b5d84fff.entry.js → p-71a6f624.entry.js} +1 -1
  207. package/dist/lime-crm-building-blocks/{p-4c255e2f.entry.js → p-731820f0.entry.js} +1 -1
  208. package/dist/lime-crm-building-blocks/p-74455a30.entry.js +1 -0
  209. package/dist/lime-crm-building-blocks/p-7922726c.entry.js +1 -0
  210. package/dist/lime-crm-building-blocks/{p-f3ba4ed1.entry.js → p-7a125570.entry.js} +1 -1
  211. package/dist/lime-crm-building-blocks/{p-5c420ada.entry.js → p-7d51a34c.entry.js} +1 -1
  212. package/dist/lime-crm-building-blocks/{p-f04ca19d.entry.js → p-7fee7ef3.entry.js} +1 -1
  213. package/dist/lime-crm-building-blocks/{p-a27e9bbb.entry.js → p-8084e825.entry.js} +1 -1
  214. package/dist/lime-crm-building-blocks/{p-6a27184b.entry.js → p-861ac606.entry.js} +1 -1
  215. package/dist/lime-crm-building-blocks/{p-b4ae3ed3.entry.js → p-8d3fa274.entry.js} +1 -1
  216. package/dist/lime-crm-building-blocks/{p-70957bab.entry.js → p-9f7992b0.entry.js} +1 -1
  217. package/dist/lime-crm-building-blocks/p-C_tMNOSt.js +1 -0
  218. package/dist/lime-crm-building-blocks/{p-6941de0b.entry.js → p-abcb1e49.entry.js} +1 -1
  219. package/dist/lime-crm-building-blocks/{p-9041e7aa.entry.js → p-b1a8d1a0.entry.js} +1 -1
  220. package/dist/lime-crm-building-blocks/p-b8d9ff68.entry.js +1 -0
  221. package/dist/lime-crm-building-blocks/{p-8f70f909.entry.js → p-bec4231f.entry.js} +1 -1
  222. package/dist/lime-crm-building-blocks/{p-8e6446b5.entry.js → p-c139ab98.entry.js} +1 -1
  223. package/dist/lime-crm-building-blocks/{p-e84ff80f.entry.js → p-c4f41ec4.entry.js} +1 -1
  224. package/dist/lime-crm-building-blocks/{p-24004bf3.entry.js → p-c609b5ec.entry.js} +1 -1
  225. package/dist/lime-crm-building-blocks/{p-ebd152ab.entry.js → p-c6a913af.entry.js} +1 -1
  226. package/dist/lime-crm-building-blocks/{p-c60673a4.entry.js → p-dd38e0ba.entry.js} +1 -1
  227. package/dist/lime-crm-building-blocks/{p-53b19393.entry.js → p-de6f4670.entry.js} +1 -1
  228. package/dist/lime-crm-building-blocks/{p-fc6d9cea.entry.js → p-e6ed33ff.entry.js} +1 -1
  229. package/dist/lime-crm-building-blocks/p-e717bdff.entry.js +1 -0
  230. package/dist/lime-crm-building-blocks/{p-da248a53.entry.js → p-ef62c7d8.entry.js} +1 -1
  231. package/dist/lime-crm-building-blocks/{p-23188fe0.entry.js → p-f0a567f3.entry.js} +1 -1
  232. package/dist/lime-crm-building-blocks/{p-befd1d3c.entry.js → p-fd6dcfe3.entry.js} +1 -1
  233. package/dist/types/components/rule-editor/chip-picker-view.d.ts +27 -0
  234. package/dist/types/components/rule-editor/group-node-view.d.ts +11 -0
  235. package/dist/types/components/rule-editor/rule-chip-popover/rule-chip-popover.d.ts +31 -0
  236. package/dist/types/components/rule-editor/rule-editor-views.d.ts +51 -0
  237. package/dist/types/components/rule-editor/rule-editor.d.ts +118 -0
  238. package/dist/types/components/rule-editor/rule-operations.d.ts +62 -0
  239. package/dist/types/components/rule-editor/view-helpers.d.ts +40 -0
  240. package/dist/types/components/rule-gate/rule-gate.d.ts +5 -2
  241. package/dist/types/components.d.ts +300 -6
  242. package/package.json +4 -4
  243. package/dist/lime-crm-building-blocks/p-4a93a4df.entry.js +0 -1
  244. package/dist/lime-crm-building-blocks/p-6318fd46.entry.js +0 -1
  245. package/dist/lime-crm-building-blocks/p-e3a3c291.entry.js +0 -1
@@ -0,0 +1,644 @@
1
+ import { h, r as registerInstance, c as createEvent } from './index-BIwHMk6j.js';
2
+ import { n } from './index.esm-EC5zE5lw.js';
3
+
4
+ /**
5
+ * Remove the node at `path`.
6
+ *
7
+ * Removing the root yields an empty `all`-group so the tree always has
8
+ * something to render. Returns `rule` unchanged when `path` does not
9
+ * address a removable node.
10
+ * @param rule
11
+ * @param path
12
+ */
13
+ function deleteNode(rule, path) {
14
+ if (path.length === 0) {
15
+ return { type: 'all', rules: [] };
16
+ }
17
+ const parentPath = path.slice(0, -1);
18
+ const key = path.at(-1);
19
+ const parent = getNode(rule, parentPath);
20
+ if ((parent.type === 'all' || parent.type === 'any') &&
21
+ typeof key === 'number') {
22
+ const rules = [...parent.rules];
23
+ rules.splice(key, 1);
24
+ return replaceAt(rule, parentPath, Object.assign(Object.assign({}, parent), { rules }));
25
+ }
26
+ if (parent.type === 'not' && key === 'rule') {
27
+ return replaceAt(rule, parentPath, { type: 'all', rules: [] });
28
+ }
29
+ return rule;
30
+ }
31
+ /**
32
+ * Replace the `args` of a `ref` node. Returns `rule` unchanged when
33
+ * `path` does not resolve to a `ref`.
34
+ * @param rule
35
+ * @param path
36
+ * @param args
37
+ */
38
+ function updateArgs(rule, path, args) {
39
+ const node = getNode(rule, path);
40
+ if (node.type !== 'ref') {
41
+ return rule;
42
+ }
43
+ return replaceAt(rule, path, Object.assign(Object.assign({}, node), { args }));
44
+ }
45
+ /**
46
+ * Replace the node at `path` with `replacement`, returning a new rule
47
+ * tree. Used by callers that need to apply a non-atomic change as a
48
+ * single emit (e.g. updating a group's whole `rules` array at once).
49
+ * @param rule
50
+ * @param path
51
+ * @param replacement
52
+ */
53
+ function replaceNode(rule, path, replacement) {
54
+ return replaceAt(rule, path, replacement);
55
+ }
56
+ /**
57
+ * Wrap `group` in a `not` when `isNegated`, otherwise return it
58
+ * unchanged. Used when re-emitting a group whose negation flag should
59
+ * be preserved.
60
+ * @param group
61
+ * @param isNegated
62
+ */
63
+ function wrapNegated(group, isNegated) {
64
+ return isNegated ? { type: 'not', rule: group } : group;
65
+ }
66
+ /**
67
+ * Append `child` to a group's `rules`, returning a new group. The
68
+ * input is not mutated.
69
+ * @param group
70
+ * @param child
71
+ */
72
+ function appendChild(group, child) {
73
+ return Object.assign(Object.assign({}, group), { rules: [...group.rules, child] });
74
+ }
75
+ /**
76
+ * Structural equality on two paths.
77
+ * @param a
78
+ * @param b
79
+ */
80
+ function pathsEqual(a, b) {
81
+ if (a.length !== b.length) {
82
+ return false;
83
+ }
84
+ return a.every((value, index) => value === b[index]);
85
+ }
86
+ /**
87
+ * Filter validation issues to those whose `path` matches `path`.
88
+ * @param issues
89
+ * @param path
90
+ */
91
+ function issuesAt(issues, path) {
92
+ return issues.filter((issue) => pathsEqual(issue.path, path));
93
+ }
94
+ function getNode(rule, path) {
95
+ let node = rule;
96
+ for (const key of path) {
97
+ node = stepIntoNode(node, key);
98
+ }
99
+ return node;
100
+ }
101
+ function replaceAt(root, path, replacement) {
102
+ if (path.length === 0) {
103
+ return replacement;
104
+ }
105
+ const [head, ...tail] = path;
106
+ if (root.type === 'not' && head === 'rule') {
107
+ return Object.assign(Object.assign({}, root), { rule: replaceAt(root.rule, tail, replacement) });
108
+ }
109
+ if ((root.type === 'all' || root.type === 'any') && head === 'rules') {
110
+ if (tail.length === 0) {
111
+ return replacement;
112
+ }
113
+ const [index, ...rest] = tail;
114
+ if (typeof index !== 'number') {
115
+ return root;
116
+ }
117
+ const rules = [...root.rules];
118
+ rules[index] = replaceAt(rules[index], rest, replacement);
119
+ return Object.assign(Object.assign({}, root), { rules });
120
+ }
121
+ return root;
122
+ }
123
+ function stepIntoNode(node, key) {
124
+ if (node.type === 'not' && key === 'rule') {
125
+ return node.rule;
126
+ }
127
+ if ((node.type === 'all' || node.type === 'any') && key === 'rules') {
128
+ return node;
129
+ }
130
+ if ((node.type === 'all' || node.type === 'any') &&
131
+ typeof key === 'number') {
132
+ return node.rules[key];
133
+ }
134
+ return node;
135
+ }
136
+
137
+ const UNKNOWN_ICON = {
138
+ name: 'question',
139
+ color: 'rgb(var(--color-glaucous-light))',
140
+ };
141
+ /**
142
+ * Class map for a rule-node container. Adds the type modifier and an
143
+ * `invalid` flag when validation issues attach to this node.
144
+ * @param type
145
+ * @param issues
146
+ */
147
+ function nodeClasses(type, issues) {
148
+ return {
149
+ 'rule-node': true,
150
+ [`rule-node--${type}`]: true,
151
+ 'rule-node--invalid': issues.length > 0,
152
+ };
153
+ }
154
+ /**
155
+ * Build the searchable list shown by the primitive pickers. Cached on
156
+ * the render context so it isn't recomputed per node.
157
+ * @param metadataById
158
+ */
159
+ function createPrimitiveOptions(metadataById) {
160
+ return [...metadataById.values()]
161
+ .map((meta) => {
162
+ var _a, _b;
163
+ return ({
164
+ value: meta.id,
165
+ text: (_a = meta.title) !== null && _a !== void 0 ? _a : meta.id,
166
+ secondaryText: (_b = meta.description) !== null && _b !== void 0 ? _b : '',
167
+ icon: meta.icon,
168
+ });
169
+ })
170
+ .sort((a, b) => a.text.localeCompare(b.text));
171
+ }
172
+ /**
173
+ * Find the picker item for `id`, falling back to a placeholder marked
174
+ * with the unknown-primitive icon when the id isn't in the registry.
175
+ * @param allItems
176
+ * @param id
177
+ */
178
+ function resolveItem(allItems, id) {
179
+ var _a;
180
+ return ((_a = allItems.find((item) => item.value === id)) !== null && _a !== void 0 ? _a : {
181
+ value: id,
182
+ text: id,
183
+ icon: UNKNOWN_ICON,
184
+ });
185
+ }
186
+ /**
187
+ * Build a picker `searcher` bound to a fixed item list. Both the ref
188
+ * picker and the chip picker want exactly this — wrapping
189
+ * {@link searchItems} in a promise — and deserve to share it.
190
+ * @param items
191
+ */
192
+ function createSearcher(items) {
193
+ return (query) => Promise.resolve(searchItems(items, query));
194
+ }
195
+ function searchItems(allItems, query) {
196
+ if (!query) {
197
+ return allItems;
198
+ }
199
+ const parts = query.toLocaleLowerCase().split(/\s+/);
200
+ return allItems.filter((item) => parts.every((part) => {
201
+ var _a, _b;
202
+ return item.text.toLocaleLowerCase().includes(part) ||
203
+ ((_a = item.secondaryText) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase().includes(part)) ||
204
+ ((_b = item.value) === null || _b === void 0 ? void 0 : _b.toLocaleLowerCase().includes(part));
205
+ }));
206
+ }
207
+
208
+ const CHIP_TOKEN_PREFIX = '__chip__:';
209
+ function chipTokenFor(index) {
210
+ return `${CHIP_TOKEN_PREFIX}${index}`;
211
+ }
212
+ // The address of a chip inside a group is the group's path followed
213
+ // by a two-segment suffix `['rules', index]`. Build and parse via
214
+ // these helpers so both sides stay in sync.
215
+ const CHIP_PATH_SUFFIX_LENGTH = 2;
216
+ function buildChipPath(groupPath, index) {
217
+ return [...groupPath, 'rules', index];
218
+ }
219
+ function parentGroupPath(chipPath) {
220
+ return chipPath.slice(0, -CHIP_PATH_SUFFIX_LENGTH);
221
+ }
222
+ /**
223
+ * If `node` is a `ref` or a `not(ref)`, return the underlying ref
224
+ * together with its negation flag. Used to decide whether a child of a
225
+ * group renders as a chip (this returns non-null) or as a nested box
226
+ * (this returns null).
227
+ * @param node
228
+ */
229
+ function extractRef(node) {
230
+ if (node.type === 'ref') {
231
+ return { ref: node, isNegated: false };
232
+ }
233
+ if (node.type === 'not' && node.rule.type === 'ref') {
234
+ return { ref: node.rule, isNegated: true };
235
+ }
236
+ return null;
237
+ }
238
+ const GroupChipsView = ({ groupNode, groupPath, chipChildren, ctx }) => {
239
+ const chipsByToken = new Map();
240
+ const value = chipChildren.map((entry) => {
241
+ const token = chipTokenFor(entry.index);
242
+ chipsByToken.set(token, entry);
243
+ const base = resolveItem(ctx.primitiveOptions, entry.ref.id);
244
+ return Object.assign(Object.assign({}, base), { text: entry.isNegated ? `¬ ${base.text}` : base.text, value: token });
245
+ });
246
+ const searcher = createSearcher(ctx.primitiveOptions);
247
+ const openChip = findOpenChip(chipChildren, groupPath, ctx.openChipPath);
248
+ const delimiter = groupNode.type === 'all' ? '&' : '|';
249
+ return (h("limel-popover", { class: "rule-node__chips-popover", open: openChip !== null, openDirection: "bottom-start", onClose: ctx.onPopoverClose }, h("div", { slot: "trigger", class: "rule-node__chips" }, h("limel-picker", { multiple: true, label: ctx.translator.get('webclient.rule-editor.rules-label'), value: value, searcher: searcher, delimiter: delimiter, readonly: ctx.readonly, disabled: ctx.disabled, onChange: chipsChangeHandler(groupNode, groupPath, chipsByToken, ctx), onInteract: chipInteractHandler(groupPath, chipsByToken, ctx) })), h("div", null, renderChipPopoverContent(openChip, groupPath, ctx))));
250
+ };
251
+ function renderChipPopoverContent(openChip, groupPath, ctx) {
252
+ if (!openChip) {
253
+ return null;
254
+ }
255
+ const openChipPath = buildChipPath(groupPath, openChip.index);
256
+ return (h("limebb-rule-chip-popover", { platform: ctx.platform, context: ctx.context, refNode: openChip.ref, isNegated: openChip.isNegated, metadata: ctx.metadataById.get(openChip.ref.id), readonly: ctx.readonly, disabled: ctx.disabled, isMutable: ctx.isMutable, onNegate: chipNegateHandler(openChip, openChipPath, ctx), onUpdateArgs: chipArgsHandler(openChip, openChipPath, ctx), onDeleteChip: chipDeleteHandler(openChipPath, ctx) }));
257
+ }
258
+ const chipsChangeHandler = (groupNode, groupPath, chipsByToken, ctx) => (event) => {
259
+ event.stopPropagation();
260
+ const items = Array.isArray(event.detail) ? event.detail : [];
261
+ const openIndex = openChipIndexInGroup(groupPath, ctx.openChipPath);
262
+ if (openIndex !== null) {
263
+ const openToken = chipTokenFor(openIndex);
264
+ if (items.every((item) => item.value !== openToken)) {
265
+ ctx.onPopoverClose();
266
+ }
267
+ }
268
+ const newChipNodes = items.flatMap((item) => {
269
+ if (typeof item.value !== 'string') {
270
+ return [];
271
+ }
272
+ const existing = chipsByToken.get(item.value);
273
+ if (existing) {
274
+ return [
275
+ existing.isNegated
276
+ ? { type: 'not', rule: existing.ref }
277
+ : existing.ref,
278
+ ];
279
+ }
280
+ return [{ type: 'ref', id: item.value }];
281
+ });
282
+ const nestedGroupRules = groupNode.rules.filter((rule) => extractRef(rule) === null);
283
+ ctx.onReplaceNode(groupPath, Object.assign(Object.assign({}, groupNode), { rules: [...newChipNodes, ...nestedGroupRules] }));
284
+ };
285
+ const chipInteractHandler = (groupPath, chipsByToken, ctx) => (event) => {
286
+ event.stopPropagation();
287
+ const token = interactedToken(event.detail);
288
+ const chip = token ? chipsByToken.get(token) : undefined;
289
+ if (!chip) {
290
+ return;
291
+ }
292
+ ctx.onChipInteract([...groupPath, 'rules', chip.index]);
293
+ };
294
+ const chipNegateHandler = (openChip, openChipPath, ctx) => (event) => {
295
+ event.stopPropagation();
296
+ const next = event.detail
297
+ ? { type: 'not', rule: openChip.ref }
298
+ : openChip.ref;
299
+ ctx.onReplaceNode(openChipPath, next);
300
+ };
301
+ const chipArgsHandler = (openChip, openChipPath, ctx) => (event) => {
302
+ event.stopPropagation();
303
+ const argsPath = openChip.isNegated
304
+ ? [...openChipPath, 'rule']
305
+ : openChipPath;
306
+ ctx.onUpdateArgs(argsPath, event.detail);
307
+ };
308
+ const chipDeleteHandler = (openChipPath, ctx) => () => {
309
+ ctx.onDelete(openChipPath);
310
+ };
311
+ /**
312
+ * `limel-picker` declares its `interact` event as
313
+ * `EventEmitter<ListItem<PickerValue>>` but the runtime actually emits
314
+ * the chip's value (a string) — see picker.tsx's handleInteract. This
315
+ * unwraps either shape into the string token.
316
+ * @param detail
317
+ */
318
+ function interactedToken(detail) {
319
+ if (typeof detail === 'string') {
320
+ return detail;
321
+ }
322
+ if (detail && typeof detail === 'object' && 'value' in detail) {
323
+ const value = detail.value;
324
+ return typeof value === 'string' ? value : undefined;
325
+ }
326
+ return undefined;
327
+ }
328
+ function findOpenChip(chipChildren, groupPath, openChipPath) {
329
+ var _a;
330
+ const index = openChipIndexInGroup(groupPath, openChipPath);
331
+ if (index === null) {
332
+ return null;
333
+ }
334
+ return (_a = chipChildren.find((entry) => entry.index === index)) !== null && _a !== void 0 ? _a : null;
335
+ }
336
+ function openChipIndexInGroup(groupPath, openChipPath) {
337
+ if (!openChipPath || openChipPath.length < CHIP_PATH_SUFFIX_LENGTH) {
338
+ return null;
339
+ }
340
+ if (!pathsEqual(parentGroupPath(openChipPath), groupPath)) {
341
+ return null;
342
+ }
343
+ const lastKey = openChipPath.at(-1);
344
+ return typeof lastKey === 'number' ? lastKey : null;
345
+ }
346
+
347
+ const GroupNodeView = ({ node, path, isNegated, ctx }) => {
348
+ const groupBasePath = isNegated ? [...path, 'rule'] : path;
349
+ const issuesHere = isNegated
350
+ ? [
351
+ ...issuesAt(ctx.issues, path),
352
+ ...issuesAt(ctx.issues, groupBasePath),
353
+ ]
354
+ : issuesAt(ctx.issues, path);
355
+ const chipChildren = [];
356
+ const nestedGroups = [];
357
+ for (const [index, child] of node.rules.entries()) {
358
+ const extracted = extractRef(child);
359
+ if (extracted) {
360
+ chipChildren.push(Object.assign(Object.assign({}, extracted), { index }));
361
+ }
362
+ else {
363
+ nestedGroups.push({ child, index });
364
+ }
365
+ }
366
+ const options = combinatorOptions(ctx);
367
+ const selectedCombinator = options.find((option) => option.value === node.type);
368
+ return (h("div", { class: nodeClasses(node.type, issuesHere), key: pathKey(path) }, h("div", { class: "rule-node__header" }, h("limel-select", { class: "rule-node__combinator-select", value: selectedCombinator, options: options, disabled: !ctx.isMutable, onChange: combinatorChangeHandler(node, path, isNegated, ctx) }), renderMutableGroupActions(node, path, isNegated, ctx)), h("div", { class: "rule-node__body" }, h(IssuesView, { issues: issuesHere }), h(GroupChipsView, { groupNode: node, groupPath: groupBasePath, chipChildren: chipChildren, ctx: ctx }), renderNestedGroups(nestedGroups, groupBasePath, ctx), renderAddGroupFooter(node, path, isNegated, ctx))));
369
+ };
370
+ function pathKey(path) {
371
+ return path.length === 0 ? 'root' : path.join('/');
372
+ }
373
+ function combinatorOptions(ctx) {
374
+ return [
375
+ {
376
+ value: 'all',
377
+ text: ctx.translator.get('webclient.rule-editor.combinator.all'),
378
+ },
379
+ {
380
+ value: 'any',
381
+ text: ctx.translator.get('webclient.rule-editor.combinator.any'),
382
+ },
383
+ ];
384
+ }
385
+ function renderMutableGroupActions(node, path, isNegated, ctx) {
386
+ if (!ctx.isMutable) {
387
+ return null;
388
+ }
389
+ return (h("div", { class: "rule-node__header-actions" }, h("limel-switch", { class: "rule-node__negate-switch", label: ctx.translator.get('webclient.rule-editor.negate'), value: isNegated, onChange: negateGroupHandler(node, path, ctx) }), h("limel-icon-button", { icon: "trash", label: ctx.translator.get('webclient.rule-editor.delete'), onClick: () => ctx.onDelete(path) })));
390
+ }
391
+ function renderNestedGroups(nestedGroups, groupBasePath, ctx) {
392
+ if (nestedGroups.length === 0) {
393
+ return null;
394
+ }
395
+ return (h("div", { class: "rule-node__children" }, nestedGroups.map((entry) => (h(RuleNodeView, { node: entry.child, path: [...groupBasePath, 'rules', entry.index], ctx: ctx })))));
396
+ }
397
+ function renderAddGroupFooter(node, path, isNegated, ctx) {
398
+ if (!ctx.isMutable) {
399
+ return null;
400
+ }
401
+ return (h("div", { class: "rule-node__footer" }, h("limel-button", { icon: "add", label: ctx.translator.get('webclient.rule-editor.add-nested-group'), onClick: addGroupHandler(node, path, isNegated, ctx) })));
402
+ }
403
+ function replaceGroup(nextGroup, path, isNegated, ctx) {
404
+ ctx.onReplaceNode(path, wrapNegated(nextGroup, isNegated));
405
+ }
406
+ const combinatorChangeHandler = (node, path, isNegated, ctx) => (event) => {
407
+ event.stopPropagation();
408
+ const newType = event.detail.value;
409
+ if (newType !== node.type) {
410
+ replaceGroup(Object.assign(Object.assign({}, node), { type: newType }), path, isNegated, ctx);
411
+ }
412
+ };
413
+ const addGroupHandler = (node, path, isNegated, ctx) => () => {
414
+ const expanded = appendChild(node, { type: 'all', rules: [] });
415
+ replaceGroup(expanded, path, isNegated, ctx);
416
+ };
417
+ const negateGroupHandler = (node, path, ctx) => (event) => {
418
+ event.stopPropagation();
419
+ ctx.onReplaceNode(path, wrapNegated(node, event.detail));
420
+ };
421
+
422
+ /**
423
+ * Render a `Rule` node and recurse into its children.
424
+ * @param props
425
+ */
426
+ const RuleNodeView = (props) => {
427
+ const { node, path, ctx } = props;
428
+ const group = extractGroup(node);
429
+ if (!group) {
430
+ return null;
431
+ }
432
+ return (h(GroupNodeView, { node: group.node, path: path, isNegated: group.isNegated, ctx: ctx }));
433
+ };
434
+ const isNegatedGroup = (node) => node.type === 'not' &&
435
+ (node.rule.type === 'all' || node.rule.type === 'any');
436
+ /**
437
+ * If `node` is a group (`all`/`any`) or a negated group, return the
438
+ * inner group together with its negation flag. Otherwise `null`.
439
+ * Used by the dispatcher and by the editor's input normalization.
440
+ * @param node
441
+ */
442
+ function extractGroup(node) {
443
+ if (node.type === 'all' || node.type === 'any') {
444
+ return { node, isNegated: false };
445
+ }
446
+ if (isNegatedGroup(node)) {
447
+ return { node: node.rule, isNegated: true };
448
+ }
449
+ if (node.type === 'not') {
450
+ const inner = extractGroup(node.rule);
451
+ if (inner) {
452
+ return { node: inner.node, isNegated: !inner.isNegated };
453
+ }
454
+ }
455
+ return null;
456
+ }
457
+ const IssuesView = ({ issues }) => {
458
+ if (issues.length === 0) {
459
+ return null;
460
+ }
461
+ return issues.map((issue) => (h("div", { class: "rule-node__issue" }, issue.message)));
462
+ };
463
+
464
+ const ruleEditorCss = () => `:host{display:block}.rule-editor--disabled{opacity:0.6;pointer-events:none}.rule-editor__label{font-size:0.75rem;font-weight:600;color:rgb(var(--contrast-1500));margin-bottom:0.25rem}.rule-editor__helper-text{font-size:0.75rem;color:rgb(var(--contrast-1300));margin-top:0.25rem}.rule-node{border:1px solid rgb(var(--contrast-500));border-radius:0.5rem;margin:0.25rem 0;overflow:hidden;background-color:rgb(var(--contrast-100))}.rule-node--invalid{border-color:rgb(var(--color-red-default))}.rule-node--all>.rule-node__header,.rule-node--any>.rule-node__header{background-color:rgb(var(--contrast-300));padding:0.375rem 0.75rem;border-bottom:1px solid rgb(var(--contrast-500))}.rule-node__header{display:flex;align-items:center;gap:0.5rem}.rule-node__header-actions{margin-left:auto;display:grid;grid-auto-flow:column;grid-gap:0.5rem;padding:0.125rem;align-items:center}.rule-node__combinator-select{min-width:6rem}.rule-node__body{padding:0.75rem;display:flex;flex-direction:column;gap:0.75rem}limel-popover.rule-node__chips-popover{display:contents}.rule-node__chips{display:block;width:100%}.rule-node__chips limel-picker{display:block;width:100%}.rule-node__children{display:flex;flex-direction:column;gap:0.5rem}.rule-node__footer{display:flex;justify-content:center}.rule-node__issue{color:rgb(var(--color-red-default));font-size:0.875rem}`;
465
+
466
+ const RuleEditor = class {
467
+ constructor(hostRef) {
468
+ registerInstance(this, hostRef);
469
+ this.change = createEvent(this, "change");
470
+ this.issues = [];
471
+ this.openChipPath = null;
472
+ this.metadataById = new Map();
473
+ this.primitiveOptions = [];
474
+ this.normalizedCache = null;
475
+ this.handleDelete = (path) => {
476
+ this.openChipPath = null;
477
+ this.emitIfChanged(deleteNode(this.normalizedValue, path));
478
+ };
479
+ this.handleUpdateArgs = (path, args) => {
480
+ this.emitIfChanged(updateArgs(this.normalizedValue, path, args));
481
+ };
482
+ this.handleReplaceNode = (path, replacement) => {
483
+ this.emitIfChanged(replaceNode(this.normalizedValue, path, replacement));
484
+ };
485
+ this.handleChipInteract = (path) => {
486
+ this.openChipPath = path;
487
+ };
488
+ this.handlePopoverClose = () => {
489
+ this.openChipPath = null;
490
+ };
491
+ }
492
+ componentWillLoad() {
493
+ this.indexMetadata();
494
+ this.runValidation();
495
+ }
496
+ componentDidLoad() {
497
+ this.emitNormalization();
498
+ }
499
+ onValueChange() {
500
+ if (this.emitNormalization()) {
501
+ return;
502
+ }
503
+ this.runValidation();
504
+ }
505
+ onAvailableSubjectsChange() {
506
+ this.runValidation();
507
+ }
508
+ render() {
509
+ const containerClasses = {
510
+ 'rule-editor': true,
511
+ 'rule-editor--disabled': this.disabled,
512
+ };
513
+ return (h("div", { key: 'd179f399433b3c80aa09e52baa19713eef7c1921', class: containerClasses }, this.renderLabel(), h(RuleNodeView, { key: '14cac42e37f52f0a32390a1f374f014b60e31dde', node: this.normalizedValue, path: [], ctx: this.createRenderContext() }), this.renderHelperText()));
514
+ }
515
+ renderLabel() {
516
+ if (!this.label) {
517
+ return null;
518
+ }
519
+ return h("div", { class: "rule-editor__label" }, this.label);
520
+ }
521
+ renderHelperText() {
522
+ if (!this.helperText) {
523
+ return null;
524
+ }
525
+ return h("div", { class: "rule-editor__helper-text" }, this.helperText);
526
+ }
527
+ createRenderContext() {
528
+ return {
529
+ issues: this.issues,
530
+ metadataById: this.metadataById,
531
+ primitiveOptions: this.primitiveOptions,
532
+ isMutable: !this.readonly && !this.disabled,
533
+ readonly: this.readonly,
534
+ disabled: this.disabled,
535
+ platform: this.platform,
536
+ context: this.context,
537
+ translator: this.platform.get(n.Translate),
538
+ openChipPath: this.openChipPath,
539
+ onDelete: this.handleDelete,
540
+ onUpdateArgs: this.handleUpdateArgs,
541
+ onReplaceNode: this.handleReplaceNode,
542
+ onChipInteract: this.handleChipInteract,
543
+ onPopoverClose: this.handlePopoverClose,
544
+ };
545
+ }
546
+ indexMetadata() {
547
+ var _a, _b, _c;
548
+ const metadata = (_c = (_b = (_a = this.ruleRegistry).listMetadata) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : [];
549
+ this.metadataById = new Map(metadata.map((item) => [item.id, item]));
550
+ this.primitiveOptions = createPrimitiveOptions(this.metadataById);
551
+ }
552
+ runValidation() {
553
+ if (!this.value) {
554
+ this.issues = [];
555
+ return;
556
+ }
557
+ const result = this.ruleRegistry.validate(this.normalizedValue, this.availableSubjects);
558
+ this.issues = result.ok ? [] : result.issues;
559
+ }
560
+ emitIfChanged(next) {
561
+ if (next === this.normalizedValue) {
562
+ return;
563
+ }
564
+ this.change.emit(collapseEmptyRoot(next));
565
+ }
566
+ /**
567
+ * Wrap any non-group `value` in a top-level `all` so the editor
568
+ * always has a group to render against. When `value` is unset,
569
+ * returns a fresh empty `all`-group as a render-only placeholder —
570
+ * `emitNormalization` will *not* push that placeholder back to the
571
+ * caller, so an unset value stays unset until the user edits.
572
+ *
573
+ * Memoized so callers that read this several times in one handler
574
+ * see the same reference — the identity check in `emitIfChanged`
575
+ * depends on it.
576
+ */
577
+ get normalizedValue() {
578
+ if (this.normalizedCache !== null &&
579
+ this.normalizedCache.source === this.value) {
580
+ return this.normalizedCache.normalized;
581
+ }
582
+ const normalized = normalize(this.value);
583
+ this.normalizedCache = { source: this.value, normalized };
584
+ return normalized;
585
+ }
586
+ /**
587
+ * If `value` wasn't already a group, emit the normalized form so
588
+ * the caller's stored state catches up. Skipped when `value` is
589
+ * unset — we render a placeholder group locally but don't push it
590
+ * back to the caller, so callers can't tell "no rule yet" apart
591
+ * from "user cleared a rule" by inspecting the emitted shape.
592
+ * Returns `true` when an emit happened so callers can short-circuit.
593
+ */
594
+ emitNormalization() {
595
+ if (!this.value) {
596
+ return false;
597
+ }
598
+ const normalized = this.normalizedValue;
599
+ if (normalized === this.value) {
600
+ return false;
601
+ }
602
+ this.change.emit(normalized);
603
+ return true;
604
+ }
605
+ get ruleRegistry() {
606
+ return this.platform.get(n.RuleRegistry);
607
+ }
608
+ static get watchers() { return {
609
+ "value": [{
610
+ "onValueChange": 0
611
+ }],
612
+ "availableSubjects": [{
613
+ "onAvailableSubjectsChange": 0
614
+ }]
615
+ }; }
616
+ };
617
+ function normalize(value) {
618
+ if (!value) {
619
+ return { type: 'all', rules: [] };
620
+ }
621
+ if (extractGroup(value)) {
622
+ return value;
623
+ }
624
+ return { type: 'all', rules: [value] };
625
+ }
626
+ /**
627
+ * Treat an empty root `all`/`any` as "no rule". Mapping that back to
628
+ * `undefined` on emit keeps the form contract a clean
629
+ * `Rule | undefined` — callers don't have to inspect rule shape to
630
+ * tell "user cleared this" from "user has a real rule". A negated
631
+ * empty group (`not(all())` etc.) is left intact — vacuous either
632
+ * direction, but the user explicitly opted into the wrapper, so we
633
+ * don't second-guess.
634
+ * @param rule
635
+ */
636
+ function collapseEmptyRoot(rule) {
637
+ if (rule.type !== 'all' && rule.type !== 'any') {
638
+ return rule;
639
+ }
640
+ return rule.rules.length === 0 ? undefined : rule;
641
+ }
642
+ RuleEditor.style = ruleEditorCss();
643
+
644
+ export { RuleEditor as limebb_rule_editor };
@@ -18,13 +18,17 @@ const RuleGate = class {
18
18
  this.compileAndEvaluate();
19
19
  }
20
20
  render() {
21
- return (h(Host, { key: '987da88562f3cfe1c5b0599d3aa73795bcbd317d', hidden: !this.shouldRender }, h("slot", { key: '3af4b067ebb51007c525719614cce800c018aeb6' })));
21
+ return (h(Host, { key: 'b3663501f4878923c36018812e60bfad702c1173', hidden: !this.shouldRender }, h("slot", { key: '1d3193332f682bd6ccb0f0ecc065b8c757f504eb' })));
22
22
  }
23
23
  get ruleRegistry() {
24
24
  return this.platform.get(n.RuleRegistry);
25
25
  }
26
26
  compileAndEvaluate() {
27
27
  var _a;
28
+ if (!this.rule) {
29
+ this.shouldRender = true;
30
+ return;
31
+ }
28
32
  const compiled = this.ruleRegistry.compile(this.rule);
29
33
  const scope = (_a = this.scope) !== null && _a !== void 0 ? _a : this.ruleRegistry.scope({ host: this.host });
30
34
  this.shouldRender = compiled(scope);
@@ -1515,7 +1515,7 @@ const LimeBBTextEditor = class {
1515
1515
  }
1516
1516
  render() {
1517
1517
  return [
1518
- h("limel-text-editor", { key: 'a208dcc0631ee1a9ab0bc488b461d25f4881c95d', ref: (el) => (this.textEditor = el), tabindex: this.disabled ? -1 : 0, value: this.value, contentType: this.contentType, customElements: this.registeredCustomElements, "aria-disabled": this.disabled, language: this.language, triggers: this.registeredTriggers, onTriggerStart: this.handleTriggerStart, onTriggerStop: this.handleTriggerStop, onTriggerChange: this.handleTriggerChange, onImagePasted: this.handleImagePasted, onMetadataChange: this.handleMetadataChange, ui: this.ui, allowResize: this.allowResize, required: this.required, disabled: this.disabled, readonly: this.readonly, helperText: this.helperText, placeholder: this.placeholder, label: this.label, invalid: this.invalid }),
1518
+ h("limel-text-editor", { key: '38d692ec58c569a0429caddf7ecfe418e21ac14b', ref: (el) => (this.textEditor = el), tabindex: this.disabled ? -1 : 0, value: this.value, contentType: this.contentType, customElements: this.registeredCustomElements, "aria-disabled": this.disabled, language: this.language, triggers: this.registeredTriggers, onTriggerStart: this.handleTriggerStart, onTriggerStop: this.handleTriggerStop, onTriggerChange: this.handleTriggerChange, onImagePasted: this.handleImagePasted, onMetadataChange: this.handleMetadataChange, ui: this.ui, allowResize: this.allowResize, required: this.required, disabled: this.disabled, readonly: this.readonly, helperText: this.helperText, placeholder: this.placeholder, label: this.label, invalid: this.invalid }),
1519
1519
  this.renderPicker(),
1520
1520
  ];
1521
1521
  }
@@ -49,7 +49,7 @@ const TrendIndicator = class {
49
49
  this.numValue = this.parseValue(this.value);
50
50
  }
51
51
  render() {
52
- return (h(Host, { key: '53ac9e7b58e9639b66de3aaa95f2c87066242bf2', class: this.getContainerClassList() }, h("limel-notched-outline", { key: '09cbfb01f55b1ce7bd997f6dfaa66c10d9889eea', id: this.tooltipId, label: this.label, labelId: this.labelId, invalid: this.invalid, required: this.required, hasValue: true, hasFloatingLabel: true, "aria-labelledby": this.labelId, "aria-describedby": this.helperTextId, "aria-controls": this.helperTextId }, h("div", { key: 'e3f9f0e361ac65f2b3f46a038c8dc398def9c0b9', slot: "content", tabIndex: 0 }, this.renderVisualization())), this.renderHelperLine(), this.renderTooltip()));
52
+ return (h(Host, { key: 'fd3bce29b7cd49a4642904fa630616b10e7d55b8', class: this.getContainerClassList() }, h("limel-notched-outline", { key: '3502f060569abb0e12c5b6bca84fdf9b190e840f', id: this.tooltipId, label: this.label, labelId: this.labelId, invalid: this.invalid, required: this.required, hasValue: true, hasFloatingLabel: true, "aria-labelledby": this.labelId, "aria-describedby": this.helperTextId, "aria-controls": this.helperTextId }, h("div", { key: '4f007fec33a71fe2205c1fbb861b45b8d41f440e', slot: "content", tabIndex: 0 }, this.renderVisualization())), this.renderHelperLine(), this.renderTooltip()));
53
53
  }
54
54
  renderVisualization() {
55
55
  if (this.reducePresence && (this.numValue === 0 || !this.hasValue())) {