@supersoniks/concorde 4.9.98-visual-stack.1 → 4.9.98-visual-stack.3
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/.gitlab-ci.yml +0 -13
- package/build-infos.json +1 -1
- package/concorde-3d.bundle.js +1 -1
- package/concorde-3d.es.js +2 -2
- package/concorde-core.bundle.js +557 -622
- package/concorde-core.es.js +6025 -5575
- package/concorde-hugging-face-infer.bundle.js +1 -1
- package/concorde-hugging-face-infer.es.js +1 -1
- package/concorde-interactive.bundle.js +1162 -0
- package/concorde-interactive.es.js +10723 -0
- package/concorde-shader.bundle.js +1 -1
- package/concorde-shader.es.js +2 -2
- package/concorde-webgpu.bundle.js +1 -1
- package/concorde-webgpu.es.js +2 -2
- package/dist/concorde-3d.bundle.js +1 -1
- package/dist/concorde-3d.es.js +2 -2
- package/dist/concorde-core.bundle.js +557 -622
- package/dist/concorde-core.es.js +6025 -5575
- package/dist/concorde-hugging-face-infer.bundle.js +1 -1
- package/dist/concorde-hugging-face-infer.es.js +1 -1
- package/dist/concorde-interactive.bundle.js +1162 -0
- package/dist/concorde-interactive.es.js +10723 -0
- package/dist/concorde-shader.bundle.js +1 -1
- package/dist/concorde-shader.es.js +2 -2
- package/dist/concorde-webgpu.bundle.js +1 -1
- package/dist/concorde-webgpu.es.js +2 -2
- package/dist/docs-mock-api-sw.js +5 -1
- package/dist/docs-mock-api-sw.js.map +2 -2
- package/dist/js/addons/interactive.js +6 -0
- package/dist/js/addons/interactive.js.map +1 -0
- package/dist/js/core/components/functional/if/if.js +65 -7
- package/dist/js/core/components/functional/if/if.js.map +1 -1
- package/dist/js/core/components/functional/interactive/action.js +96 -0
- package/dist/js/core/components/functional/interactive/action.js.map +1 -0
- package/dist/js/core/components/functional/interactive/gamepad.js +206 -0
- package/dist/js/core/components/functional/interactive/gamepad.js.map +1 -0
- package/dist/js/core/components/functional/interactive/gesture.js +148 -0
- package/dist/js/core/components/functional/interactive/gesture.js.map +1 -0
- package/dist/js/core/components/functional/interactive/helpers.js +82 -0
- package/dist/js/core/components/functional/interactive/helpers.js.map +1 -0
- package/dist/js/core/components/functional/interactive/index.js +20 -0
- package/dist/js/core/components/functional/interactive/index.js.map +1 -0
- package/dist/js/core/components/functional/interactive/keyboard.js +183 -0
- package/dist/js/core/components/functional/interactive/keyboard.js.map +1 -0
- package/dist/js/core/components/functional/interactive/matrix.js +201 -0
- package/dist/js/core/components/functional/interactive/matrix.js.map +1 -0
- package/dist/js/core/components/functional/interactive/registry.js +28 -0
- package/dist/js/core/components/functional/interactive/registry.js.map +1 -0
- package/dist/js/core/components/functional/interactive/store.js +264 -0
- package/dist/js/core/components/functional/interactive/store.js.map +1 -0
- package/dist/js/core/components/functional/interactive/ticker.js +182 -0
- package/dist/js/core/components/functional/interactive/ticker.js.map +1 -0
- package/dist/js/core/components/functional/value/value.js +49 -4
- package/dist/js/core/components/functional/value/value.js.map +1 -1
- package/dist/js/core/components/ui/_css/rounded.js +34 -0
- package/dist/js/core/components/ui/_css/rounded.js.map +1 -0
- package/dist/js/core/components/ui/_css/type.js +44 -0
- package/dist/js/core/components/ui/_css/type.js.map +1 -1
- package/dist/js/core/components/ui/_i18n/ui-aria-labels.js +95 -0
- package/dist/js/core/components/ui/_i18n/ui-aria-labels.js.map +1 -0
- package/dist/js/core/components/ui/alert/alert.js +72 -87
- package/dist/js/core/components/ui/alert/alert.js.map +1 -1
- package/dist/js/core/components/ui/alert-messages/alert-messages.js +1 -0
- package/dist/js/core/components/ui/alert-messages/alert-messages.js.map +1 -1
- package/dist/js/core/components/ui/badge/badge.js +29 -80
- package/dist/js/core/components/ui/badge/badge.js.map +1 -1
- package/dist/js/core/components/ui/button/button.js +8 -7
- package/dist/js/core/components/ui/button/button.js.map +1 -1
- package/dist/js/core/components/ui/card/card-header.js +7 -2
- package/dist/js/core/components/ui/card/card-header.js.map +1 -1
- package/dist/js/core/components/ui/divider/divider.js +1 -1
- package/dist/js/core/components/ui/divider/divider.js.map +1 -1
- package/dist/js/core/components/ui/form/checkbox/checkbox.js +4 -20
- package/dist/js/core/components/ui/form/checkbox/checkbox.js.map +1 -1
- package/dist/js/core/components/ui/form/fieldset/legend-description.js +1 -1
- package/dist/js/core/components/ui/form/fieldset/legend.js +1 -1
- package/dist/js/core/components/ui/form/input/input.js +12 -15
- package/dist/js/core/components/ui/form/input/input.js.map +1 -1
- package/dist/js/core/components/ui/form/input-autocomplete/input-autocomplete.js +363 -158
- package/dist/js/core/components/ui/form/input-autocomplete/input-autocomplete.js.map +1 -1
- package/dist/js/core/components/ui/form/radio/radio.js +1 -1
- package/dist/js/core/components/ui/form/select/select.js +3 -6
- package/dist/js/core/components/ui/form/select/select.js.map +1 -1
- package/dist/js/core/components/ui/form/textarea/textarea.js +1 -2
- package/dist/js/core/components/ui/form/textarea/textarea.js.map +1 -1
- package/dist/js/core/components/ui/image/image.js +9 -37
- package/dist/js/core/components/ui/image/image.js.map +1 -1
- package/dist/js/core/components/ui/link/link.js +25 -26
- package/dist/js/core/components/ui/link/link.js.map +1 -1
- package/dist/js/core/components/ui/modal/modal-close.js +3 -12
- package/dist/js/core/components/ui/modal/modal-close.js.map +1 -1
- package/dist/js/core/components/ui/modal/modal.js +18 -18
- package/dist/js/core/components/ui/modal/modal.js.map +1 -1
- package/dist/js/core/components/ui/pop/pop.js +131 -112
- package/dist/js/core/components/ui/pop/pop.js.map +1 -1
- package/dist/js/core/components/ui/table/table.js.map +1 -1
- package/dist/js/core/components/ui/theme/theme.js +1 -1
- package/dist/js/core/components/ui/toast/dismissed.js +9 -0
- package/dist/js/core/components/ui/toast/dismissed.js.map +1 -0
- package/dist/js/core/components/ui/toast/render-content.js +14 -0
- package/dist/js/core/components/ui/toast/render-content.js.map +1 -0
- package/dist/js/core/components/ui/toast/toast-item.js +150 -96
- package/dist/js/core/components/ui/toast/toast-item.js.map +1 -1
- package/dist/js/core/components/ui/toast/toast.js +41 -13
- package/dist/js/core/components/ui/toast/toast.js.map +1 -1
- package/dist/js/core/components/ui/tooltip/tooltip.js +144 -143
- package/dist/js/core/components/ui/tooltip/tooltip.js.map +1 -1
- package/dist/js/core/decorators/subscriber/ancestorAttribute.js.map +1 -1
- package/dist/js/core/decorators/subscriber/derive.js +3 -1
- package/dist/js/core/decorators/subscriber/derive.js.map +1 -1
- package/dist/js/core/mixins/Fetcher.js.map +1 -1
- package/dist/js/core/mixins/FormCheckable.js +1 -8
- package/dist/js/core/mixins/FormCheckable.js.map +1 -1
- package/dist/js/core/mixins/FormElement.js +26 -53
- package/dist/js/core/mixins/FormElement.js.map +1 -1
- package/dist/js/core/utils/AncestorAttributeObserver.js +130 -55
- package/dist/js/core/utils/AncestorAttributeObserver.js.map +1 -1
- package/dist/js/core/utils/LocationHandler.js +1 -1
- package/dist/js/core/utils/LocationHandler.js.map +1 -1
- package/dist/js/core/utils/dismissed.js +23 -0
- package/dist/js/core/utils/dismissed.js.map +1 -0
- package/dist/js/core/utils/positioning.js +110 -0
- package/dist/js/core/utils/positioning.js.map +1 -0
- package/dist/js/directives.js +1 -2
- package/dist/js/directives.js.map +1 -1
- package/dist/types/addons/interactive.d.ts +6 -0
- package/dist/types/addons/interactive.d.ts.map +1 -0
- package/dist/types/core/components/functional/if/if.d.ts +14 -5
- package/dist/types/core/components/functional/if/if.d.ts.map +1 -1
- package/dist/types/core/components/functional/interactive/action.d.ts +22 -0
- package/dist/types/core/components/functional/interactive/action.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/gamepad.d.ts +37 -0
- package/dist/types/core/components/functional/interactive/gamepad.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/gesture.d.ts +26 -0
- package/dist/types/core/components/functional/interactive/gesture.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/helpers.d.ts +23 -0
- package/dist/types/core/components/functional/interactive/helpers.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/index.d.ts +20 -0
- package/dist/types/core/components/functional/interactive/index.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/keyboard.d.ts +37 -0
- package/dist/types/core/components/functional/interactive/keyboard.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/matrix.d.ts +31 -0
- package/dist/types/core/components/functional/interactive/matrix.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/registry.d.ts +23 -0
- package/dist/types/core/components/functional/interactive/registry.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/store.d.ts +46 -0
- package/dist/types/core/components/functional/interactive/store.d.ts.map +1 -0
- package/dist/types/core/components/functional/interactive/ticker.d.ts +33 -0
- package/dist/types/core/components/functional/interactive/ticker.d.ts.map +1 -0
- package/dist/types/core/components/functional/value/value.d.ts +6 -0
- package/dist/types/core/components/functional/value/value.d.ts.map +1 -1
- package/dist/types/core/components/ui/_css/rounded.d.ts +3 -0
- package/dist/types/core/components/ui/_css/rounded.d.ts.map +1 -0
- package/dist/types/core/components/ui/_css/type.d.ts +13 -0
- package/dist/types/core/components/ui/_css/type.d.ts.map +1 -1
- package/dist/types/core/components/ui/_i18n/ui-aria-labels.d.ts +83 -0
- package/dist/types/core/components/ui/_i18n/ui-aria-labels.d.ts.map +1 -0
- package/dist/types/core/components/ui/alert/alert.d.ts +14 -12
- package/dist/types/core/components/ui/alert/alert.d.ts.map +1 -1
- package/dist/types/core/components/ui/alert-messages/alert-messages.d.ts.map +1 -1
- package/dist/types/core/components/ui/badge/badge.d.ts +1 -1
- package/dist/types/core/components/ui/badge/badge.d.ts.map +1 -1
- package/dist/types/core/components/ui/button/button.d.ts +13 -29
- package/dist/types/core/components/ui/button/button.d.ts.map +1 -1
- package/dist/types/core/components/ui/card/card-header.d.ts.map +1 -1
- package/dist/types/core/components/ui/divider/divider.d.ts +2 -1
- package/dist/types/core/components/ui/divider/divider.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/checkbox/checkbox.d.ts +25 -73
- package/dist/types/core/components/ui/form/checkbox/checkbox.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/input/input.d.ts +14 -29
- package/dist/types/core/components/ui/form/input/input.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/input-autocomplete/input-autocomplete.d.ts +63 -65
- package/dist/types/core/components/ui/form/input-autocomplete/input-autocomplete.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/radio/radio.d.ts +1 -1
- package/dist/types/core/components/ui/form/select/select.d.ts +3 -5
- package/dist/types/core/components/ui/form/select/select.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/textarea/textarea.d.ts +12 -28
- package/dist/types/core/components/ui/form/textarea/textarea.d.ts.map +1 -1
- package/dist/types/core/components/ui/image/image.d.ts +2 -1
- package/dist/types/core/components/ui/image/image.d.ts.map +1 -1
- package/dist/types/core/components/ui/link/link.d.ts +10 -9
- package/dist/types/core/components/ui/link/link.d.ts.map +1 -1
- package/dist/types/core/components/ui/modal/modal-close.d.ts +2 -2
- package/dist/types/core/components/ui/modal/modal-close.d.ts.map +1 -1
- package/dist/types/core/components/ui/pop/pop.d.ts +12 -4
- package/dist/types/core/components/ui/pop/pop.d.ts.map +1 -1
- package/dist/types/core/components/ui/table/table.d.ts +2 -1
- package/dist/types/core/components/ui/table/table.d.ts.map +1 -1
- package/dist/types/core/components/ui/toast/dismissed.d.ts +3 -0
- package/dist/types/core/components/ui/toast/dismissed.d.ts.map +1 -0
- package/dist/types/core/components/ui/toast/render-content.d.ts +7 -0
- package/dist/types/core/components/ui/toast/render-content.d.ts.map +1 -0
- package/dist/types/core/components/ui/toast/toast-item.d.ts +26 -9
- package/dist/types/core/components/ui/toast/toast-item.d.ts.map +1 -1
- package/dist/types/core/components/ui/toast/toast.d.ts +6 -3
- package/dist/types/core/components/ui/toast/toast.d.ts.map +1 -1
- package/dist/types/core/components/ui/toast/types.d.ts +12 -2
- package/dist/types/core/components/ui/toast/types.d.ts.map +1 -1
- package/dist/types/core/components/ui/tooltip/tooltip.d.ts +19 -11
- package/dist/types/core/components/ui/tooltip/tooltip.d.ts.map +1 -1
- package/dist/types/core/decorators/subscriber/ancestorAttribute.d.ts +3 -4
- package/dist/types/core/decorators/subscriber/ancestorAttribute.d.ts.map +1 -1
- package/dist/types/core/decorators/subscriber/derive.d.ts.map +1 -1
- package/dist/types/core/mixins/FormCheckable.d.ts +10 -27
- package/dist/types/core/mixins/FormCheckable.d.ts.map +1 -1
- package/dist/types/core/mixins/FormElement.d.ts +21 -10
- package/dist/types/core/mixins/FormElement.d.ts.map +1 -1
- package/dist/types/core/mixins/FormInput.d.ts +11 -27
- package/dist/types/core/mixins/FormInput.d.ts.map +1 -1
- package/dist/types/core/utils/AncestorAttributeObserver.d.ts +17 -9
- package/dist/types/core/utils/AncestorAttributeObserver.d.ts.map +1 -1
- package/dist/types/core/utils/LocationHandler.d.ts +3 -2
- package/dist/types/core/utils/LocationHandler.d.ts.map +1 -1
- package/dist/types/core/utils/dismissed.d.ts +3 -0
- package/dist/types/core/utils/dismissed.d.ts.map +1 -0
- package/dist/types/core/utils/positioning.d.ts +44 -0
- package/dist/types/core/utils/positioning.d.ts.map +1 -0
- package/dist/types/directives.d.ts +1 -3
- package/dist/types/directives.d.ts.map +1 -1
- package/dist/types/mixins.d.ts +22 -55
- package/dist/types/mixins.d.ts.map +1 -1
- package/docs/assets/{index-FmK4JaIM.js → index-D8MVWqY6.js} +946 -687
- package/docs/assets/index-DiD0qYvE.css +1 -0
- package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +17 -85
- package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +1 -1
- package/docs/crawl/hubs/form-components.html +13 -11
- package/docs/docs-mock-api-sw.js +5 -1
- package/docs/docs-mock-api-sw.js.map +2 -2
- package/docs/index.html +2 -2
- package/docs/llms-full.txt +12 -38
- package/docs/llms.txt +1 -1
- package/docs/src/core/components/functional/sdui/sdui.md +0 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +0 -0
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +14 -118
- package/docs/src/docs/_getting-started/create-a-component.md +0 -0
- package/docs/src/docs/_misc/formelement-subscriber-removal.md +1 -1
- package/docs/src/docs/search/docs-search.json +195 -200
- package/docs/src/tsconfig.json +324 -0
- package/gitlab/job_tests.sh +25 -12
- package/index.html +3 -3
- package/package.json +182 -10
- package/public/docs-mock-api-sw.js +5 -1
- package/public/docs-mock-api-sw.js.map +2 -2
- package/scripts/build-addons.mjs +2 -2
- package/scripts/post-build.mjs +9 -0
- package/src/addons/interactive.ts +5 -0
- package/src/core/components/functional/if/if.ts +54 -7
- package/src/core/components/functional/interactive/action.ts +84 -0
- package/src/core/components/functional/interactive/gamepad.ts +197 -0
- package/src/core/components/functional/interactive/gesture.ts +136 -0
- package/src/core/components/functional/interactive/helpers.spec.ts +50 -0
- package/src/core/components/functional/interactive/helpers.ts +97 -0
- package/src/core/components/functional/interactive/index.ts +25 -0
- package/src/core/components/functional/interactive/interactive.md +33 -0
- package/src/core/components/functional/interactive/keyboard.ts +171 -0
- package/src/core/components/functional/interactive/matrix.ts +185 -0
- package/src/core/components/functional/interactive/registry.ts +46 -0
- package/src/core/components/functional/interactive/store.ts +270 -0
- package/src/core/components/functional/interactive/ticker.ts +171 -0
- package/src/core/components/functional/list/list.ts +0 -0
- package/src/core/components/functional/subscriber/subscriber.ts +0 -0
- package/src/core/components/functional/value/value.ts +44 -4
- package/src/core/components/ui/_css/rounded.ts +36 -0
- package/src/core/components/ui/_css/type.ts +49 -0
- package/src/core/components/ui/_i18n/ui-aria-labels.ts +104 -0
- package/src/core/components/ui/alert/alert.md +128 -72
- package/src/core/components/ui/alert/alert.spec.ts +145 -0
- package/src/core/components/ui/alert/alert.ts +86 -91
- package/src/core/components/ui/alert-messages/alert-messages.ts +1 -1
- package/src/core/components/ui/badge/badge.md +126 -78
- package/src/core/components/ui/badge/badge.ts +29 -81
- package/src/core/components/ui/button/button.md +1 -0
- package/src/core/components/ui/button/button.ts +12 -10
- package/src/core/components/ui/card/card-header.ts +7 -2
- package/src/core/components/ui/card/card.md +120 -65
- package/src/core/components/ui/divider/divider.ts +4 -9
- package/src/core/components/ui/form/checkbox/checkbox.md +1 -1
- package/src/core/components/ui/form/checkbox/checkbox.ts +4 -20
- package/src/core/components/ui/form/fieldset/legend-description.ts +1 -1
- package/src/core/components/ui/form/fieldset/legend.ts +1 -1
- package/src/core/components/ui/form/input/input.md +1 -1
- package/src/core/components/ui/form/input/input.ts +25 -27
- package/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +14 -118
- package/src/core/components/ui/form/input-autocomplete/input-autocomplete.ts +419 -187
- package/src/core/components/ui/form/radio/radio.ts +1 -1
- package/src/core/components/ui/form/select/select.ts +3 -6
- package/src/core/components/ui/form/textarea/textarea.md +1 -1
- package/src/core/components/ui/form/textarea/textarea.ts +1 -2
- package/src/core/components/ui/image/image.md +147 -53
- package/src/core/components/ui/image/image.ts +10 -44
- package/src/core/components/ui/link/link.md +2 -2
- package/src/core/components/ui/link/link.ts +42 -37
- package/src/core/components/ui/modal/modal-close.ts +8 -12
- package/src/core/components/ui/modal/modal.ts +18 -18
- package/src/core/components/ui/pop/pop.md +105 -1
- package/src/core/components/ui/pop/pop.ts +145 -141
- package/src/core/components/ui/table/table.ts +2 -8
- package/src/core/components/ui/theme/theme.ts +1 -1
- package/src/core/components/ui/toast/dismissed.ts +14 -0
- package/src/core/components/ui/toast/render-content.ts +13 -0
- package/src/core/components/ui/toast/toast-item.ts +179 -103
- package/src/core/components/ui/toast/toast.ts +58 -21
- package/src/core/components/ui/toast/types.ts +14 -2
- package/src/core/components/ui/tooltip/tooltip.ts +176 -154
- package/src/core/decorators/subscriber/ancestorAttribute.spec.ts +26 -0
- package/src/core/decorators/subscriber/ancestorAttribute.ts +3 -4
- package/src/core/decorators/subscriber/derive.ts +3 -3
- package/src/core/mixins/Fetcher.ts +1 -1
- package/src/core/mixins/FormCheckable.ts +1 -8
- package/src/core/mixins/FormElement.ts +74 -76
- package/src/core/mixins/Subscriber.ts +5 -1
- package/src/core/utils/AncestorAttributeObserver.ts +183 -70
- package/src/core/utils/DataBindObserver.ts +0 -0
- package/src/core/utils/LocationHandler.ts +12 -5
- package/src/core/utils/Objects.ts +0 -0
- package/src/core/utils/dismissed.ts +22 -0
- package/src/core/utils/positioning.spec.ts +208 -0
- package/src/core/utils/positioning.ts +183 -0
- package/src/directives.ts +1 -3
- package/src/docs/_core-concept/dataFlow.md +1 -1
- package/src/docs/_decorators/ancestor-attribute.md +3 -2
- package/src/docs/_getting-started/cdn-addons.md +1 -0
- package/src/docs/_getting-started/concorde-outside.md +3 -3
- package/src/docs/_misc/formelement-subscriber-removal.md +115 -0
- package/src/docs/_misc/html-integration.md +2 -0
- package/src/docs/code.ts +3 -1
- package/src/docs/components/docs-demo-sources.ts +60 -0
- package/src/docs/docs.ts +1 -0
- package/src/docs/example/docs-input-autocomplete-demos.ts +110 -0
- package/src/docs/mock-api/router.ts +17 -1
- package/src/docs/navigation/navigation.ts +8 -0
- package/src/docs/search/docs-search.json +956 -243
- package/src/docs/tailwind/css/tailwind.css +13 -6
- package/src/tsconfig.json +135 -6
- package/src/tsconfig.tsbuildinfo +1 -1
- package/tailwind.config.js +50 -3
- package/vite/config.js +23 -35
- package/vite.config.mts +5 -0
- package/vitest.setup.ts +49 -13
- package/docs/assets/index-BZiZXMU-.css +0 -1
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
FormInput,
|
|
11
11
|
FormElement,
|
|
12
|
-
Subscriber,
|
|
13
12
|
TemplatesContainer,
|
|
14
13
|
} from "@supersoniks/concorde/mixins";
|
|
15
14
|
import "@supersoniks/concorde/core/components/ui/form/input/input";
|
|
@@ -25,17 +24,20 @@ import { customScroll } from "@supersoniks/concorde/core/components/ui/_css/scro
|
|
|
25
24
|
import { ResizeController } from "@lit-labs/observers/resize-controller.js";
|
|
26
25
|
import { traverseDotNotation } from "@supersoniks/concorde/core/utils/Objects";
|
|
27
26
|
import { Pop } from "../../pop/pop";
|
|
27
|
+
import type { ListItems } from "@supersoniks/concorde/core/components/functional/list/list";
|
|
28
28
|
|
|
29
29
|
type ListItem = Record<string, string>;
|
|
30
30
|
|
|
31
|
+
const SUGGESTION_VALUE_ATTR = "data-autocomplete-value";
|
|
32
|
+
const SUGGESTION_LABEL_ATTR = "data-autocomplete-label";
|
|
33
|
+
|
|
31
34
|
/**
|
|
32
|
-
* Input avec
|
|
33
|
-
*
|
|
34
|
-
* La valeur de cet input est ensuite retransmit au premier via un dataProvider.
|
|
35
|
+
* Input avec suggestions (queue). Valeur formulaire via formDataProvider + name ;
|
|
36
|
+
* texte de recherche sur un store interne dédié.
|
|
35
37
|
*/
|
|
36
38
|
@customElement("sonic-input-autocomplete")
|
|
37
39
|
export class InputAutocomplete extends TemplatesContainer(
|
|
38
|
-
FormInput(FormElement(
|
|
40
|
+
FormInput(FormElement(LitElement))
|
|
39
41
|
) {
|
|
40
42
|
static styles = [
|
|
41
43
|
customScroll,
|
|
@@ -43,7 +45,6 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
43
45
|
:host {
|
|
44
46
|
display: block;
|
|
45
47
|
}
|
|
46
|
-
/**disable mouse if there is an attribute readonly */
|
|
47
48
|
:host([readonly]),
|
|
48
49
|
:host([disabled]) {
|
|
49
50
|
pointer-events: none;
|
|
@@ -60,26 +61,34 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
60
61
|
min-width: 14rem;
|
|
61
62
|
width: 100%;
|
|
62
63
|
}
|
|
64
|
+
|
|
65
|
+
.init-queue {
|
|
66
|
+
display: none !important;
|
|
67
|
+
position: absolute;
|
|
68
|
+
width: 0;
|
|
69
|
+
height: 0;
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
}
|
|
63
73
|
`,
|
|
64
74
|
];
|
|
65
75
|
|
|
66
|
-
/**
|
|
67
|
-
* Possibles mutualisation avec text
|
|
68
|
-
*/
|
|
69
76
|
@property({ type: String }) size: Size = "md";
|
|
70
77
|
@property({ type: String }) placeholder = "";
|
|
71
78
|
@property() filteredFields = "";
|
|
72
79
|
@property({ type: Boolean, reflect: true }) readonly: boolean | null = null;
|
|
73
80
|
|
|
74
81
|
@property({ type: String }) dataProviderExpression = "";
|
|
75
|
-
@property({ type:
|
|
82
|
+
@property({ type: String }) serviceURL = "";
|
|
83
|
+
@property({ type: Number }) minSearchLength = 3;
|
|
76
84
|
@property({ type: Boolean }) select?: boolean;
|
|
77
85
|
@property({ type: String }) key = "";
|
|
78
|
-
/** The parameter name to use in dataProviderExpression route */
|
|
79
86
|
@property({ type: String }) searchParameter = "";
|
|
80
|
-
/** The property name to search in the dataProviderExpression result, use "_self" if result is a string list */
|
|
81
87
|
@property({ type: String }) propertyName = "";
|
|
82
88
|
|
|
89
|
+
@property({ type: Function, attribute: false }) items: ListItems | null =
|
|
90
|
+
null;
|
|
91
|
+
|
|
83
92
|
@queryAssignedNodes({ slot: "prefix", flatten: true })
|
|
84
93
|
slotInputPrefixNodes!: Array<Node>;
|
|
85
94
|
|
|
@@ -87,58 +96,292 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
87
96
|
@query("sonic-pop") popElement!: Pop;
|
|
88
97
|
_resizeController = new ResizeController(this, {});
|
|
89
98
|
|
|
90
|
-
@state()
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
|
|
94
|
-
*/
|
|
95
|
-
private searchDataProvider = "";
|
|
99
|
+
@state() private searchText = "";
|
|
100
|
+
@state() private searchDataProvider = "";
|
|
101
|
+
/** Filtre queue : ne reçoit la saisie qu'à partir de minSearchLength. */
|
|
102
|
+
private queueFilterDataProvider = "";
|
|
96
103
|
private initSearchDataProvider = "";
|
|
97
104
|
private queueDataProvider = "";
|
|
98
105
|
private initQueueDataProvider = "";
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
|
|
107
|
+
/** Public — cptypeahead. */
|
|
108
|
+
lastValidSearch: ListItem | string = "";
|
|
109
|
+
/** Public — cptypeahead (saisie live). */
|
|
110
|
+
searchPublisher?: DataProvider;
|
|
111
|
+
|
|
112
|
+
private queueFilterPublisher?: DataProvider;
|
|
103
113
|
private initCountPublisher?: DataProvider;
|
|
104
114
|
private formValuePublisher?: DataProvider;
|
|
115
|
+
private providersReady = false;
|
|
116
|
+
/** Évite de rouvrir le pop juste après une sélection. */
|
|
117
|
+
private suppressPopOpen = false;
|
|
118
|
+
private filterArmed = false;
|
|
119
|
+
|
|
120
|
+
private static instanceCounter = 0;
|
|
105
121
|
|
|
106
|
-
/**
|
|
107
|
-
* Les fonctions de gestion
|
|
108
|
-
*/
|
|
109
122
|
hasSlotOrProps() {
|
|
110
123
|
this.hasInputPrefix = !!this.slotInputPrefixNodes?.length;
|
|
111
124
|
}
|
|
112
125
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
126
|
+
private searchFieldName() {
|
|
127
|
+
return this.searchParameter || this.name;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private isSearchParameter() {
|
|
131
|
+
return !this.searchParameter || this.searchParameter === this.name;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private shouldShowSuggestions(text: string) {
|
|
135
|
+
return (
|
|
136
|
+
(text?.length || 0) >= this.minSearchLength || this.minSearchLength === 0
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private isSearchFocused() {
|
|
141
|
+
const active = document.activeElement;
|
|
142
|
+
if (!active) return false;
|
|
143
|
+
const input = this.renderRoot?.querySelector(
|
|
144
|
+
"sonic-input.form-element"
|
|
145
|
+
) as HTMLElement | null;
|
|
146
|
+
return !!(
|
|
147
|
+
input &&
|
|
148
|
+
(active === input ||
|
|
149
|
+
input.contains(active) ||
|
|
150
|
+
input.shadowRoot?.contains(active))
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private openPopIfNeeded(text: string, fromUserInput = false) {
|
|
155
|
+
if (this.suppressPopOpen) return;
|
|
156
|
+
if (!this.shouldShowSuggestions(text)) {
|
|
157
|
+
this.popElement?.hide();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (fromUserInput || this.isSearchFocused() || this.popElement?.open) {
|
|
161
|
+
this.popElement?.show();
|
|
162
|
+
// 2e show après le render Lit du pop (remettait display:none)
|
|
163
|
+
requestAnimationFrame(() => {
|
|
164
|
+
if (this.suppressPopOpen) return;
|
|
165
|
+
const current = String(
|
|
166
|
+
this.searchPublisher?.get() ?? this.searchText ?? ""
|
|
167
|
+
);
|
|
168
|
+
if (this.shouldShowSuggestions(current)) {
|
|
169
|
+
this.popElement?.show();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private setSearchText(value: string | ListItem | null | undefined) {
|
|
176
|
+
const next =
|
|
177
|
+
value == null || value === ""
|
|
178
|
+
? ""
|
|
179
|
+
: typeof value === "string"
|
|
180
|
+
? value
|
|
181
|
+
: String(value);
|
|
182
|
+
this.searchText = next;
|
|
183
|
+
if (this.searchPublisher && this.searchPublisher.get() !== next) {
|
|
184
|
+
this.searchPublisher.set(next);
|
|
185
|
+
}
|
|
186
|
+
this.syncQueueFilter(next);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Pousse vers la queue seulement si assez de caractères. */
|
|
190
|
+
private syncQueueFilter(text: string) {
|
|
191
|
+
if (!this.queueFilterPublisher) return;
|
|
192
|
+
const ready =
|
|
193
|
+
this.minSearchLength === 0 || text.length >= this.minSearchLength;
|
|
194
|
+
if (ready) {
|
|
195
|
+
if (!this.filterArmed || this.queueFilterPublisher.get() !== text) {
|
|
196
|
+
this.queueFilterPublisher.set(text);
|
|
197
|
+
}
|
|
198
|
+
this.filterArmed = true;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (this.filterArmed) {
|
|
202
|
+
this.filterArmed = false;
|
|
203
|
+
this.clearSearchQueueResults();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private clearSearchQueueResults() {
|
|
208
|
+
if (!this.queueDataProvider) return;
|
|
209
|
+
const queuePub = PublisherManager.get(this.queueDataProvider);
|
|
210
|
+
const descriptors = queuePub.get();
|
|
211
|
+
if (Array.isArray(descriptors)) {
|
|
212
|
+
for (const d of descriptors) {
|
|
213
|
+
if (d?.dataProvider) {
|
|
214
|
+
PublisherManager.getInstance().delete(d.dataProvider);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
queuePub.set([]);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private applySuggestion(value: unknown, label: string) {
|
|
222
|
+
this.suppressPopOpen = true;
|
|
223
|
+
const formValue = value as string;
|
|
224
|
+
const searchLabel =
|
|
225
|
+
label ||
|
|
226
|
+
(typeof formValue === "string" ? formValue : String(formValue ?? ""));
|
|
227
|
+
|
|
228
|
+
this.formValuePublisher?.set(formValue);
|
|
229
|
+
this.lastValidSearch = this.isSearchParameter() ? formValue : searchLabel;
|
|
230
|
+
this.setSearchText(
|
|
231
|
+
this.isSearchParameter() ? String(formValue ?? "") : searchLabel
|
|
232
|
+
);
|
|
233
|
+
this.popElement?.hide();
|
|
234
|
+
|
|
235
|
+
// Laisse le cycle hide/focus se terminer avant de réautoriser l'ouverture.
|
|
236
|
+
requestAnimationFrame(() => {
|
|
237
|
+
this.suppressPopOpen = false;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
118
241
|
private updateSearchParameter = (value: string) => {
|
|
119
|
-
if (value == ""
|
|
120
|
-
this.
|
|
242
|
+
if (value == "" || value == null) {
|
|
243
|
+
if (this.isSearchParameter()) {
|
|
244
|
+
this.lastValidSearch = "";
|
|
245
|
+
this.setSearchText("");
|
|
246
|
+
}
|
|
121
247
|
return;
|
|
122
248
|
}
|
|
123
249
|
const found = this.queryQueueListItem(
|
|
124
250
|
this.queueDataProvider,
|
|
125
|
-
|
|
251
|
+
(listItem) => {
|
|
252
|
+
const itemVal =
|
|
253
|
+
this.propertyName === "_self"
|
|
254
|
+
? listItem
|
|
255
|
+
: listItem[this.propertyName || this.name];
|
|
256
|
+
return itemVal == value;
|
|
257
|
+
},
|
|
126
258
|
this.setSearchFromSelection
|
|
127
259
|
);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
260
|
+
if (!found) {
|
|
261
|
+
const foundInit = this.queryQueueListItem(
|
|
262
|
+
this.initQueueDataProvider,
|
|
263
|
+
(listItem) => {
|
|
264
|
+
const itemVal =
|
|
265
|
+
this.propertyName === "_self"
|
|
266
|
+
? listItem
|
|
267
|
+
: listItem[this.propertyName || this.name];
|
|
268
|
+
return itemVal == value;
|
|
269
|
+
},
|
|
270
|
+
this.setSearchFromSelection
|
|
271
|
+
);
|
|
272
|
+
if (!foundInit && this.isSearchParameter()) {
|
|
273
|
+
this.lastValidSearch = value;
|
|
274
|
+
this.setSearchText(String(value));
|
|
275
|
+
}
|
|
133
276
|
}
|
|
134
277
|
};
|
|
135
278
|
|
|
136
|
-
private
|
|
137
|
-
|
|
279
|
+
private onSearchPublisherAssign = (value: string) => {
|
|
280
|
+
const next = value == null ? "" : String(value);
|
|
281
|
+
if (this.searchText !== next) {
|
|
282
|
+
this.searchText = next;
|
|
283
|
+
}
|
|
284
|
+
this.syncQueueFilter(next);
|
|
285
|
+
this.openPopIfNeeded(next);
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
private handleSearchActivity = () => {
|
|
289
|
+
const text = String(this.searchPublisher?.get() ?? this.searchText ?? "");
|
|
290
|
+
this.openPopIfNeeded(text, true);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/** keyup composé depuis l'input shadow — ouvre le pop dès qu'il y a assez de caractères. */
|
|
294
|
+
private handleSearchKeyUp = (e: KeyboardEvent) => {
|
|
295
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
296
|
+
if (["Escape", "Tab", "Enter", "ArrowUp", "ArrowDown"].includes(e.key))
|
|
297
|
+
return;
|
|
298
|
+
this.handleSearchActivity();
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Capture : empêche la nav FormElement (data-keyboard-nav) de sortir du champ
|
|
303
|
+
* et de fermer le pop. ArrowDown/Up gardent le pop ouvert et entrent dans la liste.
|
|
304
|
+
* Enter depuis le champ sélectionne la 1re suggestion.
|
|
305
|
+
*/
|
|
306
|
+
private handleSearchKeyDown = (e: KeyboardEvent) => {
|
|
307
|
+
const path = e.composedPath() as HTMLElement[];
|
|
308
|
+
const fromMenuItem = path.some((n) => n?.tagName === "SONIC-MENU-ITEM");
|
|
309
|
+
|
|
310
|
+
// Enter / Espace sur une suggestion → sélection
|
|
311
|
+
if (fromMenuItem && (e.key === "Enter" || e.key === " ")) {
|
|
312
|
+
const item = path.find((n) => n?.tagName === "SONIC-MENU-ITEM") as
|
|
313
|
+
| (HTMLElement & { value?: string | null })
|
|
314
|
+
| undefined;
|
|
315
|
+
if (!item) return;
|
|
316
|
+
e.preventDefault();
|
|
317
|
+
e.stopPropagation();
|
|
318
|
+
this.selectSuggestionItem(item);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (fromMenuItem) return;
|
|
323
|
+
|
|
324
|
+
const text = String(this.searchPublisher?.get() ?? this.searchText ?? "");
|
|
325
|
+
if (!this.shouldShowSuggestions(text)) return;
|
|
326
|
+
|
|
327
|
+
// Enter dans le champ → 1re suggestion
|
|
328
|
+
if (e.key === "Enter") {
|
|
329
|
+
const items = this.getSuggestionItems();
|
|
330
|
+
if (!items.length) return;
|
|
331
|
+
e.preventDefault();
|
|
332
|
+
e.stopPropagation();
|
|
333
|
+
this.selectSuggestionItem(items[0]);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
|
|
338
|
+
|
|
339
|
+
e.preventDefault();
|
|
340
|
+
e.stopPropagation();
|
|
341
|
+
|
|
342
|
+
this.suppressPopOpen = false;
|
|
343
|
+
this.popElement?.show();
|
|
344
|
+
requestAnimationFrame(() => this.popElement?.show());
|
|
345
|
+
|
|
346
|
+
const items = this.getSuggestionItems();
|
|
347
|
+
if (!items.length) return;
|
|
348
|
+
|
|
349
|
+
const target = e.key === "ArrowDown" ? items[0] : items[items.length - 1];
|
|
350
|
+
target.focus?.();
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
private getSuggestionItems() {
|
|
354
|
+
return [
|
|
355
|
+
...(this.renderRoot?.querySelectorAll("sonic-menu-item") ?? []),
|
|
356
|
+
] as Array<HTMLElement & { value?: string | null; focus?: () => void }>;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private selectSuggestionItem(
|
|
360
|
+
item: HTMLElement & { value?: string | null }
|
|
361
|
+
) {
|
|
362
|
+
const value =
|
|
363
|
+
item.getAttribute(SUGGESTION_VALUE_ATTR) ?? item.value ?? null;
|
|
364
|
+
const label =
|
|
365
|
+
item.getAttribute(SUGGESTION_LABEL_ATTR) ??
|
|
366
|
+
(item.textContent || "").trim();
|
|
367
|
+
|
|
368
|
+
if (value == null && !label) return;
|
|
369
|
+
this.applySuggestion(value ?? label, label);
|
|
138
370
|
}
|
|
139
371
|
|
|
140
|
-
|
|
141
|
-
|
|
372
|
+
/**
|
|
373
|
+
* pointerdown : avant le click document qui ferme le pop.
|
|
374
|
+
* data-autocomplete-* (démos .items) ou value + textContent (templates legacy).
|
|
375
|
+
*/
|
|
376
|
+
private handleSuggestionPointerDown = (e: Event) => {
|
|
377
|
+
const item = (e.composedPath() as HTMLElement[]).find(
|
|
378
|
+
(n) => n?.tagName === "SONIC-MENU-ITEM"
|
|
379
|
+
) as (HTMLElement & { value?: string | null }) | undefined;
|
|
380
|
+
if (!item) return;
|
|
381
|
+
|
|
382
|
+
e.preventDefault();
|
|
383
|
+
e.stopPropagation();
|
|
384
|
+
this.selectSuggestionItem(item);
|
|
142
385
|
};
|
|
143
386
|
|
|
144
387
|
private initSearchParameter = () => {
|
|
@@ -149,22 +392,6 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
149
392
|
);
|
|
150
393
|
};
|
|
151
394
|
|
|
152
|
-
private selectListItem = (listItem: ListItem) => {
|
|
153
|
-
const value =
|
|
154
|
-
this.propertyName === "_self"
|
|
155
|
-
? listItem
|
|
156
|
-
: listItem[this.propertyName || this.name];
|
|
157
|
-
this.formValuePublisher?.set(value);
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
private findSearchedItem = (listItem: ListItem) => {
|
|
161
|
-
const value =
|
|
162
|
-
this.propertyName === "_self"
|
|
163
|
-
? listItem
|
|
164
|
-
: listItem[this.propertyName || this.searchParameter || this.name];
|
|
165
|
-
return value == this.searchPublisher?.get();
|
|
166
|
-
};
|
|
167
|
-
|
|
168
395
|
private findSelection = (listItem: ListItem) => {
|
|
169
396
|
const value =
|
|
170
397
|
this.propertyName === "_self"
|
|
@@ -178,115 +405,97 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
178
405
|
this.propertyName === "_self"
|
|
179
406
|
? listItem
|
|
180
407
|
: listItem[this.searchParameter || this.propertyName || this.name];
|
|
181
|
-
|
|
182
|
-
this.searchPublisher?.set(this.lastValidSearch);
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
private updateActiveSelection = () => {
|
|
186
|
-
this.queryQueueListItem(
|
|
187
|
-
this.queueDataProvider,
|
|
188
|
-
this.findSearchedItem,
|
|
189
|
-
this.selectListItem
|
|
190
|
-
);
|
|
191
|
-
if (
|
|
192
|
-
!this.select &&
|
|
193
|
-
this.lastValidSearch &&
|
|
194
|
-
this.lastValidSearch != this.searchPublisher?.get() &&
|
|
195
|
-
this.formValuePublisher?.get()
|
|
196
|
-
) {
|
|
197
|
-
this.formValuePublisher?.set("");
|
|
198
|
-
}
|
|
408
|
+
this.setSearchText(this.lastValidSearch as string);
|
|
199
409
|
};
|
|
200
410
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const dpPrefix = formDataProvider + "__" + this.name + "__autocomplete";
|
|
411
|
+
private setupProviders() {
|
|
412
|
+
const searchParameter = this.searchFieldName();
|
|
413
|
+
const formDataProvider =
|
|
414
|
+
this.formDataProvider ||
|
|
415
|
+
this.getAncestorAttributeValue("formDataProvider") ||
|
|
416
|
+
"";
|
|
417
|
+
|
|
418
|
+
const instanceId = InputAutocomplete.instanceCounter++;
|
|
419
|
+
const dpPrefix =
|
|
420
|
+
(formDataProvider || "form") +
|
|
421
|
+
"__" +
|
|
422
|
+
(this.name || "field") +
|
|
423
|
+
"__autocomplete__" +
|
|
424
|
+
instanceId;
|
|
216
425
|
this.initSearchDataProvider = `${dpPrefix}_init_search__`;
|
|
217
426
|
this.initQueueDataProvider = `${dpPrefix}_init_queue__`;
|
|
218
427
|
this.searchDataProvider = `${dpPrefix}_search__`;
|
|
428
|
+
this.queueFilterDataProvider = `${dpPrefix}_queue_filter__`;
|
|
219
429
|
this.queueDataProvider = `${dpPrefix}_queue__`;
|
|
220
430
|
|
|
221
|
-
/**
|
|
222
|
-
* Les publishers utilisés plusieurs fois dans la classe son miss en propriétés privées de la classe
|
|
223
|
-
*/
|
|
224
431
|
const getPublisher = PublisherManager.get;
|
|
225
|
-
this.searchPublisher =
|
|
226
|
-
searchParameter
|
|
227
|
-
|
|
432
|
+
this.searchPublisher =
|
|
433
|
+
getPublisher(this.searchDataProvider)[searchParameter];
|
|
434
|
+
this.queueFilterPublisher =
|
|
435
|
+
getPublisher(this.queueFilterDataProvider)[searchParameter];
|
|
228
436
|
this.formValuePublisher = traverseDotNotation(
|
|
229
437
|
getPublisher(formDataProvider),
|
|
230
438
|
this.name
|
|
231
439
|
);
|
|
232
|
-
this.countPublisher = getPublisher(this.queueDataProvider).resultCount;
|
|
233
440
|
this.initCountPublisher = getPublisher(
|
|
234
441
|
this.initQueueDataProvider
|
|
235
442
|
).resultCount;
|
|
236
443
|
|
|
237
|
-
/**
|
|
238
|
-
* Si une valeur est fourrnie a l'initialisation, un queue spécifique appelle le service avec le name founi en paramètre
|
|
239
|
-
* Pour récupérer la valeur de searchParameter correspondante et renseigner l'input
|
|
240
|
-
**/
|
|
241
444
|
if (this.value) {
|
|
242
|
-
|
|
445
|
+
getPublisher(this.initSearchDataProvider)[this.name].set(this.value);
|
|
243
446
|
}
|
|
244
|
-
this.initCountPublisher?.onAssign(this.initSearchParameter);
|
|
245
447
|
|
|
246
|
-
|
|
247
|
-
* Lorsque la sélection change, on met à jour la valeur de recherche
|
|
248
|
-
*/
|
|
448
|
+
this.initCountPublisher?.onAssign(this.initSearchParameter);
|
|
249
449
|
this.formValuePublisher?.onAssign(this.updateSearchParameter);
|
|
450
|
+
this.searchPublisher?.onAssign(this.onSearchPublisherAssign);
|
|
250
451
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
452
|
+
const existing = this.searchPublisher?.get();
|
|
453
|
+
if (existing != null && existing !== "") {
|
|
454
|
+
this.searchText = String(existing);
|
|
455
|
+
this.syncQueueFilter(this.searchText);
|
|
456
|
+
}
|
|
256
457
|
|
|
257
|
-
this.
|
|
458
|
+
this.providersReady = true;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
private teardownProviders() {
|
|
462
|
+
this.initCountPublisher?.offAssign(this.initSearchParameter);
|
|
463
|
+
this.formValuePublisher?.offAssign(this.updateSearchParameter);
|
|
464
|
+
this.searchPublisher?.offAssign(this.onSearchPublisherAssign);
|
|
465
|
+
|
|
466
|
+
const getPublisher = PublisherManager.get;
|
|
467
|
+
if (this.initSearchDataProvider)
|
|
468
|
+
getPublisher(this.initSearchDataProvider).delete();
|
|
469
|
+
if (this.initQueueDataProvider)
|
|
470
|
+
getPublisher(this.initQueueDataProvider).delete();
|
|
471
|
+
if (this.searchDataProvider) getPublisher(this.searchDataProvider).delete();
|
|
472
|
+
if (this.queueFilterDataProvider)
|
|
473
|
+
getPublisher(this.queueFilterDataProvider).delete();
|
|
474
|
+
if (this.queueDataProvider) getPublisher(this.queueDataProvider).delete();
|
|
475
|
+
|
|
476
|
+
this.providersReady = false;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
connectedCallback() {
|
|
480
|
+
super.connectedCallback();
|
|
481
|
+
this.setupProviders();
|
|
482
|
+
this.addEventListener("keyup", this.handleSearchKeyUp);
|
|
483
|
+
this.addEventListener("keydown", this.handleSearchKeyDown, true);
|
|
258
484
|
}
|
|
259
485
|
|
|
260
486
|
protected firstUpdated(_changedProperties: PropertyValues): void {
|
|
261
487
|
super.firstUpdated(_changedProperties);
|
|
262
|
-
// Écouter le focusout sur le popElement pour fermer le pop quand le focus sort
|
|
263
488
|
this.popElement.addEventListener("focusout", this.handleFocusOut);
|
|
264
489
|
}
|
|
265
490
|
|
|
266
491
|
disconnectedCallback() {
|
|
492
|
+
this.removeEventListener("keyup", this.handleSearchKeyUp);
|
|
493
|
+
this.removeEventListener("keydown", this.handleSearchKeyDown, true);
|
|
494
|
+
this.teardownProviders();
|
|
495
|
+
this.popElement?.removeEventListener("focusout", this.handleFocusOut);
|
|
267
496
|
super.disconnectedCallback();
|
|
268
|
-
this.initCountPublisher?.offAssign(this.initSearchParameter);
|
|
269
|
-
this.formValuePublisher?.offAssign(this.updateSearchParameter);
|
|
270
|
-
this.countPublisher?.offAssign(this.updateActiveSelection);
|
|
271
|
-
const getPublisher = PublisherManager.get;
|
|
272
|
-
getPublisher(this.initSearchDataProvider).delete();
|
|
273
|
-
getPublisher(this.initQueueDataProvider).delete();
|
|
274
|
-
getPublisher(this.searchDataProvider).delete();
|
|
275
|
-
getPublisher(this.queueDataProvider).delete();
|
|
276
|
-
|
|
277
|
-
this.searchPublisher?.offAssign(this.updatePopContentVisibility);
|
|
278
|
-
|
|
279
|
-
// Retirer l'écouteur de focusout
|
|
280
|
-
this.popElement.removeEventListener("focusout", this.handleFocusOut);
|
|
281
497
|
}
|
|
282
498
|
|
|
283
|
-
/**
|
|
284
|
-
* @param queueDataProvider
|
|
285
|
-
* @param itemFinder
|
|
286
|
-
* @param itemMutator
|
|
287
|
-
*
|
|
288
|
-
* @return bool|undefined True if item found, false otherwise, undefined if result is not a list
|
|
289
|
-
*/
|
|
290
499
|
queryQueueListItem(
|
|
291
500
|
queueDataProvider: string,
|
|
292
501
|
itemFinder: (listItem: ListItem) => boolean,
|
|
@@ -294,19 +503,17 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
294
503
|
) {
|
|
295
504
|
const queuePublisher = PublisherManager.get(queueDataProvider);
|
|
296
505
|
let listItem: ListItem | undefined;
|
|
297
|
-
|
|
506
|
+
const listsDescriptors = queuePublisher.get();
|
|
298
507
|
|
|
299
508
|
if (!listsDescriptors || !Array.isArray(listsDescriptors)) {
|
|
300
509
|
return false;
|
|
301
510
|
}
|
|
302
511
|
if (!listsDescriptors.length) return false;
|
|
303
512
|
for (const listDescriptor of listsDescriptors) {
|
|
304
|
-
|
|
513
|
+
const list = PublisherManager.get(listDescriptor.dataProvider).get();
|
|
305
514
|
if (!Array.isArray(list)) continue;
|
|
306
515
|
listItem = list.find(itemFinder);
|
|
307
|
-
if (listItem)
|
|
308
|
-
break;
|
|
309
|
-
}
|
|
516
|
+
if (listItem) break;
|
|
310
517
|
}
|
|
311
518
|
if (listItem) {
|
|
312
519
|
itemMutator(listItem);
|
|
@@ -316,68 +523,86 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
316
523
|
}
|
|
317
524
|
|
|
318
525
|
setSelectionRange(start: number, end: number) {
|
|
319
|
-
(
|
|
526
|
+
(
|
|
527
|
+
this.renderRoot?.querySelector("sonic-input.form-element") as Input | null
|
|
528
|
+
)?.setSelectionRange(start, end);
|
|
320
529
|
}
|
|
321
530
|
|
|
322
531
|
handleHide(): void {
|
|
323
532
|
if (!this.select) return;
|
|
324
|
-
if (this.
|
|
533
|
+
if (!this.searchText) {
|
|
325
534
|
this.lastValidSearch = "";
|
|
326
535
|
this.formValuePublisher?.set("");
|
|
327
536
|
return;
|
|
328
537
|
}
|
|
329
|
-
this.
|
|
538
|
+
this.setSearchText(this.lastValidSearch as string);
|
|
330
539
|
}
|
|
331
540
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
541
|
+
/** Contient `node` même à travers des shadow roots imbriqués. */
|
|
542
|
+
private deepContains(container: Element | null | undefined, node: Node | null) {
|
|
543
|
+
if (!container || !node) return false;
|
|
544
|
+
let current: Node | null = node;
|
|
545
|
+
while (current) {
|
|
546
|
+
if (current === container || container.contains(current)) return true;
|
|
547
|
+
const root = current.getRootNode();
|
|
548
|
+
if (root instanceof ShadowRoot) {
|
|
549
|
+
current = root.host;
|
|
550
|
+
} else {
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
335
553
|
}
|
|
336
|
-
return
|
|
554
|
+
return false;
|
|
337
555
|
}
|
|
338
556
|
|
|
339
557
|
handleFocus(): void {
|
|
340
|
-
this.
|
|
558
|
+
const text = String(this.searchText ?? "");
|
|
559
|
+
if (this.shouldShowSuggestions(text)) {
|
|
560
|
+
this.suppressPopOpen = false;
|
|
561
|
+
this.popElement?.show();
|
|
562
|
+
}
|
|
341
563
|
}
|
|
342
564
|
|
|
343
|
-
handleFocusOut = (
|
|
344
|
-
|
|
345
|
-
|
|
565
|
+
handleFocusOut = (e: FocusEvent): void => {
|
|
566
|
+
const related = e.relatedTarget as Node | null;
|
|
567
|
+
if (
|
|
568
|
+
this.deepContains(this.popElement, related) ||
|
|
569
|
+
this.deepContains(this, related)
|
|
570
|
+
) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
346
574
|
setTimeout(() => {
|
|
575
|
+
if (this.suppressPopOpen) return;
|
|
347
576
|
const activeElement = document.activeElement;
|
|
348
|
-
if (
|
|
349
|
-
|
|
577
|
+
if (
|
|
578
|
+
!activeElement ||
|
|
579
|
+
this.deepContains(this.popElement, activeElement) ||
|
|
580
|
+
this.deepContains(this, activeElement)
|
|
581
|
+
) {
|
|
350
582
|
return;
|
|
351
583
|
}
|
|
352
|
-
|
|
353
|
-
// Vérifier si le focus est dans le popElement ou dans ce composant
|
|
354
|
-
const isInPop =
|
|
355
|
-
this.popElement.contains(activeElement) ||
|
|
356
|
-
this.popElement.shadowRoot?.contains(activeElement);
|
|
357
|
-
const isInComponent =
|
|
358
|
-
this.contains(activeElement) ||
|
|
359
|
-
this.shadowRoot?.contains(activeElement);
|
|
360
|
-
|
|
361
|
-
// Si le focus n'est ni dans le pop ni dans ce composant, fermer le pop
|
|
362
|
-
if (!isInPop && !isInComponent) {
|
|
363
|
-
this.popElement.hide();
|
|
364
|
-
}
|
|
584
|
+
this.popElement?.hide();
|
|
365
585
|
}, 0);
|
|
366
586
|
};
|
|
367
587
|
|
|
368
588
|
render() {
|
|
589
|
+
if (!this.providersReady || !this.searchDataProvider) {
|
|
590
|
+
return nothing;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const templates = this.templateList.concat(this.templatePartsList);
|
|
594
|
+
|
|
369
595
|
return html`
|
|
370
596
|
<sonic-pop manual style="display:block;" @hide=${this.handleHide}>
|
|
371
597
|
<sonic-input
|
|
372
598
|
class="form-element"
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
formDataProvider="${this.searchDataProvider}"
|
|
599
|
+
.formDataProvider=${this.searchDataProvider}
|
|
600
|
+
.value=${this.searchText}
|
|
376
601
|
type="search"
|
|
377
|
-
data-keyboard-nav="
|
|
602
|
+
data-keyboard-nav=""
|
|
378
603
|
label="${ifDefined(this.label)}"
|
|
379
604
|
description="${ifDefined(this.description)}"
|
|
380
|
-
name="${ifDefined(this.
|
|
605
|
+
name="${ifDefined(this.searchFieldName())}"
|
|
381
606
|
?required=${this.required}
|
|
382
607
|
placeholder="${ifDefined(this.placeholder)}"
|
|
383
608
|
?readonly="${this.readonly}"
|
|
@@ -386,7 +611,7 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
386
611
|
inlineContent
|
|
387
612
|
size=${this.size}
|
|
388
613
|
@focus=${this.handleFocus}
|
|
389
|
-
|
|
614
|
+
@change=${this.handleSearchActivity}
|
|
390
615
|
>
|
|
391
616
|
<slot
|
|
392
617
|
name="prefix"
|
|
@@ -408,33 +633,40 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
408
633
|
<sonic-menu
|
|
409
634
|
slot="content"
|
|
410
635
|
class="custom-scroll"
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
636
|
+
data-on-select="keep"
|
|
637
|
+
style="${this.offsetWidth ? `width: ${this.offsetWidth}px` : ""}"
|
|
638
|
+
@pointerdown=${this.handleSuggestionPointerDown}
|
|
414
639
|
>
|
|
415
640
|
<sonic-queue
|
|
416
641
|
dataProvider="${this.queueDataProvider}"
|
|
417
642
|
filteredFields=${this.filteredFields}
|
|
418
643
|
dataProviderExpression="${this.dataProviderExpression}"
|
|
419
|
-
dataFilterProvider="${this.
|
|
420
|
-
|
|
421
|
-
.templates=${this.templateList.concat(this.templatePartsList)}
|
|
422
|
-
displayContents
|
|
423
|
-
>
|
|
424
|
-
</sonic-queue>
|
|
425
|
-
<sonic-queue
|
|
426
|
-
noLazyload
|
|
427
|
-
loader="no-loader"
|
|
428
|
-
dataProvider="${this.initQueueDataProvider}"
|
|
429
|
-
filteredFields=${this.filteredFields}
|
|
430
|
-
dataProviderExpression="${this.dataProviderExpression}"
|
|
431
|
-
dataFilterProvider="${this.initSearchDataProvider}"
|
|
644
|
+
dataFilterProvider="${this.queueFilterDataProvider}"
|
|
645
|
+
serviceURL=${ifDefined(this.serviceURL || undefined)}
|
|
432
646
|
key="${this.key}"
|
|
647
|
+
.templates=${templates}
|
|
648
|
+
.items=${this.items}
|
|
433
649
|
displayContents
|
|
434
650
|
>
|
|
435
651
|
</sonic-queue>
|
|
436
652
|
</sonic-menu>
|
|
437
653
|
</sonic-pop>
|
|
654
|
+
<!-- Lookup valeur initiale : hors menu, jamais displayContents (sinon visible). -->
|
|
655
|
+
<sonic-queue
|
|
656
|
+
class="init-queue"
|
|
657
|
+
hidden
|
|
658
|
+
noLazyload
|
|
659
|
+
loader="no-loader"
|
|
660
|
+
dataProvider="${this.initQueueDataProvider}"
|
|
661
|
+
filteredFields=${this.filteredFields}
|
|
662
|
+
dataProviderExpression="${this.dataProviderExpression}"
|
|
663
|
+
dataFilterProvider="${this.initSearchDataProvider}"
|
|
664
|
+
serviceURL=${ifDefined(this.serviceURL || undefined)}
|
|
665
|
+
key="${this.key}"
|
|
666
|
+
.templates=${templates}
|
|
667
|
+
.items=${this.items}
|
|
668
|
+
>
|
|
669
|
+
</sonic-queue>
|
|
438
670
|
`;
|
|
439
671
|
}
|
|
440
672
|
}
|