@limetech/lime-crm-building-blocks 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/cjs/{condition-tree-translate-B_qIQz9s.js → condition-tree-translate-BQwKtiNZ.js} +1 -1
- package/dist/cjs/{filter-group-logic-Bt5tIbfP.js → filter-group-logic-CeGmYgsu.js} +1 -1
- package/dist/cjs/{filter-operators-CzIq9qKC.js → filter-operators-C3T2czC_.js} +1 -1
- package/dist/cjs/{index-mDIvByXc.js → index-Du4GyM0Y.js} +13 -8
- package/dist/cjs/index.cjs.js +3 -3
- package/dist/cjs/{index.esm-D1EzGa8X.js → index.esm-C2zw0QJK.js} +2 -2
- package/dist/cjs/lime-crm-building-blocks.cjs.js +3 -3
- package/dist/cjs/{lime-query-validation-Df4GZRGm.js → lime-query-validation-CzYkphmi.js} +1 -1
- package/dist/cjs/limebb-alert-dialog.cjs.entry.js +1 -1
- package/dist/cjs/limebb-browser.cjs.entry.js +2 -2
- package/dist/cjs/limebb-chat-icon-list_3.cjs.entry.js +2 -2
- package/dist/cjs/limebb-chat-list.cjs.entry.js +2 -2
- package/dist/cjs/limebb-color-palette-picker.cjs.entry.js +1 -1
- package/dist/cjs/limebb-color-palette-swatches.cjs.entry.js +1 -1
- package/dist/cjs/limebb-component-config.cjs.entry.js +3 -3
- package/dist/cjs/limebb-component-picker.cjs.entry.js +2 -2
- package/dist/cjs/limebb-composer-toolbar.cjs.entry.js +2 -2
- package/dist/cjs/limebb-condition-tree-editor.cjs.entry.js +24 -9
- package/dist/cjs/limebb-condition-tree.cjs.entry.js +121 -34
- package/dist/cjs/limebb-currency-picker.cjs.entry.js +2 -2
- package/dist/cjs/limebb-dashboard-widget.cjs.entry.js +1 -1
- package/dist/cjs/limebb-data-cells.cjs.entry.js +2 -2
- package/dist/cjs/limebb-date-picker.cjs.entry.js +2 -2
- package/dist/cjs/limebb-date-range.cjs.entry.js +1 -1
- package/dist/cjs/limebb-document-chips.cjs.entry.js +1 -1
- package/dist/cjs/limebb-document-item.cjs.entry.js +1 -1
- package/dist/cjs/limebb-document-picker.cjs.entry.js +1 -1
- package/dist/cjs/limebb-empty-state.cjs.entry.js +1 -1
- package/dist/cjs/limebb-feed-item-thumbnail-file-info.cjs.entry.js +1 -1
- package/dist/cjs/limebb-feed-timeline-item.cjs.entry.js +2 -2
- package/dist/cjs/limebb-feed.cjs.entry.js +2 -2
- package/dist/cjs/limebb-filter-chip_6.cjs.entry.js +4 -4
- package/dist/cjs/limebb-icon-picker.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-currency-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-date-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-decimal-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-relative-date-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile-unit-format.cjs.entry.js +1 -1
- package/dist/cjs/limebb-info-tile.cjs.entry.js +3 -3
- package/dist/cjs/limebb-inline-image.cjs.entry.js +2 -2
- package/dist/cjs/limebb-kanban-group.cjs.entry.js +2 -2
- package/dist/cjs/limebb-kanban-item.cjs.entry.js +2 -2
- package/dist/cjs/limebb-kanban.cjs.entry.js +1 -1
- package/dist/cjs/limebb-lime-query-builder.cjs.entry.js +3 -3
- package/dist/cjs/limebb-lime-query-filter-builder.cjs.entry.js +3 -3
- package/dist/cjs/limebb-lime-query-filter-comparison_2.cjs.entry.js +4 -4
- package/dist/cjs/limebb-lime-query-order-by-editor_2.cjs.entry.js +3 -3
- package/dist/cjs/limebb-lime-query-order-by-item.cjs.entry.js +1 -1
- package/dist/cjs/limebb-lime-query-response-format-builder.cjs.entry.js +3 -3
- package/dist/cjs/limebb-lime-query-response-format-editor_2.cjs.entry.js +1 -1
- package/dist/cjs/limebb-limeobject-file-viewer.cjs.entry.js +2 -2
- package/dist/cjs/limebb-live-docs-info.cjs.entry.js +1 -1
- package/dist/cjs/limebb-loader.cjs.entry.js +2 -2
- package/dist/cjs/limebb-locale-picker.cjs.entry.js +2 -2
- package/dist/cjs/limebb-mention-group-counter.cjs.entry.js +1 -1
- package/dist/cjs/limebb-mention.cjs.entry.js +2 -2
- package/dist/cjs/limebb-navigation-button_2.cjs.entry.js +1 -1
- package/dist/cjs/limebb-notification-item.cjs.entry.js +2 -2
- package/dist/cjs/limebb-notification-list.cjs.entry.js +2 -2
- package/dist/cjs/limebb-object-chip.cjs.entry.js +3 -3
- package/dist/cjs/limebb-percentage-visualizer.cjs.entry.js +2 -2
- package/dist/cjs/limebb-property-selector.cjs.entry.js +3 -3
- package/dist/cjs/limebb-rule-arg-filter-editor.cjs.entry.js +2 -2
- package/dist/cjs/limebb-rule-condition-chip.cjs.entry.js +71 -0
- package/dist/cjs/limebb-rule-condition-editor-CHWTMOmi.js +285 -0
- package/dist/cjs/limebb-rule-condition-editor.cjs.entry.js +9 -0
- package/dist/cjs/limebb-rule-editor.cjs.entry.js +217 -573
- package/dist/cjs/limebb-rule-gate.cjs.entry.js +2 -2
- package/dist/cjs/limebb-text-editor-picker.cjs.entry.js +1 -1
- package/dist/cjs/limebb-text-editor.cjs.entry.js +3 -3
- package/dist/cjs/limebb-trend-indicator.cjs.entry.js +2 -2
- package/dist/cjs/limebb-value-comparison-editor.cjs.entry.js +3 -3
- package/dist/cjs/{limetype-BPuuRLtH.js → limetype-BzVDjAKS.js} +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/{web-component-template-DRMW9wHN.js → web-component-template-C-AkY5as.js} +1 -1
- package/dist/collection/collection-manifest.json +3 -2
- package/dist/collection/components/condition-tree/condition-tree-editor/condition-tree-editor.js +46 -5
- package/dist/collection/components/condition-tree/condition-tree-nodes.js +13 -6
- package/dist/collection/components/condition-tree/condition-tree.js +69 -18
- package/dist/collection/components/condition-tree/group-node-view.js +41 -5
- package/dist/collection/components/condition-tree/leaf-node-view.js +19 -2
- package/dist/collection/components/rule-editor/condition-tree-adapter.js +229 -0
- package/dist/collection/components/rule-editor/rule-condition-chip/rule-condition-chip.css +4 -0
- package/dist/collection/components/rule-editor/rule-condition-chip/rule-condition-chip.js +322 -0
- package/dist/collection/components/rule-editor/rule-condition-editor/rule-condition-editor.css +5 -0
- package/dist/collection/components/rule-editor/rule-condition-editor/rule-condition-editor.js +259 -0
- package/dist/collection/components/rule-editor/rule-editor.css +1 -73
- package/dist/collection/components/rule-editor/rule-editor.js +143 -153
- package/dist/collection/components/rule-editor/rule-issues.js +89 -0
- package/dist/collection/components/rule-editor/view-helpers.js +19 -41
- package/dist/components/condition-tree-adapter.js +1 -0
- package/dist/components/condition-tree-editor.js +1 -1
- package/dist/components/condition-tree.js +1 -0
- package/dist/components/limebb-condition-tree.js +1 -1
- package/dist/components/limebb-rule-condition-chip.d.ts +11 -0
- package/dist/components/limebb-rule-condition-chip.js +1 -0
- package/dist/components/limebb-rule-condition-editor.d.ts +11 -0
- package/dist/components/limebb-rule-condition-editor.js +1 -0
- package/dist/components/limebb-rule-editor.js +1 -1
- package/dist/esm/{condition-tree-translate-CBeXbZ_z.js → condition-tree-translate-ZQptbaXF.js} +1 -1
- package/dist/esm/{filter-group-logic-CzThKf85.js → filter-group-logic-nqCMmV0e.js} +1 -1
- package/dist/esm/{filter-operators-u3T1PKhm.js → filter-operators-QbKK26m2.js} +1 -1
- package/dist/esm/{index-COtSgrC5.js → index-BK566_jX.js} +13 -8
- package/dist/esm/{index.esm-B9D_MXA6.js → index.esm-C__n3hug.js} +1 -1
- package/dist/esm/index.js +3 -3
- package/dist/esm/lime-crm-building-blocks.js +4 -4
- package/dist/esm/{lime-query-validation-dGoN_93p.js → lime-query-validation-BvB2v-yP.js} +1 -1
- package/dist/esm/limebb-alert-dialog.entry.js +1 -1
- package/dist/esm/limebb-browser.entry.js +2 -2
- package/dist/esm/limebb-chat-icon-list_3.entry.js +2 -2
- package/dist/esm/limebb-chat-list.entry.js +2 -2
- package/dist/esm/limebb-color-palette-picker.entry.js +1 -1
- package/dist/esm/limebb-color-palette-swatches.entry.js +1 -1
- package/dist/esm/limebb-component-config.entry.js +3 -3
- package/dist/esm/limebb-component-picker.entry.js +2 -2
- package/dist/esm/limebb-composer-toolbar.entry.js +2 -2
- package/dist/esm/limebb-condition-tree-editor.entry.js +24 -9
- package/dist/esm/limebb-condition-tree.entry.js +121 -34
- package/dist/esm/limebb-currency-picker.entry.js +2 -2
- package/dist/esm/limebb-dashboard-widget.entry.js +1 -1
- package/dist/esm/limebb-data-cells.entry.js +2 -2
- package/dist/esm/limebb-date-picker.entry.js +2 -2
- package/dist/esm/limebb-date-range.entry.js +1 -1
- package/dist/esm/limebb-document-chips.entry.js +1 -1
- package/dist/esm/limebb-document-item.entry.js +1 -1
- package/dist/esm/limebb-document-picker.entry.js +1 -1
- package/dist/esm/limebb-empty-state.entry.js +1 -1
- package/dist/esm/limebb-feed-item-thumbnail-file-info.entry.js +1 -1
- package/dist/esm/limebb-feed-timeline-item.entry.js +2 -2
- package/dist/esm/limebb-feed.entry.js +2 -2
- package/dist/esm/limebb-filter-chip_6.entry.js +4 -4
- package/dist/esm/limebb-icon-picker.entry.js +1 -1
- package/dist/esm/limebb-info-tile-currency-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile-date-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile-decimal-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile-relative-date-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile-unit-format.entry.js +1 -1
- package/dist/esm/limebb-info-tile.entry.js +3 -3
- package/dist/esm/limebb-inline-image.entry.js +2 -2
- package/dist/esm/limebb-kanban-group.entry.js +2 -2
- package/dist/esm/limebb-kanban-item.entry.js +2 -2
- package/dist/esm/limebb-kanban.entry.js +1 -1
- package/dist/esm/limebb-lime-query-builder.entry.js +3 -3
- package/dist/esm/limebb-lime-query-filter-builder.entry.js +3 -3
- package/dist/esm/limebb-lime-query-filter-comparison_2.entry.js +4 -4
- package/dist/esm/limebb-lime-query-order-by-editor_2.entry.js +3 -3
- package/dist/esm/limebb-lime-query-order-by-item.entry.js +1 -1
- package/dist/esm/limebb-lime-query-response-format-builder.entry.js +3 -3
- package/dist/esm/limebb-lime-query-response-format-editor_2.entry.js +1 -1
- package/dist/esm/limebb-limeobject-file-viewer.entry.js +2 -2
- package/dist/esm/limebb-live-docs-info.entry.js +1 -1
- package/dist/esm/limebb-loader.entry.js +2 -2
- package/dist/esm/limebb-locale-picker.entry.js +2 -2
- package/dist/esm/limebb-mention-group-counter.entry.js +1 -1
- package/dist/esm/limebb-mention.entry.js +2 -2
- package/dist/esm/limebb-navigation-button_2.entry.js +1 -1
- package/dist/esm/limebb-notification-item.entry.js +2 -2
- package/dist/esm/limebb-notification-list.entry.js +2 -2
- package/dist/esm/limebb-object-chip.entry.js +3 -3
- package/dist/esm/limebb-percentage-visualizer.entry.js +2 -2
- package/dist/esm/limebb-property-selector.entry.js +3 -3
- package/dist/esm/limebb-rule-arg-filter-editor.entry.js +2 -2
- package/dist/esm/limebb-rule-condition-chip.entry.js +69 -0
- package/dist/esm/limebb-rule-condition-editor-DeY758N-.js +281 -0
- package/dist/esm/limebb-rule-condition-editor.entry.js +3 -0
- package/dist/esm/limebb-rule-editor.entry.js +217 -573
- package/dist/esm/limebb-rule-gate.entry.js +2 -2
- package/dist/esm/limebb-text-editor-picker.entry.js +1 -1
- package/dist/esm/limebb-text-editor.entry.js +3 -3
- package/dist/esm/limebb-trend-indicator.entry.js +2 -2
- package/dist/esm/limebb-value-comparison-editor.entry.js +3 -3
- package/dist/esm/{limetype-BcELY1NF.js → limetype-Muf9VutX.js} +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/{web-component-template-DxbwHsvw.js → web-component-template-D1JpeNy_.js} +1 -1
- package/dist/lime-crm-building-blocks/index.esm.js +1 -1
- package/dist/lime-crm-building-blocks/lime-crm-building-blocks.esm.js +1 -1
- package/dist/lime-crm-building-blocks/p-0621e884.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-ab0f8170.entry.js → p-087d5651.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-ce2755a0.entry.js → p-1917956c.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-07a9c8f2.entry.js → p-1ae4962d.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-021e452a.entry.js → p-23d2632b.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-ffca266e.entry.js → p-251784bf.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-635a45ad.entry.js → p-27240bb0.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/p-2adeac66.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-6a8422d2.entry.js → p-32339f09.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-1990e369.entry.js → p-3446290c.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-d495cc19.entry.js → p-35d9b3ad.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-eed0b2c2.entry.js → p-3865eec4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-dacf9e77.entry.js → p-394b521a.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-8c36b847.entry.js → p-39a36450.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-97e75dee.entry.js → p-3b672249.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-ad5dcefd.entry.js → p-47b56a75.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-402a9c97.entry.js → p-4af3ea2c.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-0cc47cad.entry.js → p-4bdaf436.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-cf66256a.entry.js → p-4f60b7bc.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-90f0c96b.entry.js → p-4fd9d615.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-28550961.entry.js → p-53b44865.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-7ae27308.entry.js → p-550606f6.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/p-573f9e95.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-a5f3913d.entry.js → p-5c541d0c.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-ce723c21.entry.js → p-612c6b28.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-5f682c06.entry.js → p-627b0c79.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-49d042aa.entry.js → p-6303201b.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-6f923112.entry.js → p-687640ed.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-8e9fcf3c.entry.js → p-6bd61290.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-dcb49a62.entry.js → p-6d2dba20.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-0193ed83.entry.js → p-6e2553b4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-Cz5s8qGk.js → p-7DQ7qvMa.js} +1 -1
- package/dist/lime-crm-building-blocks/p-7c3d3e06.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-dd02821e.entry.js → p-7d53756b.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-79d743bb.entry.js → p-895c8966.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-da35bcc7.entry.js → p-8c0455e4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-a201df35.entry.js → p-8f80d024.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-32a81271.entry.js → p-949ed056.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-cf03a756.entry.js → p-985ae787.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/p-9959019d.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-DLec4QaM.js → p-B7whyaAL.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-COtSgrC5.js → p-BK566_jX.js} +1 -1
- package/dist/lime-crm-building-blocks/p-ClYOFrOo.js +1 -0
- package/dist/lime-crm-building-blocks/{p-DVypQWZ4.js → p-Cve-3L4y.js} +1 -1
- package/dist/lime-crm-building-blocks/p-DOULPRTn.js +1 -0
- package/dist/lime-crm-building-blocks/{p-Cj_3f9vm.js → p-DhGRAeCH.js} +1 -1
- package/dist/lime-crm-building-blocks/p-DjoMDjMo.js +1 -0
- package/dist/lime-crm-building-blocks/p-DuWEcQ7n.js +1 -0
- package/dist/lime-crm-building-blocks/{p-dfaef740.entry.js → p-a1052482.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-3babfbe0.entry.js → p-a14bed52.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-cc53a8ca.entry.js → p-a2e291b4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-8a17a7ea.entry.js → p-a2ebd5a4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-0cbe2180.entry.js → p-a4556649.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-f5c1ed0c.entry.js → p-a598f92f.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-b44b9dbc.entry.js → p-a938384f.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-f3539042.entry.js → p-ab0210b2.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-c0d49532.entry.js → p-b272730c.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-0370200d.entry.js → p-b4571d32.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-551a36f6.entry.js → p-b72c748b.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-0ed9a7cc.entry.js → p-bac9d3a9.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/p-bd6c12bc.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-81783bd4.entry.js → p-bf693702.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-e6cc320a.entry.js → p-c58067ec.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-08797129.entry.js → p-c7bfa2e4.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-a953d48e.entry.js → p-d4635a39.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-d3c58bc1.entry.js → p-d6099dc7.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-bf05d9de.entry.js → p-d6c7cf0f.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-1ebe45b8.entry.js → p-da79c5fc.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/p-e18a2cef.entry.js +1 -0
- package/dist/lime-crm-building-blocks/{p-f9991c35.entry.js → p-e19f4b3b.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-46aec244.entry.js → p-eb95767a.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-ddc4ede8.entry.js → p-ec9b5e30.entry.js} +1 -1
- package/dist/lime-crm-building-blocks/{p-95ba7a84.entry.js → p-f49250f3.entry.js} +1 -1
- package/dist/types/components/condition-tree/condition-tree-editor/condition-tree-editor.d.ts +20 -3
- package/dist/types/components/condition-tree/condition-tree-nodes.d.ts +11 -4
- package/dist/types/components/condition-tree/condition-tree-view-context.d.ts +3 -2
- package/dist/types/components/condition-tree/condition-tree.d.ts +41 -8
- package/dist/types/components/condition-tree/condition-tree.types.d.ts +21 -2
- package/dist/types/components/rule-editor/condition-tree-adapter.d.ts +67 -0
- package/dist/types/components/rule-editor/rule-condition-chip/rule-condition-chip.d.ts +82 -0
- package/dist/types/components/rule-editor/rule-condition-editor/rule-condition-editor.d.ts +61 -0
- package/dist/types/components/rule-editor/rule-editor.d.ts +105 -47
- package/dist/types/components/rule-editor/rule-issues.d.ts +12 -0
- package/dist/types/components/rule-editor/view-helpers.d.ts +16 -35
- package/dist/types/components.d.ts +304 -79
- package/dist/types/stencil-public-runtime.d.ts +61 -55
- package/package.json +4 -4
- package/dist/cjs/limebb-rule-chip-popover.cjs.entry.js +0 -82
- package/dist/collection/components/rule-editor/chip-picker-view.js +0 -148
- package/dist/collection/components/rule-editor/group-node-view.js +0 -79
- package/dist/collection/components/rule-editor/rule-chip-popover/rule-chip-popover.css +0 -36
- package/dist/collection/components/rule-editor/rule-chip-popover/rule-chip-popover.js +0 -344
- package/dist/collection/components/rule-editor/rule-editor-views.js +0 -43
- package/dist/collection/components/rule-editor/rule-operations.js +0 -145
- package/dist/components/limebb-rule-chip-popover.d.ts +0 -11
- package/dist/components/limebb-rule-chip-popover.js +0 -1
- package/dist/components/rule-chip-popover.js +0 -1
- package/dist/esm/limebb-rule-chip-popover.entry.js +0 -80
- package/dist/lime-crm-building-blocks/p-1578c8f0.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-229d018c.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-6331f9c5.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-705c53c0.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-84ad9159.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-BxCq236x.js +0 -1
- package/dist/lime-crm-building-blocks/p-Css8537O.js +0 -1
- package/dist/lime-crm-building-blocks/p-a58c9e1e.entry.js +0 -1
- package/dist/lime-crm-building-blocks/p-hsyotUav.js +0 -1
- package/dist/types/components/rule-editor/chip-picker-view.d.ts +0 -35
- package/dist/types/components/rule-editor/group-node-view.d.ts +0 -11
- package/dist/types/components/rule-editor/rule-chip-popover/rule-chip-popover.d.ts +0 -43
- package/dist/types/components/rule-editor/rule-editor-views.d.ts +0 -58
- package/dist/types/components/rule-editor/rule-operations.d.ts +0 -70
|
@@ -1,177 +1,106 @@
|
|
|
1
|
-
import { h, r as registerInstance, c as createEvent, H as Host, g as getElement } from './index-
|
|
2
|
-
import { M as Mt, n } from './index.esm-
|
|
1
|
+
import { h, r as registerInstance, c as createEvent, H as Host, g as getElement } from './index-BK566_jX.js';
|
|
2
|
+
import { M as Mt, n } from './index.esm-C__n3hug.js';
|
|
3
|
+
import { c as createTranslator } from './condition-tree-translate-ZQptbaXF.js';
|
|
4
|
+
import { c as createRuleConditionTreeAdapter, g as groupOf } from './limebb-rule-condition-editor-DeY758N-.js';
|
|
5
|
+
import './limebb-rule-condition-chip.entry.js';
|
|
3
6
|
import { r as ruleForMode, b as ruleMode, A as ALWAYS_PRIMITIVE_ID } from './rule-editor-modes-BCglve2Z.js';
|
|
4
7
|
import { c as createRandomString } from './random-string-C2JP2nLw.js';
|
|
8
|
+
import './web-component-template-D1JpeNy_.js';
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* The problems the registry found, gathered by the node each belongs to.
|
|
8
12
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @param
|
|
13
|
-
* @param
|
|
14
|
-
*/
|
|
15
|
-
function deleteNode(rule, path) {
|
|
16
|
-
if (path.length === 0) {
|
|
17
|
-
return { type: 'all', rules: [] };
|
|
18
|
-
}
|
|
19
|
-
const parentPath = path.slice(0, -1);
|
|
20
|
-
const key = path.at(-1);
|
|
21
|
-
const parent = getNode(rule, parentPath);
|
|
22
|
-
if (parent === undefined) {
|
|
23
|
-
return rule;
|
|
24
|
-
}
|
|
25
|
-
if ((parent.type === 'all' || parent.type === 'any') &&
|
|
26
|
-
typeof key === 'number') {
|
|
27
|
-
const rules = [...parent.rules];
|
|
28
|
-
rules.splice(key, 1);
|
|
29
|
-
return replaceAt(rule, parentPath, Object.assign(Object.assign({}, parent), { rules }));
|
|
30
|
-
}
|
|
31
|
-
if (parent.type === 'not' && key === 'rule') {
|
|
32
|
-
return replaceAt(rule, parentPath, { type: 'all', rules: [] });
|
|
33
|
-
}
|
|
34
|
-
return rule;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Replace the `args` of a `ref` node. Returns `rule` unchanged when
|
|
38
|
-
* `path` does not resolve to a `ref`.
|
|
39
|
-
* @param rule
|
|
40
|
-
* @param path
|
|
41
|
-
* @param args
|
|
42
|
-
*/
|
|
43
|
-
function updateArgs(rule, path, args) {
|
|
44
|
-
const node = getNode(rule, path);
|
|
45
|
-
if (node === undefined || node.type !== 'ref') {
|
|
46
|
-
return rule;
|
|
47
|
-
}
|
|
48
|
-
return replaceAt(rule, path, Object.assign(Object.assign({}, node), { args }));
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Replace the node at `path` with `replacement`, returning a new rule
|
|
52
|
-
* tree. Used by callers that need to apply a non-atomic change as a
|
|
53
|
-
* single emit (e.g. updating a group's whole `rules` array at once).
|
|
54
|
-
* @param rule
|
|
55
|
-
* @param path
|
|
56
|
-
* @param replacement
|
|
57
|
-
*/
|
|
58
|
-
function replaceNode(rule, path, replacement) {
|
|
59
|
-
return replaceAt(rule, path, replacement);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Wrap `group` in a `not` when `isNegated`, otherwise return it
|
|
63
|
-
* unchanged. Used when re-emitting a group whose negation flag should
|
|
64
|
-
* be preserved.
|
|
65
|
-
* @param group
|
|
66
|
-
* @param isNegated
|
|
67
|
-
*/
|
|
68
|
-
function wrapNegated(group, isNegated) {
|
|
69
|
-
return isNegated ? { type: 'not', rule: group } : group;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Append `child` to a group's `rules`, returning a new group. The
|
|
73
|
-
* input is not mutated.
|
|
74
|
-
* @param group
|
|
75
|
-
* @param child
|
|
13
|
+
* The registry addresses an issue by path — `['rules', 0, 'rule']` for
|
|
14
|
+
* `root.rules[0].rule` — while the tree asks about one node at a time and never
|
|
15
|
+
* says where it is. Resolving the paths once, here, bridges the two.
|
|
16
|
+
* @param root
|
|
17
|
+
* @param issues
|
|
76
18
|
*/
|
|
77
|
-
function
|
|
78
|
-
|
|
19
|
+
function collectRuleIssues(root, issues) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
const owners = displayOwners(root);
|
|
22
|
+
const byNode = new Map();
|
|
23
|
+
for (const issue of issues) {
|
|
24
|
+
const node = nodeAt(root, issue.path);
|
|
25
|
+
// An empty path means the rule as a whole, and one the path cannot
|
|
26
|
+
// reach has nowhere better to go than the root either.
|
|
27
|
+
const owner = (_a = (node && owners.get(node))) !== null && _a !== void 0 ? _a : root;
|
|
28
|
+
byNode.set(owner, [...((_b = byNode.get(owner)) !== null && _b !== void 0 ? _b : []), issue.message]);
|
|
29
|
+
}
|
|
30
|
+
return byNode;
|
|
79
31
|
}
|
|
80
32
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
33
|
+
* Which node each node is drawn as part of. Most stand for themselves; the
|
|
34
|
+
* exception is everything under a `not`, which is drawn as that `not` — the
|
|
35
|
+
* two are one thing on screen, and only the wrapper has somewhere to show it.
|
|
36
|
+
* @param root
|
|
84
37
|
*/
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
38
|
+
function displayOwners(root) {
|
|
39
|
+
const owners = new Map();
|
|
40
|
+
const visit = (node, owner) => {
|
|
41
|
+
// A hand-edited rule can hold a `null` where a node should be. It is
|
|
42
|
+
// drawn, as something that cannot be read, so it is walked past here.
|
|
43
|
+
if (typeof node !== 'object' || node === null) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
owners.set(node, owner);
|
|
47
|
+
if (node.type === 'not') {
|
|
48
|
+
visit(node.rule, owner);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if ((node.type === 'all' || node.type === 'any') &&
|
|
52
|
+
Array.isArray(node.rules)) {
|
|
53
|
+
for (const child of node.rules) {
|
|
54
|
+
visit(child, child);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
visit(root, root);
|
|
59
|
+
return owners;
|
|
98
60
|
}
|
|
99
61
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
62
|
+
* The node a validation path addresses, or nothing when it addresses none.
|
|
63
|
+
*
|
|
64
|
+
* Walked one hop at a time because the two the registry emits have different
|
|
65
|
+
* shapes: into a negation is the single segment `rule`, into the *n*-th child
|
|
66
|
+
* of a group is the pair `rules`, *n*. Anything else is not a path this rule
|
|
67
|
+
* can be walked by.
|
|
68
|
+
* @param root
|
|
104
69
|
* @param path
|
|
105
70
|
*/
|
|
106
|
-
function
|
|
107
|
-
let node =
|
|
108
|
-
|
|
109
|
-
|
|
71
|
+
function nodeAt(root, path) {
|
|
72
|
+
let node = root;
|
|
73
|
+
let index = 0;
|
|
74
|
+
while (index < path.length) {
|
|
75
|
+
// The same `null` can be standing one hop short of the path's end,
|
|
76
|
+
// with no hop to take from it. Asked for `type`, it would throw.
|
|
77
|
+
if (node === null || typeof node !== 'object') {
|
|
110
78
|
return undefined;
|
|
111
79
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (path.length === 0) {
|
|
118
|
-
return replacement;
|
|
119
|
-
}
|
|
120
|
-
const [head, ...tail] = path;
|
|
121
|
-
if (root.type === 'not' && head === 'rule') {
|
|
122
|
-
return Object.assign(Object.assign({}, root), { rule: replaceAt(root.rule, tail, replacement) });
|
|
123
|
-
}
|
|
124
|
-
if ((root.type === 'all' || root.type === 'any') && head === 'rules') {
|
|
125
|
-
if (tail.length === 0) {
|
|
126
|
-
return replacement;
|
|
80
|
+
const key = path[index];
|
|
81
|
+
if (key === 'rule' && node.type === 'not') {
|
|
82
|
+
node = node.rule;
|
|
83
|
+
index += 1;
|
|
84
|
+
continue;
|
|
127
85
|
}
|
|
128
|
-
const [index
|
|
129
|
-
if (
|
|
130
|
-
|
|
86
|
+
const child = path[index + 1];
|
|
87
|
+
if (key === 'rules' &&
|
|
88
|
+
(node.type === 'all' || node.type === 'any') &&
|
|
89
|
+
Array.isArray(node.rules) &&
|
|
90
|
+
typeof child === 'number') {
|
|
91
|
+
node = node.rules[child];
|
|
92
|
+
index += 2;
|
|
93
|
+
continue;
|
|
131
94
|
}
|
|
132
|
-
|
|
133
|
-
rules[index] = replaceAt(rules[index], rest, replacement);
|
|
134
|
-
return Object.assign(Object.assign({}, root), { rules });
|
|
135
|
-
}
|
|
136
|
-
return root;
|
|
137
|
-
}
|
|
138
|
-
function stepIntoNode(node, key) {
|
|
139
|
-
if (node.type === 'not' && key === 'rule') {
|
|
140
|
-
return node.rule;
|
|
141
|
-
}
|
|
142
|
-
if ((node.type === 'all' || node.type === 'any') && key === 'rules') {
|
|
143
|
-
return node;
|
|
144
|
-
}
|
|
145
|
-
if ((node.type === 'all' || node.type === 'any') &&
|
|
146
|
-
typeof key === 'number') {
|
|
147
|
-
return node.rules[key];
|
|
95
|
+
return undefined;
|
|
148
96
|
}
|
|
149
97
|
return node;
|
|
150
98
|
}
|
|
151
99
|
|
|
152
|
-
const UNKNOWN_ICON = {
|
|
153
|
-
name: 'question',
|
|
154
|
-
color: 'rgb(var(--color-glaucous-light))',
|
|
155
|
-
};
|
|
156
|
-
/**
|
|
157
|
-
* Class map for a rule-node container. Adds the type modifier and an
|
|
158
|
-
* `invalid` flag when validation issues attach to this node.
|
|
159
|
-
* @param type
|
|
160
|
-
* @param issues
|
|
161
|
-
*/
|
|
162
|
-
function nodeClasses(type, issues) {
|
|
163
|
-
return {
|
|
164
|
-
'rule-node': true,
|
|
165
|
-
[`rule-node--${type}`]: true,
|
|
166
|
-
'rule-node--invalid': issues.length > 0,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
100
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* register translation keys as metadata — plain strings travel through
|
|
174
|
-
* unchanged.
|
|
101
|
+
* The primitives the add button offers. Titles and descriptions go through the
|
|
102
|
+
* translator, so a caller can register translation keys as metadata — plain
|
|
103
|
+
* strings travel through unchanged.
|
|
175
104
|
* @param metadataById
|
|
176
105
|
* @param translator
|
|
177
106
|
*/
|
|
@@ -179,7 +108,7 @@ function createPrimitiveOptions(metadataById, translator) {
|
|
|
179
108
|
return [...metadataById.values()]
|
|
180
109
|
.map((meta) => ({
|
|
181
110
|
value: meta.id,
|
|
182
|
-
text: meta
|
|
111
|
+
text: primitiveTitle(meta, translator),
|
|
183
112
|
secondaryText: meta.description
|
|
184
113
|
? translator.get(meta.description)
|
|
185
114
|
: '',
|
|
@@ -187,6 +116,15 @@ function createPrimitiveOptions(metadataById, translator) {
|
|
|
187
116
|
}))
|
|
188
117
|
.sort((a, b) => a.text.localeCompare(b.text));
|
|
189
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* How a primitive reads: its translated title, or its bare id when it has none
|
|
121
|
+
* to give. The add menu and the chip both read it from here, so they agree.
|
|
122
|
+
* @param meta
|
|
123
|
+
* @param translator
|
|
124
|
+
*/
|
|
125
|
+
function primitiveTitle(meta, translator) {
|
|
126
|
+
return meta.title ? translator.get(meta.title) : meta.id;
|
|
127
|
+
}
|
|
190
128
|
/**
|
|
191
129
|
* Whether every context key a primitive reads is in the reachable set.
|
|
192
130
|
* A primitive that reads nothing is always covered.
|
|
@@ -197,23 +135,9 @@ function primitiveReadsCovered(meta, reachable) {
|
|
|
197
135
|
return meta.reads.every((key) => reachable.has(key));
|
|
198
136
|
}
|
|
199
137
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* @param id
|
|
204
|
-
*/
|
|
205
|
-
function resolveItem(allItems, id) {
|
|
206
|
-
var _a;
|
|
207
|
-
return ((_a = allItems.find((item) => item.value === id)) !== null && _a !== void 0 ? _a : {
|
|
208
|
-
value: id,
|
|
209
|
-
text: id,
|
|
210
|
-
icon: UNKNOWN_ICON,
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Build a picker `searcher` bound to a fixed item list. Both the ref
|
|
215
|
-
* picker and the chip picker want exactly this — wrapping
|
|
216
|
-
* {@link searchItems} in a promise — and deserve to share it.
|
|
138
|
+
* Narrow the primitives as the user types, for the search field at the top of
|
|
139
|
+
* the add menu. Every word has to match somewhere — title, description or id —
|
|
140
|
+
* so that "deal won" finds "Won deals".
|
|
217
141
|
* @param items
|
|
218
142
|
*/
|
|
219
143
|
function createSearcher(items) {
|
|
@@ -228,273 +152,12 @@ function searchItems(allItems, query) {
|
|
|
228
152
|
var _a, _b;
|
|
229
153
|
return item.text.toLocaleLowerCase().includes(part) ||
|
|
230
154
|
((_a = item.secondaryText) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase().includes(part)) ||
|
|
231
|
-
((_b = item.value)
|
|
155
|
+
String((_b = item.value) !== null && _b !== void 0 ? _b : '')
|
|
156
|
+
.toLocaleLowerCase()
|
|
157
|
+
.includes(part);
|
|
232
158
|
}));
|
|
233
159
|
}
|
|
234
160
|
|
|
235
|
-
const CHIP_TOKEN_PREFIX = '__chip__:';
|
|
236
|
-
function chipTokenFor(index) {
|
|
237
|
-
return `${CHIP_TOKEN_PREFIX}${index}`;
|
|
238
|
-
}
|
|
239
|
-
// The address of a chip inside a group is the group's path followed
|
|
240
|
-
// by a two-segment suffix `['rules', index]`. Build and parse via
|
|
241
|
-
// these helpers so both sides stay in sync.
|
|
242
|
-
const CHIP_PATH_SUFFIX_LENGTH = 2;
|
|
243
|
-
/**
|
|
244
|
-
* Address of the chip at `index` inside a group: the group's path plus
|
|
245
|
-
* the `['rules', index]` suffix. Built here so the picker and popover
|
|
246
|
-
* address chips the same way.
|
|
247
|
-
* @param groupPath
|
|
248
|
-
* @param index
|
|
249
|
-
*/
|
|
250
|
-
function buildChipPath(groupPath, index) {
|
|
251
|
-
return [...groupPath, 'rules', index];
|
|
252
|
-
}
|
|
253
|
-
function parentGroupPath(chipPath) {
|
|
254
|
-
return chipPath.slice(0, -CHIP_PATH_SUFFIX_LENGTH);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* If `node` is a `ref` or a `not(ref)`, return the underlying ref
|
|
258
|
-
* together with its negation flag. Used to decide whether a child of a
|
|
259
|
-
* group renders as a chip (this returns non-null) or as a nested box
|
|
260
|
-
* (this returns null).
|
|
261
|
-
* @param node
|
|
262
|
-
*/
|
|
263
|
-
function extractRef(node) {
|
|
264
|
-
if (node.type === 'ref') {
|
|
265
|
-
return { ref: node, isNegated: false };
|
|
266
|
-
}
|
|
267
|
-
if (node.type === 'not' && node.rule.type === 'ref') {
|
|
268
|
-
return { ref: node.rule, isNegated: true };
|
|
269
|
-
}
|
|
270
|
-
return null;
|
|
271
|
-
}
|
|
272
|
-
const GroupChipsView = ({ groupNode, groupPath, chipChildren, ctx }) => {
|
|
273
|
-
const chipsByToken = new Map();
|
|
274
|
-
const value = chipChildren.map((entry) => {
|
|
275
|
-
const token = chipTokenFor(entry.index);
|
|
276
|
-
chipsByToken.set(token, entry);
|
|
277
|
-
const base = resolveItem(ctx.allPrimitiveOptions, entry.ref.id);
|
|
278
|
-
return Object.assign(Object.assign({}, base), { text: entry.isNegated ? `¬ ${base.text}` : base.text, value: token });
|
|
279
|
-
});
|
|
280
|
-
const searcher = createSearcher(ctx.availablePrimitiveOptions);
|
|
281
|
-
const openChip = findOpenChip(chipChildren, groupPath, ctx.openChipPath);
|
|
282
|
-
const delimiter = groupNode.type === 'all' ? '&' : '|';
|
|
283
|
-
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))));
|
|
284
|
-
};
|
|
285
|
-
function renderChipPopoverContent(openChip, groupPath, ctx) {
|
|
286
|
-
if (!openChip) {
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
const openChipPath = buildChipPath(groupPath, openChip.index);
|
|
290
|
-
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, focusOnOpen: ctx.focusOnOpen, onNegate: chipNegateHandler(openChip, openChipPath, ctx), onUpdateArgs: chipArgsHandler(openChip, openChipPath, ctx), onDeleteChip: chipDeleteHandler(openChipPath, ctx) }));
|
|
291
|
-
}
|
|
292
|
-
const chipsChangeHandler = (groupNode, groupPath, chipsByToken, ctx) => (event) => {
|
|
293
|
-
event.stopPropagation();
|
|
294
|
-
const items = Array.isArray(event.detail) ? event.detail : [];
|
|
295
|
-
const openIndex = openChipIndexInGroup(groupPath, ctx.openChipPath);
|
|
296
|
-
if (openIndex !== null) {
|
|
297
|
-
const openToken = chipTokenFor(openIndex);
|
|
298
|
-
if (items.every((item) => item.value !== openToken)) {
|
|
299
|
-
ctx.onPopoverClose();
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
const newChipNodes = items.flatMap((item) => {
|
|
303
|
-
if (typeof item.value !== 'string') {
|
|
304
|
-
return [];
|
|
305
|
-
}
|
|
306
|
-
const existing = chipsByToken.get(item.value);
|
|
307
|
-
if (existing) {
|
|
308
|
-
return [
|
|
309
|
-
existing.isNegated
|
|
310
|
-
? { type: 'not', rule: existing.ref }
|
|
311
|
-
: existing.ref,
|
|
312
|
-
];
|
|
313
|
-
}
|
|
314
|
-
return [{ type: 'ref', id: item.value }];
|
|
315
|
-
});
|
|
316
|
-
const nestedGroupRules = groupNode.rules.filter((rule) => extractRef(rule) === null);
|
|
317
|
-
ctx.onReplaceNode(groupPath, Object.assign(Object.assign({}, groupNode), { rules: [...newChipNodes, ...nestedGroupRules] }));
|
|
318
|
-
};
|
|
319
|
-
const chipInteractHandler = (groupPath, chipsByToken, ctx) => (event) => {
|
|
320
|
-
event.stopPropagation();
|
|
321
|
-
const token = interactedToken(event.detail);
|
|
322
|
-
const chip = token ? chipsByToken.get(token) : undefined;
|
|
323
|
-
if (!chip) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
ctx.onChipInteract([...groupPath, 'rules', chip.index]);
|
|
327
|
-
};
|
|
328
|
-
const chipNegateHandler = (openChip, openChipPath, ctx) => (event) => {
|
|
329
|
-
event.stopPropagation();
|
|
330
|
-
const next = event.detail
|
|
331
|
-
? { type: 'not', rule: openChip.ref }
|
|
332
|
-
: openChip.ref;
|
|
333
|
-
ctx.onReplaceNode(openChipPath, next);
|
|
334
|
-
};
|
|
335
|
-
const chipArgsHandler = (openChip, openChipPath, ctx) => (event) => {
|
|
336
|
-
event.stopPropagation();
|
|
337
|
-
const argsPath = openChip.isNegated
|
|
338
|
-
? [...openChipPath, 'rule']
|
|
339
|
-
: openChipPath;
|
|
340
|
-
ctx.onUpdateArgs(argsPath, event.detail);
|
|
341
|
-
};
|
|
342
|
-
const chipDeleteHandler = (openChipPath, ctx) => () => {
|
|
343
|
-
ctx.onDelete(openChipPath);
|
|
344
|
-
};
|
|
345
|
-
/**
|
|
346
|
-
* `limel-picker` declares its `interact` event as
|
|
347
|
-
* `EventEmitter<ListItem<PickerValue>>` but the runtime actually emits
|
|
348
|
-
* the chip's value (a string) — see picker.tsx's handleInteract. This
|
|
349
|
-
* unwraps either shape into the string token.
|
|
350
|
-
* @param detail
|
|
351
|
-
*/
|
|
352
|
-
function interactedToken(detail) {
|
|
353
|
-
if (typeof detail === 'string') {
|
|
354
|
-
return detail;
|
|
355
|
-
}
|
|
356
|
-
if (detail && typeof detail === 'object' && 'value' in detail) {
|
|
357
|
-
const value = detail.value;
|
|
358
|
-
return typeof value === 'string' ? value : undefined;
|
|
359
|
-
}
|
|
360
|
-
return undefined;
|
|
361
|
-
}
|
|
362
|
-
function findOpenChip(chipChildren, groupPath, openChipPath) {
|
|
363
|
-
var _a;
|
|
364
|
-
const index = openChipIndexInGroup(groupPath, openChipPath);
|
|
365
|
-
if (index === null) {
|
|
366
|
-
return null;
|
|
367
|
-
}
|
|
368
|
-
return (_a = chipChildren.find((entry) => entry.index === index)) !== null && _a !== void 0 ? _a : null;
|
|
369
|
-
}
|
|
370
|
-
function openChipIndexInGroup(groupPath, openChipPath) {
|
|
371
|
-
if (!openChipPath || openChipPath.length < CHIP_PATH_SUFFIX_LENGTH) {
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
|
-
if (!pathsEqual(parentGroupPath(openChipPath), groupPath)) {
|
|
375
|
-
return null;
|
|
376
|
-
}
|
|
377
|
-
const lastKey = openChipPath.at(-1);
|
|
378
|
-
return typeof lastKey === 'number' ? lastKey : null;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const GroupNodeView = ({ node, path, isNegated, ctx }) => {
|
|
382
|
-
const groupBasePath = isNegated ? [...path, 'rule'] : path;
|
|
383
|
-
const issuesHere = isNegated
|
|
384
|
-
? [
|
|
385
|
-
...issuesAt(ctx.issues, path),
|
|
386
|
-
...issuesAt(ctx.issues, groupBasePath),
|
|
387
|
-
]
|
|
388
|
-
: issuesAt(ctx.issues, path);
|
|
389
|
-
const chipChildren = [];
|
|
390
|
-
const nestedGroups = [];
|
|
391
|
-
for (const [index, child] of node.rules.entries()) {
|
|
392
|
-
const extracted = extractRef(child);
|
|
393
|
-
if (extracted) {
|
|
394
|
-
chipChildren.push(Object.assign(Object.assign({}, extracted), { index }));
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
nestedGroups.push({ child, index });
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
const options = combinatorOptions(ctx);
|
|
401
|
-
const selectedCombinator = options.find((option) => option.value === node.type);
|
|
402
|
-
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))));
|
|
403
|
-
};
|
|
404
|
-
function pathKey(path) {
|
|
405
|
-
return path.length === 0 ? 'root' : path.join('/');
|
|
406
|
-
}
|
|
407
|
-
function combinatorOptions(ctx) {
|
|
408
|
-
return [
|
|
409
|
-
{
|
|
410
|
-
value: 'all',
|
|
411
|
-
text: ctx.translator.get('webclient.combinator.all'),
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
value: 'any',
|
|
415
|
-
text: ctx.translator.get('webclient.combinator.any'),
|
|
416
|
-
},
|
|
417
|
-
];
|
|
418
|
-
}
|
|
419
|
-
function renderMutableGroupActions(node, path, isNegated, ctx) {
|
|
420
|
-
if (!ctx.isMutable) {
|
|
421
|
-
return null;
|
|
422
|
-
}
|
|
423
|
-
return (h("div", { class: "rule-node__header-actions" }, h("limel-switch", { class: "rule-node__negate-switch", label: ctx.translator.get('webclient.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) })));
|
|
424
|
-
}
|
|
425
|
-
function renderNestedGroups(nestedGroups, groupBasePath, ctx) {
|
|
426
|
-
if (nestedGroups.length === 0) {
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
return (h("div", { class: "rule-node__children" }, nestedGroups.map((entry) => (h(RuleNodeView, { node: entry.child, path: [...groupBasePath, 'rules', entry.index], ctx: ctx })))));
|
|
430
|
-
}
|
|
431
|
-
function renderAddGroupFooter(node, path, isNegated, ctx) {
|
|
432
|
-
if (!ctx.isMutable) {
|
|
433
|
-
return null;
|
|
434
|
-
}
|
|
435
|
-
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) })));
|
|
436
|
-
}
|
|
437
|
-
function replaceGroup(nextGroup, path, isNegated, ctx) {
|
|
438
|
-
ctx.onReplaceNode(path, wrapNegated(nextGroup, isNegated));
|
|
439
|
-
}
|
|
440
|
-
const combinatorChangeHandler = (node, path, isNegated, ctx) => (event) => {
|
|
441
|
-
event.stopPropagation();
|
|
442
|
-
const newType = event.detail.value;
|
|
443
|
-
if (newType !== node.type) {
|
|
444
|
-
replaceGroup(Object.assign(Object.assign({}, node), { type: newType }), path, isNegated, ctx);
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
const addGroupHandler = (node, path, isNegated, ctx) => () => {
|
|
448
|
-
const expanded = appendChild(node, { type: 'all', rules: [] });
|
|
449
|
-
replaceGroup(expanded, path, isNegated, ctx);
|
|
450
|
-
};
|
|
451
|
-
const negateGroupHandler = (node, path, ctx) => (event) => {
|
|
452
|
-
event.stopPropagation();
|
|
453
|
-
ctx.onReplaceNode(path, wrapNegated(node, event.detail));
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Render a `Rule` node and recurse into its children.
|
|
458
|
-
* @param props
|
|
459
|
-
*/
|
|
460
|
-
const RuleNodeView = (props) => {
|
|
461
|
-
const { node, path, ctx } = props;
|
|
462
|
-
const group = extractGroup(node);
|
|
463
|
-
if (!group) {
|
|
464
|
-
return null;
|
|
465
|
-
}
|
|
466
|
-
return (h(GroupNodeView, { node: group.node, path: path, isNegated: group.isNegated, ctx: ctx }));
|
|
467
|
-
};
|
|
468
|
-
const isNegatedGroup = (node) => node.type === 'not' &&
|
|
469
|
-
(node.rule.type === 'all' || node.rule.type === 'any');
|
|
470
|
-
/**
|
|
471
|
-
* If `node` is a group (`all`/`any`) or a negated group, return the
|
|
472
|
-
* inner group together with its negation flag. Otherwise `null`.
|
|
473
|
-
* Used by the dispatcher and by the editor's input normalization.
|
|
474
|
-
* @param node
|
|
475
|
-
*/
|
|
476
|
-
function extractGroup(node) {
|
|
477
|
-
if (node.type === 'all' || node.type === 'any') {
|
|
478
|
-
return { node, isNegated: false };
|
|
479
|
-
}
|
|
480
|
-
if (isNegatedGroup(node)) {
|
|
481
|
-
return { node: node.rule, isNegated: true };
|
|
482
|
-
}
|
|
483
|
-
if (node.type === 'not') {
|
|
484
|
-
const inner = extractGroup(node.rule);
|
|
485
|
-
if (inner) {
|
|
486
|
-
return { node: inner.node, isNegated: !inner.isNegated };
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
return null;
|
|
490
|
-
}
|
|
491
|
-
const IssuesView = ({ issues }) => {
|
|
492
|
-
if (issues.length === 0) {
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
return issues.map((issue) => (h("div", { class: "rule-node__issue" }, issue.message)));
|
|
496
|
-
};
|
|
497
|
-
|
|
498
161
|
/**
|
|
499
162
|
* The shared string each mode is labelled from. Adverbs answering "when
|
|
500
163
|
* does this apply?", so they carry no rule-editor namespace and are
|
|
@@ -527,7 +190,7 @@ const RuleModeView = (props) => {
|
|
|
527
190
|
} }));
|
|
528
191
|
};
|
|
529
192
|
|
|
530
|
-
const ruleEditorCss = () => `@charset "UTF-8";:host{display:block;position:relative}.limel-notched-outline{--limel-notched-outline-background-color:transparent;padding:0.5rem 0 0 0}limel-notched-outline:not([invalid]:not([invalid=false])) .limel-notched-outline{--limel-notched-outline-border-color:transparent}.rule-editor--disabled{opacity:0.6;pointer-events:none}
|
|
193
|
+
const ruleEditorCss = () => `@charset "UTF-8";:host{display:block;position:relative}.limel-notched-outline{--limel-notched-outline-background-color:transparent;padding:0.5rem 0 0 0}limel-notched-outline:not([invalid]:not([invalid=false])) .limel-notched-outline{--limel-notched-outline-border-color:transparent}.rule-editor--disabled{opacity:0.6;pointer-events:none}limebb-condition-tree{--popover-surface-width:min(calc(100vw - 4rem), 50rem)}:host(limebb-rule-editor:focus),:host(limebb-rule-editor:focus-visible),:host(limebb-rule-editor:focus-within){--limel-h-l-grid-template-rows-transition-speed:0.46s;--limel-h-l-grid-template-rows:1fr}:host(limebb-rule-editor){--limel-h-l-grid-template-rows-transition-speed:0.3s;--limel-h-l-grid-template-rows:0fr}:host(limebb-rule-editor:focus) limel-helper-line,:host(limebb-rule-editor:focus-visible) limel-helper-line,:host(limebb-rule-editor:focus-within) limel-helper-line,:host(limebb-rule-editor:hover) limel-helper-line{will-change:grid-template-rows}limel-help{position:absolute;top:calc(var(--form-row-gap, 1rem) * -0.5);left:calc(var(--form-column-gap, 1rem) * -0.5);z-index:1}`;
|
|
531
194
|
|
|
532
195
|
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
533
196
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -543,8 +206,6 @@ const RuleEditor = class {
|
|
|
543
206
|
constructor(hostRef) {
|
|
544
207
|
registerInstance(this, hostRef);
|
|
545
208
|
this.change = createEvent(this, "change");
|
|
546
|
-
this.issues = [];
|
|
547
|
-
this.openChipPath = null;
|
|
548
209
|
/**
|
|
549
210
|
* The mode the author last clicked, held until `value` reads back
|
|
550
211
|
* as it.
|
|
@@ -555,10 +216,27 @@ const RuleEditor = class {
|
|
|
555
216
|
* what the author just clicked.
|
|
556
217
|
*/
|
|
557
218
|
this.modeOverride = null;
|
|
558
|
-
this.focusOnOpen = false;
|
|
559
219
|
this.metadataById = new Map();
|
|
560
|
-
|
|
220
|
+
/**
|
|
221
|
+
* How each registered primitive reads, by id. Translated once here
|
|
222
|
+
* because the platform's translator parses the message afresh on
|
|
223
|
+
* every call, and the adapter would otherwise do that per condition,
|
|
224
|
+
* several times over, on every edit.
|
|
225
|
+
*/
|
|
226
|
+
this.primitiveTitles = new Map();
|
|
561
227
|
this.availablePrimitiveOptions = [];
|
|
228
|
+
this.searcher = createSearcher([]);
|
|
229
|
+
/**
|
|
230
|
+
* What validation found, by the node it belongs to.
|
|
231
|
+
*/
|
|
232
|
+
this.issuesByNode = new Map();
|
|
233
|
+
/**
|
|
234
|
+
* The conditions added here rather than loaded, which a `RuleRef`
|
|
235
|
+
* does not record. The adapter reads it to decide which condition
|
|
236
|
+
* opens itself. Replaced when the tree goes, since a condition still
|
|
237
|
+
* listed when the author comes back would open itself again.
|
|
238
|
+
*/
|
|
239
|
+
this.created = new WeakSet();
|
|
562
240
|
this.reachableSlots = new Set();
|
|
563
241
|
this.normalizedCache = null;
|
|
564
242
|
this.hasLoaded = false;
|
|
@@ -572,6 +250,9 @@ const RuleEditor = class {
|
|
|
572
250
|
* conditions are gone, rather than handing back the ones they
|
|
573
251
|
* removed. With nothing stashed, `conditional` emits no rule, which
|
|
574
252
|
* is how the editor already says "the author cleared this".
|
|
253
|
+
*
|
|
254
|
+
* What is not stashed is which conditions had just been added, so
|
|
255
|
+
* that none of them opens itself again on the way back.
|
|
575
256
|
* @param mode
|
|
576
257
|
*/
|
|
577
258
|
this.handleModeChange = (mode) => {
|
|
@@ -579,32 +260,28 @@ const RuleEditor = class {
|
|
|
579
260
|
if (this.currentMode === 'conditional') {
|
|
580
261
|
this.stashedTree = this.value;
|
|
581
262
|
}
|
|
263
|
+
if (mode !== 'conditional') {
|
|
264
|
+
this.created = new WeakSet();
|
|
265
|
+
}
|
|
582
266
|
this.modeOverride = mode;
|
|
583
267
|
this.change.emit((_a = ruleForMode(mode)) !== null && _a !== void 0 ? _a : this.stashedTree);
|
|
584
268
|
};
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
this.
|
|
600
|
-
|
|
601
|
-
this.handleChipInteract = (path) => {
|
|
602
|
-
this.openChipPath = path;
|
|
603
|
-
this.focusOnOpen = false;
|
|
604
|
-
};
|
|
605
|
-
this.handlePopoverClose = () => {
|
|
606
|
-
this.openChipPath = null;
|
|
607
|
-
this.focusOnOpen = false;
|
|
269
|
+
/**
|
|
270
|
+
* Take in a tree the author changed. The tree reports `null` when
|
|
271
|
+
* the last condition goes, which for a rule means there is none —
|
|
272
|
+
* the same thing an emptied editor has always emitted.
|
|
273
|
+
*
|
|
274
|
+
* Editing the tree is only possible in `conditional`, so the edit
|
|
275
|
+
* itself records the mode: without this, a tree emptied to nothing
|
|
276
|
+
* would read back as the first offered mode and rewrite the setting
|
|
277
|
+
* under the author.
|
|
278
|
+
* @param event
|
|
279
|
+
*/
|
|
280
|
+
this.handleTreeChange = (event) => {
|
|
281
|
+
var _a;
|
|
282
|
+
event.stopPropagation();
|
|
283
|
+
this.modeOverride = 'conditional';
|
|
284
|
+
this.change.emit((_a = event.detail) !== null && _a !== void 0 ? _a : undefined);
|
|
608
285
|
};
|
|
609
286
|
}
|
|
610
287
|
componentWillLoad() {
|
|
@@ -615,6 +292,7 @@ const RuleEditor = class {
|
|
|
615
292
|
this.indexMetadata();
|
|
616
293
|
this.rebuildAvailableOptions();
|
|
617
294
|
this.runValidation();
|
|
295
|
+
this.rebuildAdapter();
|
|
618
296
|
}
|
|
619
297
|
/**
|
|
620
298
|
* Re-walk reachable slots when the editor is re-attached to the DOM,
|
|
@@ -629,6 +307,7 @@ const RuleEditor = class {
|
|
|
629
307
|
this.computeReachableSlots();
|
|
630
308
|
this.rebuildAvailableOptions();
|
|
631
309
|
this.runValidation();
|
|
310
|
+
this.rebuildAdapter();
|
|
632
311
|
}
|
|
633
312
|
componentDidLoad() {
|
|
634
313
|
this.hasLoaded = true;
|
|
@@ -645,7 +324,7 @@ const RuleEditor = class {
|
|
|
645
324
|
this.rebuildFromRegistries();
|
|
646
325
|
}
|
|
647
326
|
render() {
|
|
648
|
-
return (h(Host, { key: '
|
|
327
|
+
return (h(Host, { key: 'eb89af0c748f82d8e60b1209c4fcce3475ac2934' }, this.renderHelp(), h("limel-notched-outline", { key: '9d454ec87268aa9ff07776d38882365a544a64e7', label: this.label, labelId: this.labelId, required: this.required, readonly: this.readonly, disabled: this.disabled, invalid: this.invalid, hasValue: true, hasFloatingLabel: true }, h("div", { key: '57293e75c641d4909a4d2e1d3a3d2c20a60a4512', slot: "content", class: {
|
|
649
328
|
'rule-editor': true,
|
|
650
329
|
'rule-editor--disabled': this.disabled,
|
|
651
330
|
}, role: "group", "aria-labelledby": this.label ? this.labelId : undefined, "aria-describedby": this.helperText ? this.helperTextId : undefined }, this.renderModes(), this.renderTree())), this.renderHelperLine()));
|
|
@@ -662,13 +341,18 @@ const RuleEditor = class {
|
|
|
662
341
|
* The condition tree, shown unless a mode other than `conditional`
|
|
663
342
|
* is selected — an unconditional rule has no conditions to show.
|
|
664
343
|
* A caller offering no modes at all gets the tree, as before.
|
|
344
|
+
*
|
|
345
|
+
* An unset rule is handed over as unset, rather than as an empty
|
|
346
|
+
* group: the tree draws the group an author's first condition will
|
|
347
|
+
* land in, and drawing one here would only be a second opinion on
|
|
348
|
+
* what that looks like.
|
|
665
349
|
*/
|
|
666
350
|
renderTree() {
|
|
667
351
|
const mode = this.currentMode;
|
|
668
352
|
if (mode && mode !== 'conditional') {
|
|
669
353
|
return null;
|
|
670
354
|
}
|
|
671
|
-
return (h(
|
|
355
|
+
return (h("limebb-condition-tree", { platform: this.platform, context: this.effectiveContext, value: this.normalizedValue, adapter: this.adapter, addOptions: this.availablePrimitiveOptions, addSearcher: this.searcher, readonly: this.readonly, disabled: this.disabled, onChange: this.handleTreeChange }));
|
|
672
356
|
}
|
|
673
357
|
renderHelperLine() {
|
|
674
358
|
if (!this.helperText) {
|
|
@@ -682,27 +366,6 @@ const RuleEditor = class {
|
|
|
682
366
|
}
|
|
683
367
|
return h("limel-help", { value: this.help });
|
|
684
368
|
}
|
|
685
|
-
createRenderContext() {
|
|
686
|
-
return {
|
|
687
|
-
issues: this.issues,
|
|
688
|
-
metadataById: this.metadataById,
|
|
689
|
-
allPrimitiveOptions: this.allPrimitiveOptions,
|
|
690
|
-
availablePrimitiveOptions: this.availablePrimitiveOptions,
|
|
691
|
-
isMutable: !this.readonly && !this.disabled,
|
|
692
|
-
readonly: this.readonly,
|
|
693
|
-
disabled: this.disabled,
|
|
694
|
-
platform: this.platform,
|
|
695
|
-
context: this.effectiveContext,
|
|
696
|
-
translator: this.translator,
|
|
697
|
-
openChipPath: this.openChipPath,
|
|
698
|
-
focusOnOpen: this.focusOnOpen,
|
|
699
|
-
onDelete: this.handleDelete,
|
|
700
|
-
onUpdateArgs: this.handleUpdateArgs,
|
|
701
|
-
onReplaceNode: this.handleReplaceNode,
|
|
702
|
-
onChipInteract: this.handleChipInteract,
|
|
703
|
-
onPopoverClose: this.handlePopoverClose,
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
369
|
/**
|
|
707
370
|
* The mode the editor is in, or `undefined` when it offers none —
|
|
708
371
|
* then it is the plain tree editor it was before modes existed.
|
|
@@ -736,51 +399,14 @@ const RuleEditor = class {
|
|
|
736
399
|
this.modeOverride = null;
|
|
737
400
|
}
|
|
738
401
|
}
|
|
739
|
-
/**
|
|
740
|
-
* Path of a newly added chip whose primitive declares a config
|
|
741
|
-
* component, so its args editor opens immediately on add. The new
|
|
742
|
-
* ref is found by object identity — the picker reuses existing ref
|
|
743
|
-
* objects and only the added chip is a fresh node — so adding a
|
|
744
|
-
* second instance of a primitive already in the group is still
|
|
745
|
-
* detected. Returns `null` unless exactly one ref was added and it
|
|
746
|
-
* has an editor, leaving the open chip untouched for removals,
|
|
747
|
-
* multi-adds, and negation.
|
|
748
|
-
* @param path
|
|
749
|
-
* @param replacement
|
|
750
|
-
*/
|
|
751
|
-
autoOpenPathFor(path, replacement) {
|
|
752
|
-
var _a;
|
|
753
|
-
if (replacement.type !== 'all' && replacement.type !== 'any') {
|
|
754
|
-
return null;
|
|
755
|
-
}
|
|
756
|
-
const previous = getNode(this.normalizedValue, path);
|
|
757
|
-
if (previous === undefined ||
|
|
758
|
-
(previous.type !== 'all' && previous.type !== 'any')) {
|
|
759
|
-
return null;
|
|
760
|
-
}
|
|
761
|
-
const previousRefs = new Set(previous.rules
|
|
762
|
-
.map((rule) => { var _a; return (_a = extractRef(rule)) === null || _a === void 0 ? void 0 : _a.ref; })
|
|
763
|
-
.filter((ref) => ref !== undefined));
|
|
764
|
-
const added = replacement.rules
|
|
765
|
-
.map((rule, index) => {
|
|
766
|
-
var _a;
|
|
767
|
-
const ref = (_a = extractRef(rule)) === null || _a === void 0 ? void 0 : _a.ref;
|
|
768
|
-
return ref && !previousRefs.has(ref) ? { ref, index } : null;
|
|
769
|
-
})
|
|
770
|
-
.filter((entry) => entry !== null);
|
|
771
|
-
if (added.length !== 1) {
|
|
772
|
-
return null;
|
|
773
|
-
}
|
|
774
|
-
const [{ ref, index }] = added;
|
|
775
|
-
return ((_a = this.metadataById.get(ref.id)) === null || _a === void 0 ? void 0 : _a.configComponent)
|
|
776
|
-
? buildChipPath(path, index)
|
|
777
|
-
: null;
|
|
778
|
-
}
|
|
779
402
|
indexMetadata() {
|
|
780
403
|
var _a, _b, _c;
|
|
781
404
|
const metadata = (_c = (_b = (_a = this.ruleRegistry).listMetadata) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : [];
|
|
782
405
|
this.metadataById = new Map(metadata.map((item) => [item.id, item]));
|
|
783
|
-
this.
|
|
406
|
+
this.primitiveTitles = new Map(metadata.map((item) => [
|
|
407
|
+
item.id,
|
|
408
|
+
primitiveTitle(item, this.translator),
|
|
409
|
+
]));
|
|
784
410
|
}
|
|
785
411
|
/**
|
|
786
412
|
* Recompute the cached add-palette options. The inputs — indexed
|
|
@@ -790,6 +416,7 @@ const RuleEditor = class {
|
|
|
790
416
|
*/
|
|
791
417
|
rebuildAvailableOptions() {
|
|
792
418
|
this.availablePrimitiveOptions = createPrimitiveOptions(this.availablePrimitiveMetadata(), this.translator);
|
|
419
|
+
this.searcher = createSearcher(this.availablePrimitiveOptions);
|
|
793
420
|
}
|
|
794
421
|
/**
|
|
795
422
|
* The subset of registered metadata offered for adding in the
|
|
@@ -797,7 +424,7 @@ const RuleEditor = class {
|
|
|
797
424
|
* reachable slots are dropped, and so is the always primitive —
|
|
798
425
|
* it reads nothing, so it is always covered, but an "Always" chip
|
|
799
426
|
* among a group's conditions says nothing. Filtering only the
|
|
800
|
-
* palette —
|
|
427
|
+
* palette — the adapter still reads the whole index — keeps
|
|
801
428
|
* already-placed chips resolving to their proper title even when
|
|
802
429
|
* their read slot isn't reachable.
|
|
803
430
|
*/
|
|
@@ -837,45 +464,81 @@ const RuleEditor = class {
|
|
|
837
464
|
]);
|
|
838
465
|
}
|
|
839
466
|
runValidation() {
|
|
840
|
-
|
|
841
|
-
this.issues = [];
|
|
842
|
-
return;
|
|
843
|
-
}
|
|
844
|
-
const result = this.ruleRegistry.validate(this.normalizedValue, [
|
|
845
|
-
...this.reachableSlots,
|
|
846
|
-
]);
|
|
847
|
-
this.issues = result.ok ? [] : result.issues;
|
|
467
|
+
this.issuesByNode = this.findIssues();
|
|
848
468
|
}
|
|
849
469
|
/**
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
470
|
+
* What the registry finds wrong with the rule, gathered by the node
|
|
471
|
+
* each problem belongs to. Validation runs against the normalized
|
|
472
|
+
* rule, which is also what the tree is handed, so the paths the
|
|
473
|
+
* registry reports address the very nodes the tree draws.
|
|
474
|
+
*
|
|
475
|
+
* A rule the registry cannot even walk — one hand-edited into a shape
|
|
476
|
+
* that is not a rule — makes it throw rather than report. That is the
|
|
477
|
+
* rule an author most needs the editor for, so the throw is caught
|
|
478
|
+
* and the editor drawn anyway: the tree marks the offending condition
|
|
479
|
+
* unreadable itself, which is the same thing validation would have
|
|
480
|
+
* said and in the place it belongs.
|
|
855
481
|
*/
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
482
|
+
findIssues() {
|
|
483
|
+
const root = this.normalizedValue;
|
|
484
|
+
if (!root) {
|
|
485
|
+
return new Map();
|
|
486
|
+
}
|
|
487
|
+
try {
|
|
488
|
+
const result = this.ruleRegistry.validate(root, [
|
|
489
|
+
...this.reachableSlots,
|
|
490
|
+
]);
|
|
491
|
+
return result.ok
|
|
492
|
+
? new Map()
|
|
493
|
+
: collectRuleIssues(root, result.issues);
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
// The throw names the node it choked on. What the author needs is
|
|
497
|
+
// already in the tree; this is what tells a developer an unreadable
|
|
498
|
+
// rule from a registry that could not answer for a readable one.
|
|
499
|
+
console.warn('rule-editor could not validate the rule', {
|
|
500
|
+
rule: root,
|
|
501
|
+
error,
|
|
502
|
+
});
|
|
503
|
+
return new Map();
|
|
859
504
|
}
|
|
860
|
-
this.modeOverride = 'conditional';
|
|
861
|
-
this.change.emit(collapseEmptyRoot(next));
|
|
862
505
|
}
|
|
863
506
|
/**
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
868
|
-
*
|
|
507
|
+
* Gather what the tree draws from into a new adapter, which is how a
|
|
508
|
+
* change the rule does not carry reaches the screen at all.
|
|
509
|
+
*
|
|
510
|
+
* Not rebuilt for a validation pass: that runs because the rule
|
|
511
|
+
* changed, and the tree is already redrawing for the same reason.
|
|
512
|
+
* Rebuilding there would sync its open state twice for one edit.
|
|
513
|
+
*/
|
|
514
|
+
rebuildAdapter() {
|
|
515
|
+
this.adapter = createRuleConditionTreeAdapter({
|
|
516
|
+
metadata: this.metadataById,
|
|
517
|
+
titles: this.primitiveTitles,
|
|
518
|
+
translate: createTranslator(this.platform),
|
|
519
|
+
issues: () => this.issuesByNode,
|
|
520
|
+
created: () => this.created,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Wrap any non-group `value` in a top-level `all`, so that a lone
|
|
525
|
+
* condition has a group to grow in. An unset value stays unset: the
|
|
526
|
+
* tree draws the group a first condition will land in, and
|
|
527
|
+
* `emitNormalization` never pushes that placeholder back to the
|
|
528
|
+
* caller, so "no rule yet" stays distinguishable from "the author
|
|
529
|
+
* cleared this".
|
|
869
530
|
*
|
|
870
531
|
* An unconditional mode is the exception: its sentinel is left
|
|
871
532
|
* exactly as it came in, because wrapping it would rewrite the
|
|
872
533
|
* shape the mode is read back from.
|
|
873
534
|
*
|
|
874
|
-
* Memoized so
|
|
875
|
-
*
|
|
876
|
-
* depends on it.
|
|
535
|
+
* Memoized, so that the tree is handed the same rule on every
|
|
536
|
+
* render and redraws only when the rule itself changes.
|
|
877
537
|
*/
|
|
878
538
|
get normalizedValue() {
|
|
539
|
+
if (!this.value) {
|
|
540
|
+
return undefined;
|
|
541
|
+
}
|
|
879
542
|
const mode = this.currentMode;
|
|
880
543
|
if (this.normalizedCache !== null &&
|
|
881
544
|
this.normalizedCache.source === this.value &&
|
|
@@ -942,35 +605,16 @@ const EMPTY_CONTEXT = Object.freeze({
|
|
|
942
605
|
id: null,
|
|
943
606
|
});
|
|
944
607
|
function normalize(value, mode) {
|
|
945
|
-
if (!value) {
|
|
946
|
-
return { type: 'all', rules: [] };
|
|
947
|
-
}
|
|
948
608
|
// Neither sentinel is a group, and wrapping one would rewrite the
|
|
949
609
|
// very shape the mode is read back from.
|
|
950
610
|
if (mode === 'always' || mode === 'never') {
|
|
951
611
|
return value;
|
|
952
612
|
}
|
|
953
|
-
if (
|
|
613
|
+
if (groupOf(value)) {
|
|
954
614
|
return value;
|
|
955
615
|
}
|
|
956
616
|
return { type: 'all', rules: [value] };
|
|
957
617
|
}
|
|
958
|
-
/**
|
|
959
|
-
* Treat an empty root `all`/`any` as "no rule". Mapping that back to
|
|
960
|
-
* `undefined` on emit keeps the form contract a clean
|
|
961
|
-
* `Rule | undefined` — callers don't have to inspect rule shape to
|
|
962
|
-
* tell "user cleared this" from "user has a real rule". A negated
|
|
963
|
-
* empty group (`not(all())` etc.) is left intact — vacuous either
|
|
964
|
-
* direction, but the user explicitly opted into the wrapper, so we
|
|
965
|
-
* don't second-guess.
|
|
966
|
-
* @param rule
|
|
967
|
-
*/
|
|
968
|
-
function collapseEmptyRoot(rule) {
|
|
969
|
-
if (rule.type !== 'all' && rule.type !== 'any') {
|
|
970
|
-
return rule;
|
|
971
|
-
}
|
|
972
|
-
return rule.rules.length === 0 ? undefined : rule;
|
|
973
|
-
}
|
|
974
618
|
RuleEditor.style = ruleEditorCss();
|
|
975
619
|
|
|
976
620
|
export { RuleEditor as limebb_rule_editor };
|