@limetech/lime-crm-building-blocks 2.3.0 → 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 +20 -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 +9 -4
- 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/chat-list/chat-list.js +7 -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-chat-list.js +1 -1
- 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 +9 -4
- 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-e7dee7ac.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
|
@@ -10,20 +10,30 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
10
10
|
};
|
|
11
11
|
import { Host, h, } from "@stencil/core";
|
|
12
12
|
import { PlatformServiceName, SelectContext, } from "@limetech/lime-web-components";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { createPrimitiveOptions, primitiveReadsCovered } from "./view-helpers";
|
|
13
|
+
import { createTranslator } from "../condition-tree/condition-tree-translate";
|
|
14
|
+
import { createRuleConditionTreeAdapter, groupOf, } from "./condition-tree-adapter";
|
|
15
|
+
import { collectRuleIssues } from "./rule-issues";
|
|
16
|
+
import { createPrimitiveOptions, createSearcher, primitiveReadsCovered, primitiveTitle, } from "./view-helpers";
|
|
17
|
+
// The adapter names the chip and the args editor by tag only, and a tag that
|
|
18
|
+
// appears solely as a string is not a dependency the compiler can see.
|
|
19
|
+
import "./rule-condition-chip/rule-condition-chip";
|
|
20
|
+
import "./rule-condition-editor/rule-condition-editor";
|
|
17
21
|
import { RuleModeView } from "./rule-editor-mode-view";
|
|
18
22
|
import { ALWAYS_PRIMITIVE_ID, ruleForMode, ruleMode, } from "./rule-editor-modes";
|
|
19
23
|
import { createRandomString } from "../../util/random-string";
|
|
20
24
|
/**
|
|
21
25
|
* Tree editor for {@link Rule}.
|
|
22
26
|
*
|
|
23
|
-
* Renders a `Rule` value as a tree
|
|
24
|
-
* primitive refs
|
|
25
|
-
*
|
|
26
|
-
* primitive's
|
|
27
|
+
* Renders a `Rule` value as a `limebb-condition-tree`. Lets an author
|
|
28
|
+
* add primitive refs to `all` / `any` groups and to the negations of
|
|
29
|
+
* those two, nest groups, negate a single ref, delete nodes, and edit
|
|
30
|
+
* per-primitive args via the editor declared on each primitive's
|
|
31
|
+
* metadata.
|
|
32
|
+
*
|
|
33
|
+
* The tree owns every structural edit, and knows nothing about rules. A
|
|
34
|
+
* `Rule` reaches it through an adapter — see `condition-tree-adapter.ts`
|
|
35
|
+
* — which is also where the group negation the rule model writes as a
|
|
36
|
+
* `not` wrapper is folded into the combinator the tree shows.
|
|
27
37
|
*
|
|
28
38
|
* The component is value-in / value-out. Pass `value` and listen for
|
|
29
39
|
* `change`; persistence is the caller's concern.
|
|
@@ -64,8 +74,6 @@ import { createRandomString } from "../../util/random-string";
|
|
|
64
74
|
*/
|
|
65
75
|
export class RuleEditor {
|
|
66
76
|
constructor() {
|
|
67
|
-
this.issues = [];
|
|
68
|
-
this.openChipPath = null;
|
|
69
77
|
/**
|
|
70
78
|
* The mode the author last clicked, held until `value` reads back
|
|
71
79
|
* as it.
|
|
@@ -76,10 +84,27 @@ export class RuleEditor {
|
|
|
76
84
|
* what the author just clicked.
|
|
77
85
|
*/
|
|
78
86
|
this.modeOverride = null;
|
|
79
|
-
this.focusOnOpen = false;
|
|
80
87
|
this.metadataById = new Map();
|
|
81
|
-
|
|
88
|
+
/**
|
|
89
|
+
* How each registered primitive reads, by id. Translated once here
|
|
90
|
+
* because the platform's translator parses the message afresh on
|
|
91
|
+
* every call, and the adapter would otherwise do that per condition,
|
|
92
|
+
* several times over, on every edit.
|
|
93
|
+
*/
|
|
94
|
+
this.primitiveTitles = new Map();
|
|
82
95
|
this.availablePrimitiveOptions = [];
|
|
96
|
+
this.searcher = createSearcher([]);
|
|
97
|
+
/**
|
|
98
|
+
* What validation found, by the node it belongs to.
|
|
99
|
+
*/
|
|
100
|
+
this.issuesByNode = new Map();
|
|
101
|
+
/**
|
|
102
|
+
* The conditions added here rather than loaded, which a `RuleRef`
|
|
103
|
+
* does not record. The adapter reads it to decide which condition
|
|
104
|
+
* opens itself. Replaced when the tree goes, since a condition still
|
|
105
|
+
* listed when the author comes back would open itself again.
|
|
106
|
+
*/
|
|
107
|
+
this.created = new WeakSet();
|
|
83
108
|
this.reachableSlots = new Set();
|
|
84
109
|
this.normalizedCache = null;
|
|
85
110
|
this.hasLoaded = false;
|
|
@@ -93,6 +118,9 @@ export class RuleEditor {
|
|
|
93
118
|
* conditions are gone, rather than handing back the ones they
|
|
94
119
|
* removed. With nothing stashed, `conditional` emits no rule, which
|
|
95
120
|
* is how the editor already says "the author cleared this".
|
|
121
|
+
*
|
|
122
|
+
* What is not stashed is which conditions had just been added, so
|
|
123
|
+
* that none of them opens itself again on the way back.
|
|
96
124
|
* @param mode
|
|
97
125
|
*/
|
|
98
126
|
this.handleModeChange = (mode) => {
|
|
@@ -100,32 +128,28 @@ export class RuleEditor {
|
|
|
100
128
|
if (this.currentMode === 'conditional') {
|
|
101
129
|
this.stashedTree = this.value;
|
|
102
130
|
}
|
|
131
|
+
if (mode !== 'conditional') {
|
|
132
|
+
this.created = new WeakSet();
|
|
133
|
+
}
|
|
103
134
|
this.modeOverride = mode;
|
|
104
135
|
this.change.emit((_a = ruleForMode(mode)) !== null && _a !== void 0 ? _a : this.stashedTree);
|
|
105
136
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
this.handleChipInteract = (path) => {
|
|
123
|
-
this.openChipPath = path;
|
|
124
|
-
this.focusOnOpen = false;
|
|
125
|
-
};
|
|
126
|
-
this.handlePopoverClose = () => {
|
|
127
|
-
this.openChipPath = null;
|
|
128
|
-
this.focusOnOpen = false;
|
|
137
|
+
/**
|
|
138
|
+
* Take in a tree the author changed. The tree reports `null` when
|
|
139
|
+
* the last condition goes, which for a rule means there is none —
|
|
140
|
+
* the same thing an emptied editor has always emitted.
|
|
141
|
+
*
|
|
142
|
+
* Editing the tree is only possible in `conditional`, so the edit
|
|
143
|
+
* itself records the mode: without this, a tree emptied to nothing
|
|
144
|
+
* would read back as the first offered mode and rewrite the setting
|
|
145
|
+
* under the author.
|
|
146
|
+
* @param event
|
|
147
|
+
*/
|
|
148
|
+
this.handleTreeChange = (event) => {
|
|
149
|
+
var _a;
|
|
150
|
+
event.stopPropagation();
|
|
151
|
+
this.modeOverride = 'conditional';
|
|
152
|
+
this.change.emit((_a = event.detail) !== null && _a !== void 0 ? _a : undefined);
|
|
129
153
|
};
|
|
130
154
|
}
|
|
131
155
|
componentWillLoad() {
|
|
@@ -136,6 +160,7 @@ export class RuleEditor {
|
|
|
136
160
|
this.indexMetadata();
|
|
137
161
|
this.rebuildAvailableOptions();
|
|
138
162
|
this.runValidation();
|
|
163
|
+
this.rebuildAdapter();
|
|
139
164
|
}
|
|
140
165
|
/**
|
|
141
166
|
* Re-walk reachable slots when the editor is re-attached to the DOM,
|
|
@@ -150,6 +175,7 @@ export class RuleEditor {
|
|
|
150
175
|
this.computeReachableSlots();
|
|
151
176
|
this.rebuildAvailableOptions();
|
|
152
177
|
this.runValidation();
|
|
178
|
+
this.rebuildAdapter();
|
|
153
179
|
}
|
|
154
180
|
componentDidLoad() {
|
|
155
181
|
this.hasLoaded = true;
|
|
@@ -166,7 +192,7 @@ export class RuleEditor {
|
|
|
166
192
|
this.rebuildFromRegistries();
|
|
167
193
|
}
|
|
168
194
|
render() {
|
|
169
|
-
return (h(Host, { key: '
|
|
195
|
+
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: {
|
|
170
196
|
'rule-editor': true,
|
|
171
197
|
'rule-editor--disabled': this.disabled,
|
|
172
198
|
}, role: "group", "aria-labelledby": this.label ? this.labelId : undefined, "aria-describedby": this.helperText ? this.helperTextId : undefined }, this.renderModes(), this.renderTree())), this.renderHelperLine()));
|
|
@@ -183,13 +209,18 @@ export class RuleEditor {
|
|
|
183
209
|
* The condition tree, shown unless a mode other than `conditional`
|
|
184
210
|
* is selected — an unconditional rule has no conditions to show.
|
|
185
211
|
* A caller offering no modes at all gets the tree, as before.
|
|
212
|
+
*
|
|
213
|
+
* An unset rule is handed over as unset, rather than as an empty
|
|
214
|
+
* group: the tree draws the group an author's first condition will
|
|
215
|
+
* land in, and drawing one here would only be a second opinion on
|
|
216
|
+
* what that looks like.
|
|
186
217
|
*/
|
|
187
218
|
renderTree() {
|
|
188
219
|
const mode = this.currentMode;
|
|
189
220
|
if (mode && mode !== 'conditional') {
|
|
190
221
|
return null;
|
|
191
222
|
}
|
|
192
|
-
return (h(
|
|
223
|
+
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 }));
|
|
193
224
|
}
|
|
194
225
|
renderHelperLine() {
|
|
195
226
|
if (!this.helperText) {
|
|
@@ -203,27 +234,6 @@ export class RuleEditor {
|
|
|
203
234
|
}
|
|
204
235
|
return h("limel-help", { value: this.help });
|
|
205
236
|
}
|
|
206
|
-
createRenderContext() {
|
|
207
|
-
return {
|
|
208
|
-
issues: this.issues,
|
|
209
|
-
metadataById: this.metadataById,
|
|
210
|
-
allPrimitiveOptions: this.allPrimitiveOptions,
|
|
211
|
-
availablePrimitiveOptions: this.availablePrimitiveOptions,
|
|
212
|
-
isMutable: !this.readonly && !this.disabled,
|
|
213
|
-
readonly: this.readonly,
|
|
214
|
-
disabled: this.disabled,
|
|
215
|
-
platform: this.platform,
|
|
216
|
-
context: this.effectiveContext,
|
|
217
|
-
translator: this.translator,
|
|
218
|
-
openChipPath: this.openChipPath,
|
|
219
|
-
focusOnOpen: this.focusOnOpen,
|
|
220
|
-
onDelete: this.handleDelete,
|
|
221
|
-
onUpdateArgs: this.handleUpdateArgs,
|
|
222
|
-
onReplaceNode: this.handleReplaceNode,
|
|
223
|
-
onChipInteract: this.handleChipInteract,
|
|
224
|
-
onPopoverClose: this.handlePopoverClose,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
237
|
/**
|
|
228
238
|
* The mode the editor is in, or `undefined` when it offers none —
|
|
229
239
|
* then it is the plain tree editor it was before modes existed.
|
|
@@ -257,51 +267,14 @@ export class RuleEditor {
|
|
|
257
267
|
this.modeOverride = null;
|
|
258
268
|
}
|
|
259
269
|
}
|
|
260
|
-
/**
|
|
261
|
-
* Path of a newly added chip whose primitive declares a config
|
|
262
|
-
* component, so its args editor opens immediately on add. The new
|
|
263
|
-
* ref is found by object identity — the picker reuses existing ref
|
|
264
|
-
* objects and only the added chip is a fresh node — so adding a
|
|
265
|
-
* second instance of a primitive already in the group is still
|
|
266
|
-
* detected. Returns `null` unless exactly one ref was added and it
|
|
267
|
-
* has an editor, leaving the open chip untouched for removals,
|
|
268
|
-
* multi-adds, and negation.
|
|
269
|
-
* @param path
|
|
270
|
-
* @param replacement
|
|
271
|
-
*/
|
|
272
|
-
autoOpenPathFor(path, replacement) {
|
|
273
|
-
var _a;
|
|
274
|
-
if (replacement.type !== 'all' && replacement.type !== 'any') {
|
|
275
|
-
return null;
|
|
276
|
-
}
|
|
277
|
-
const previous = getNode(this.normalizedValue, path);
|
|
278
|
-
if (previous === undefined ||
|
|
279
|
-
(previous.type !== 'all' && previous.type !== 'any')) {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
const previousRefs = new Set(previous.rules
|
|
283
|
-
.map((rule) => { var _a; return (_a = extractRef(rule)) === null || _a === void 0 ? void 0 : _a.ref; })
|
|
284
|
-
.filter((ref) => ref !== undefined));
|
|
285
|
-
const added = replacement.rules
|
|
286
|
-
.map((rule, index) => {
|
|
287
|
-
var _a;
|
|
288
|
-
const ref = (_a = extractRef(rule)) === null || _a === void 0 ? void 0 : _a.ref;
|
|
289
|
-
return ref && !previousRefs.has(ref) ? { ref, index } : null;
|
|
290
|
-
})
|
|
291
|
-
.filter((entry) => entry !== null);
|
|
292
|
-
if (added.length !== 1) {
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
const [{ ref, index }] = added;
|
|
296
|
-
return ((_a = this.metadataById.get(ref.id)) === null || _a === void 0 ? void 0 : _a.configComponent)
|
|
297
|
-
? buildChipPath(path, index)
|
|
298
|
-
: null;
|
|
299
|
-
}
|
|
300
270
|
indexMetadata() {
|
|
301
271
|
var _a, _b, _c;
|
|
302
272
|
const metadata = (_c = (_b = (_a = this.ruleRegistry).listMetadata) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : [];
|
|
303
273
|
this.metadataById = new Map(metadata.map((item) => [item.id, item]));
|
|
304
|
-
this.
|
|
274
|
+
this.primitiveTitles = new Map(metadata.map((item) => [
|
|
275
|
+
item.id,
|
|
276
|
+
primitiveTitle(item, this.translator),
|
|
277
|
+
]));
|
|
305
278
|
}
|
|
306
279
|
/**
|
|
307
280
|
* Recompute the cached add-palette options. The inputs — indexed
|
|
@@ -311,6 +284,7 @@ export class RuleEditor {
|
|
|
311
284
|
*/
|
|
312
285
|
rebuildAvailableOptions() {
|
|
313
286
|
this.availablePrimitiveOptions = createPrimitiveOptions(this.availablePrimitiveMetadata(), this.translator);
|
|
287
|
+
this.searcher = createSearcher(this.availablePrimitiveOptions);
|
|
314
288
|
}
|
|
315
289
|
/**
|
|
316
290
|
* The subset of registered metadata offered for adding in the
|
|
@@ -318,7 +292,7 @@ export class RuleEditor {
|
|
|
318
292
|
* reachable slots are dropped, and so is the always primitive —
|
|
319
293
|
* it reads nothing, so it is always covered, but an "Always" chip
|
|
320
294
|
* among a group's conditions says nothing. Filtering only the
|
|
321
|
-
* palette —
|
|
295
|
+
* palette — the adapter still reads the whole index — keeps
|
|
322
296
|
* already-placed chips resolving to their proper title even when
|
|
323
297
|
* their read slot isn't reachable.
|
|
324
298
|
*/
|
|
@@ -358,45 +332,81 @@ export class RuleEditor {
|
|
|
358
332
|
]);
|
|
359
333
|
}
|
|
360
334
|
runValidation() {
|
|
361
|
-
|
|
362
|
-
this.issues = [];
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const result = this.ruleRegistry.validate(this.normalizedValue, [
|
|
366
|
-
...this.reachableSlots,
|
|
367
|
-
]);
|
|
368
|
-
this.issues = result.ok ? [] : result.issues;
|
|
335
|
+
this.issuesByNode = this.findIssues();
|
|
369
336
|
}
|
|
370
337
|
/**
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
338
|
+
* What the registry finds wrong with the rule, gathered by the node
|
|
339
|
+
* each problem belongs to. Validation runs against the normalized
|
|
340
|
+
* rule, which is also what the tree is handed, so the paths the
|
|
341
|
+
* registry reports address the very nodes the tree draws.
|
|
342
|
+
*
|
|
343
|
+
* A rule the registry cannot even walk — one hand-edited into a shape
|
|
344
|
+
* that is not a rule — makes it throw rather than report. That is the
|
|
345
|
+
* rule an author most needs the editor for, so the throw is caught
|
|
346
|
+
* and the editor drawn anyway: the tree marks the offending condition
|
|
347
|
+
* unreadable itself, which is the same thing validation would have
|
|
348
|
+
* said and in the place it belongs.
|
|
376
349
|
*/
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
350
|
+
findIssues() {
|
|
351
|
+
const root = this.normalizedValue;
|
|
352
|
+
if (!root) {
|
|
353
|
+
return new Map();
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
const result = this.ruleRegistry.validate(root, [
|
|
357
|
+
...this.reachableSlots,
|
|
358
|
+
]);
|
|
359
|
+
return result.ok
|
|
360
|
+
? new Map()
|
|
361
|
+
: collectRuleIssues(root, result.issues);
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
// The throw names the node it choked on. What the author needs is
|
|
365
|
+
// already in the tree; this is what tells a developer an unreadable
|
|
366
|
+
// rule from a registry that could not answer for a readable one.
|
|
367
|
+
console.warn('rule-editor could not validate the rule', {
|
|
368
|
+
rule: root,
|
|
369
|
+
error,
|
|
370
|
+
});
|
|
371
|
+
return new Map();
|
|
380
372
|
}
|
|
381
|
-
this.modeOverride = 'conditional';
|
|
382
|
-
this.change.emit(collapseEmptyRoot(next));
|
|
383
373
|
}
|
|
384
374
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
375
|
+
* Gather what the tree draws from into a new adapter, which is how a
|
|
376
|
+
* change the rule does not carry reaches the screen at all.
|
|
377
|
+
*
|
|
378
|
+
* Not rebuilt for a validation pass: that runs because the rule
|
|
379
|
+
* changed, and the tree is already redrawing for the same reason.
|
|
380
|
+
* Rebuilding there would sync its open state twice for one edit.
|
|
381
|
+
*/
|
|
382
|
+
rebuildAdapter() {
|
|
383
|
+
this.adapter = createRuleConditionTreeAdapter({
|
|
384
|
+
metadata: this.metadataById,
|
|
385
|
+
titles: this.primitiveTitles,
|
|
386
|
+
translate: createTranslator(this.platform),
|
|
387
|
+
issues: () => this.issuesByNode,
|
|
388
|
+
created: () => this.created,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Wrap any non-group `value` in a top-level `all`, so that a lone
|
|
393
|
+
* condition has a group to grow in. An unset value stays unset: the
|
|
394
|
+
* tree draws the group a first condition will land in, and
|
|
395
|
+
* `emitNormalization` never pushes that placeholder back to the
|
|
396
|
+
* caller, so "no rule yet" stays distinguishable from "the author
|
|
397
|
+
* cleared this".
|
|
390
398
|
*
|
|
391
399
|
* An unconditional mode is the exception: its sentinel is left
|
|
392
400
|
* exactly as it came in, because wrapping it would rewrite the
|
|
393
401
|
* shape the mode is read back from.
|
|
394
402
|
*
|
|
395
|
-
* Memoized so
|
|
396
|
-
*
|
|
397
|
-
* depends on it.
|
|
403
|
+
* Memoized, so that the tree is handed the same rule on every
|
|
404
|
+
* render and redraws only when the rule itself changes.
|
|
398
405
|
*/
|
|
399
406
|
get normalizedValue() {
|
|
407
|
+
if (!this.value) {
|
|
408
|
+
return undefined;
|
|
409
|
+
}
|
|
400
410
|
const mode = this.currentMode;
|
|
401
411
|
if (this.normalizedCache !== null &&
|
|
402
412
|
this.normalizedCache.source === this.value &&
|
|
@@ -529,7 +539,7 @@ export class RuleEditor {
|
|
|
529
539
|
"name": "inheritdoc",
|
|
530
540
|
"text": undefined
|
|
531
541
|
}],
|
|
532
|
-
"text": "The value of the current property"
|
|
542
|
+
"text": "The value of the current property\nThe rule under edit. Hand back what `change` emitted, not a copy:\nwhich condition is open, which have been visited and what\nvalidation said about each are all tracked by object identity, so\na deep-cloned rule reads as a different one that happens to look\nthe same."
|
|
533
543
|
},
|
|
534
544
|
"getter": false,
|
|
535
545
|
"setter": false
|
|
@@ -619,7 +629,7 @@ export class RuleEditor {
|
|
|
619
629
|
"name": "inheritdoc",
|
|
620
630
|
"text": undefined
|
|
621
631
|
}],
|
|
622
|
-
"text": "Whether or not the current property is readonly\nThe
|
|
632
|
+
"text": "Whether or not the current property is readonly\nThe controls that add, delete and negate are not rendered when set,\nleaving the rule to be read. The args editor for each ref is still\nrendered, with `readonly` forwarded to it."
|
|
623
633
|
},
|
|
624
634
|
"getter": false,
|
|
625
635
|
"setter": false,
|
|
@@ -641,7 +651,7 @@ export class RuleEditor {
|
|
|
641
651
|
"name": "inheritdoc",
|
|
642
652
|
"text": undefined
|
|
643
653
|
}],
|
|
644
|
-
"text": "Whether or not the current property is disabled\
|
|
654
|
+
"text": "Whether or not the current property is disabled\nEvery control stays where it is, dimmed and inert, when set. The\nargs editor is rendered with `disabled` forwarded to it."
|
|
645
655
|
},
|
|
646
656
|
"getter": false,
|
|
647
657
|
"setter": false,
|
|
@@ -735,10 +745,9 @@ export class RuleEditor {
|
|
|
735
745
|
static get states() {
|
|
736
746
|
return {
|
|
737
747
|
"resolvedContext": {},
|
|
738
|
-
"issues": {},
|
|
739
|
-
"openChipPath": {},
|
|
740
748
|
"modeOverride": {},
|
|
741
|
-
"availablePrimitiveOptions": {}
|
|
749
|
+
"availablePrimitiveOptions": {},
|
|
750
|
+
"adapter": {}
|
|
742
751
|
};
|
|
743
752
|
}
|
|
744
753
|
static get events() {
|
|
@@ -750,7 +759,7 @@ export class RuleEditor {
|
|
|
750
759
|
"composed": true,
|
|
751
760
|
"docs": {
|
|
752
761
|
"tags": [],
|
|
753
|
-
"text": "
|
|
762
|
+
"text": "The edited rule, or nothing when the author has cleared it.\n\nWhat comes out is what should go back in as `value` \u2014 see the note\nthere on why the objects themselves matter."
|
|
754
763
|
},
|
|
755
764
|
"complexType": {
|
|
756
765
|
"original": "Rule | undefined",
|
|
@@ -785,32 +794,13 @@ const EMPTY_CONTEXT = Object.freeze({
|
|
|
785
794
|
id: null,
|
|
786
795
|
});
|
|
787
796
|
function normalize(value, mode) {
|
|
788
|
-
if (!value) {
|
|
789
|
-
return { type: 'all', rules: [] };
|
|
790
|
-
}
|
|
791
797
|
// Neither sentinel is a group, and wrapping one would rewrite the
|
|
792
798
|
// very shape the mode is read back from.
|
|
793
799
|
if (mode === 'always' || mode === 'never') {
|
|
794
800
|
return value;
|
|
795
801
|
}
|
|
796
|
-
if (
|
|
802
|
+
if (groupOf(value)) {
|
|
797
803
|
return value;
|
|
798
804
|
}
|
|
799
805
|
return { type: 'all', rules: [value] };
|
|
800
806
|
}
|
|
801
|
-
/**
|
|
802
|
-
* Treat an empty root `all`/`any` as "no rule". Mapping that back to
|
|
803
|
-
* `undefined` on emit keeps the form contract a clean
|
|
804
|
-
* `Rule | undefined` — callers don't have to inspect rule shape to
|
|
805
|
-
* tell "user cleared this" from "user has a real rule". A negated
|
|
806
|
-
* empty group (`not(all())` etc.) is left intact — vacuous either
|
|
807
|
-
* direction, but the user explicitly opted into the wrapper, so we
|
|
808
|
-
* don't second-guess.
|
|
809
|
-
* @param rule
|
|
810
|
-
*/
|
|
811
|
-
function collapseEmptyRoot(rule) {
|
|
812
|
-
if (rule.type !== 'all' && rule.type !== 'any') {
|
|
813
|
-
return rule;
|
|
814
|
-
}
|
|
815
|
-
return rule.rules.length === 0 ? undefined : rule;
|
|
816
|
-
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The problems the registry found, gathered by the node each belongs to.
|
|
3
|
+
*
|
|
4
|
+
* The registry addresses an issue by path — `['rules', 0, 'rule']` for
|
|
5
|
+
* `root.rules[0].rule` — while the tree asks about one node at a time and never
|
|
6
|
+
* says where it is. Resolving the paths once, here, bridges the two.
|
|
7
|
+
* @param root
|
|
8
|
+
* @param issues
|
|
9
|
+
*/
|
|
10
|
+
export function collectRuleIssues(root, issues) {
|
|
11
|
+
var _a, _b;
|
|
12
|
+
const owners = displayOwners(root);
|
|
13
|
+
const byNode = new Map();
|
|
14
|
+
for (const issue of issues) {
|
|
15
|
+
const node = nodeAt(root, issue.path);
|
|
16
|
+
// An empty path means the rule as a whole, and one the path cannot
|
|
17
|
+
// reach has nowhere better to go than the root either.
|
|
18
|
+
const owner = (_a = (node && owners.get(node))) !== null && _a !== void 0 ? _a : root;
|
|
19
|
+
byNode.set(owner, [...((_b = byNode.get(owner)) !== null && _b !== void 0 ? _b : []), issue.message]);
|
|
20
|
+
}
|
|
21
|
+
return byNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Which node each node is drawn as part of. Most stand for themselves; the
|
|
25
|
+
* exception is everything under a `not`, which is drawn as that `not` — the
|
|
26
|
+
* two are one thing on screen, and only the wrapper has somewhere to show it.
|
|
27
|
+
* @param root
|
|
28
|
+
*/
|
|
29
|
+
function displayOwners(root) {
|
|
30
|
+
const owners = new Map();
|
|
31
|
+
const visit = (node, owner) => {
|
|
32
|
+
// A hand-edited rule can hold a `null` where a node should be. It is
|
|
33
|
+
// drawn, as something that cannot be read, so it is walked past here.
|
|
34
|
+
if (typeof node !== 'object' || node === null) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
owners.set(node, owner);
|
|
38
|
+
if (node.type === 'not') {
|
|
39
|
+
visit(node.rule, owner);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if ((node.type === 'all' || node.type === 'any') &&
|
|
43
|
+
Array.isArray(node.rules)) {
|
|
44
|
+
for (const child of node.rules) {
|
|
45
|
+
visit(child, child);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
visit(root, root);
|
|
50
|
+
return owners;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The node a validation path addresses, or nothing when it addresses none.
|
|
54
|
+
*
|
|
55
|
+
* Walked one hop at a time because the two the registry emits have different
|
|
56
|
+
* shapes: into a negation is the single segment `rule`, into the *n*-th child
|
|
57
|
+
* of a group is the pair `rules`, *n*. Anything else is not a path this rule
|
|
58
|
+
* can be walked by.
|
|
59
|
+
* @param root
|
|
60
|
+
* @param path
|
|
61
|
+
*/
|
|
62
|
+
function nodeAt(root, path) {
|
|
63
|
+
let node = root;
|
|
64
|
+
let index = 0;
|
|
65
|
+
while (index < path.length) {
|
|
66
|
+
// The same `null` can be standing one hop short of the path's end,
|
|
67
|
+
// with no hop to take from it. Asked for `type`, it would throw.
|
|
68
|
+
if (node === null || typeof node !== 'object') {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const key = path[index];
|
|
72
|
+
if (key === 'rule' && node.type === 'not') {
|
|
73
|
+
node = node.rule;
|
|
74
|
+
index += 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const child = path[index + 1];
|
|
78
|
+
if (key === 'rules' &&
|
|
79
|
+
(node.type === 'all' || node.type === 'any') &&
|
|
80
|
+
Array.isArray(node.rules) &&
|
|
81
|
+
typeof child === 'number') {
|
|
82
|
+
node = node.rules[child];
|
|
83
|
+
index += 2;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return node;
|
|
89
|
+
}
|
|
@@ -1,26 +1,7 @@
|
|
|
1
|
-
const UNKNOWN_ICON = {
|
|
2
|
-
name: 'question',
|
|
3
|
-
color: 'rgb(var(--color-glaucous-light))',
|
|
4
|
-
};
|
|
5
1
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @param issues
|
|
10
|
-
*/
|
|
11
|
-
export function nodeClasses(type, issues) {
|
|
12
|
-
return {
|
|
13
|
-
'rule-node': true,
|
|
14
|
-
[`rule-node--${type}`]: true,
|
|
15
|
-
'rule-node--invalid': issues.length > 0,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Build the searchable list shown by the primitive pickers. Cached on
|
|
20
|
-
* the render context so it isn't recomputed per node. `meta.title` and
|
|
21
|
-
* `meta.description` are passed through the translator so callers can
|
|
22
|
-
* register translation keys as metadata — plain strings travel through
|
|
23
|
-
* unchanged.
|
|
2
|
+
* The primitives the add button offers. Titles and descriptions go through the
|
|
3
|
+
* translator, so a caller can register translation keys as metadata — plain
|
|
4
|
+
* strings travel through unchanged.
|
|
24
5
|
* @param metadataById
|
|
25
6
|
* @param translator
|
|
26
7
|
*/
|
|
@@ -28,7 +9,7 @@ export function createPrimitiveOptions(metadataById, translator) {
|
|
|
28
9
|
return [...metadataById.values()]
|
|
29
10
|
.map((meta) => ({
|
|
30
11
|
value: meta.id,
|
|
31
|
-
text: meta
|
|
12
|
+
text: primitiveTitle(meta, translator),
|
|
32
13
|
secondaryText: meta.description
|
|
33
14
|
? translator.get(meta.description)
|
|
34
15
|
: '',
|
|
@@ -36,6 +17,15 @@ export function createPrimitiveOptions(metadataById, translator) {
|
|
|
36
17
|
}))
|
|
37
18
|
.sort((a, b) => a.text.localeCompare(b.text));
|
|
38
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* How a primitive reads: its translated title, or its bare id when it has none
|
|
22
|
+
* to give. The add menu and the chip both read it from here, so they agree.
|
|
23
|
+
* @param meta
|
|
24
|
+
* @param translator
|
|
25
|
+
*/
|
|
26
|
+
export function primitiveTitle(meta, translator) {
|
|
27
|
+
return meta.title ? translator.get(meta.title) : meta.id;
|
|
28
|
+
}
|
|
39
29
|
/**
|
|
40
30
|
* Whether every context key a primitive reads is in the reachable set.
|
|
41
31
|
* A primitive that reads nothing is always covered.
|
|
@@ -46,23 +36,9 @@ export function primitiveReadsCovered(meta, reachable) {
|
|
|
46
36
|
return meta.reads.every((key) => reachable.has(key));
|
|
47
37
|
}
|
|
48
38
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* @param id
|
|
53
|
-
*/
|
|
54
|
-
export function resolveItem(allItems, id) {
|
|
55
|
-
var _a;
|
|
56
|
-
return ((_a = allItems.find((item) => item.value === id)) !== null && _a !== void 0 ? _a : {
|
|
57
|
-
value: id,
|
|
58
|
-
text: id,
|
|
59
|
-
icon: UNKNOWN_ICON,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Build a picker `searcher` bound to a fixed item list. Both the ref
|
|
64
|
-
* picker and the chip picker want exactly this — wrapping
|
|
65
|
-
* {@link searchItems} in a promise — and deserve to share it.
|
|
39
|
+
* Narrow the primitives as the user types, for the search field at the top of
|
|
40
|
+
* the add menu. Every word has to match somewhere — title, description or id —
|
|
41
|
+
* so that "deal won" finds "Won deals".
|
|
66
42
|
* @param items
|
|
67
43
|
*/
|
|
68
44
|
export function createSearcher(items) {
|
|
@@ -77,6 +53,8 @@ function searchItems(allItems, query) {
|
|
|
77
53
|
var _a, _b;
|
|
78
54
|
return item.text.toLocaleLowerCase().includes(part) ||
|
|
79
55
|
((_a = item.secondaryText) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase().includes(part)) ||
|
|
80
|
-
((_b = item.value)
|
|
56
|
+
String((_b = item.value) !== null && _b !== void 0 ? _b : '')
|
|
57
|
+
.toLocaleLowerCase()
|
|
58
|
+
.includes(part);
|
|
81
59
|
}));
|
|
82
60
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const n={all:{type:"all",negated:!1},any:{type:"any",negated:!1},"not-all":{type:"all",negated:!0},none:{type:"any",negated:!0}},e={all:"not-all",any:"none","not-all":"all",none:"any"};function t(n){return{describe:(e,t)=>function(n,e,t){const r=t.issues().get(n),d=o(n);if(d)return{kind:"group",combinator:d.combinator,children:d.rules,issues:r};const f=i(n);return f?function(n,e,t,o){const{ref:i,negated:r}=n,l=t.metadata.get(i.id),d=t.created().has(i),f=null==l?void 0:l.configComponent;return{kind:"leaf",chip:{label:u(i,t),icon:a(l),invalid:!l||!!(null==o?void 0:o.length),component:{name:"limebb-rule-condition-chip",props:{negated:r,iconColor:c(l)}}},negated:r,issues:o,autoOpen:d&&!!f,editor:f&&{name:"limebb-rule-condition-editor",props:{configComponent:f,focusOnOpen:d&&!e.visited}}}}(f,e,t,r):function(n,e,t){var o;return{kind:"leaf",chip:{label:null!==(o=l(n))&&void 0!==o?o:"…",icon:"question",invalid:!0,component:{name:"limebb-rule-condition-chip"}},issues:(null==t?void 0:t.length)?t:[e.translate("webclient.rule-editor.unreadable-condition","This condition cannot be read, and so cannot be edited here.")]}}(n,t,r)}(e,t,n),group:d,negate:f,createLeaf:e=>{var t;const o={type:"ref",id:String(null!==(t=null==e?void 0:e.value)&&void 0!==t?t:"")};return n.created().add(o),o}}}function o(n){if(!r(n))return;if("all"===n.type||"any"===n.type)return Array.isArray(n.rules)?{combinator:n.type,rules:n.rules}:void 0;if("not"!==n.type)return;const t=o(n.rule);return t?{combinator:e[t.combinator],rules:t.rules}:void 0}function i(n){if(r(n))return"ref"===n.type?{ref:n,negated:!1}:"not"===n.type&&r(n.rule)&&"ref"===n.rule.type?{ref:n.rule,negated:!0}:void 0}function r(n){return"object"==typeof n&&null!==n}function u(n,e){return e.titles.get(n.id)||n.id||"…"}function l(n){if(!r(n))return;const e=n.type;return"string"==typeof e&&e?e:void 0}function a(n){return n?n.icon?"string"==typeof n.icon?n.icon:n.icon.name:void 0:"question"}function c(n){return"object"==typeof(null==n?void 0:n.icon)?n.icon.color:void 0}function d(e,t){const o={type:n[e].type,rules:[...t]};return n[e].negated?{type:"not",rule:o}:o}function f(n,e){return e?"not"===n.type?n:{type:"not",rule:n}:"not"===n.type?n.rule:n}export{t as c,o as g,i as r}
|