@supersoniks/concorde 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +163 -0
  2. package/build-infos.json +1 -1
  3. package/concorde-core.bundle.js +175 -171
  4. package/concorde-core.es.js +2490 -2246
  5. package/dist/concorde-core.bundle.js +175 -171
  6. package/dist/concorde-core.es.js +2490 -2246
  7. package/package.json +22 -1
  8. package/php/get-challenge.php +34 -0
  9. package/php/some-service.php +42 -0
  10. package/scripts/pre-build.mjs +4 -0
  11. package/src/core/_types/endpoint.ts +4 -0
  12. package/src/core/_types/key.ts +1 -0
  13. package/src/core/components/functional/example/example.ts +38 -6
  14. package/src/core/decorators/Subscriber.ts +2 -0
  15. package/src/core/decorators/api.spec.ts +150 -0
  16. package/src/core/decorators/api.ts +244 -0
  17. package/src/core/decorators/subscriber/bind.ts +57 -145
  18. package/src/core/decorators/subscriber/dynamicPath.ts +77 -0
  19. package/src/core/decorators/subscriber/dynamicPropertyWatch.ts +105 -0
  20. package/src/core/decorators/subscriber/onAssign.ts +11 -147
  21. package/src/core/decorators/subscriber/publish.spec.ts +21 -0
  22. package/src/core/decorators/subscriber/publish.ts +148 -0
  23. package/src/core/decorators/subscriber/publisherPath.ts +13 -0
  24. package/src/core/decorators/subscriber/subscribe.spec.ts +21 -0
  25. package/src/core/decorators/subscriber/subscribe.ts +32 -0
  26. package/src/core/decorators/subscriber/subscribe.type-test.ts +32 -0
  27. package/src/core/utils/api.ts +83 -15
  28. package/src/core/utils/dataProviderKey.spec.ts +34 -0
  29. package/src/core/utils/dataProviderKey.ts +86 -0
  30. package/src/core/utils/endpoint.spec.ts +41 -0
  31. package/src/core/utils/endpoint.ts +87 -0
  32. package/src/decorators.ts +14 -0
  33. package/src/docs/{_misc → _decorators}/ancestor-attribute.md +15 -31
  34. package/src/docs/_decorators/bind.md +164 -0
  35. package/src/docs/_decorators/get.md +65 -0
  36. package/src/docs/_decorators/publish.md +54 -0
  37. package/src/docs/_decorators/subscribe.md +36 -0
  38. package/src/docs/_misc/dataProviderKey.md +135 -0
  39. package/src/docs/_misc/endpoint.md +42 -0
  40. package/src/docs/example/decorators-demo-bind-demos.ts +210 -0
  41. package/src/docs/example/decorators-demo-geo.ts +45 -0
  42. package/src/docs/example/decorators-demo-init.ts +228 -0
  43. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +324 -0
  44. package/src/docs/example/decorators-demo.ts +12 -459
  45. package/src/docs/navigation/navigation.ts +27 -10
  46. package/src/docs/search/docs-search.json +1059 -609
  47. package/src/tsconfig-model.json +1 -1
  48. package/src/tsconfig.json +65 -1
  49. package/src/tsconfig.tsbuildinfo +1 -1
  50. package/src/utils.ts +8 -1
  51. package/vite.config.mts +11 -0
  52. package/src/docs/_misc/bind.md +0 -362
  53. /package/src/docs/{_misc → _decorators}/auto-subscribe.md +0 -0
  54. /package/src/docs/{_misc → _decorators}/on-assign.md +0 -0
  55. /package/src/docs/{_misc → _decorators}/wait-for-ancestors.md +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "exclude": ["node_modules/**/*", "dist/**/*", "vite.config.mts", "docs.ts", "docs/*", "router-test.html"],
2
+ "exclude": ["node_modules/**/*", "dist/**/*", "vite.config.mts", "docs.ts", "docs/*", "router-test.html", "**/*.type-test.ts"],
3
3
  "compilerOptions": {
4
4
  "target": "es2021",
5
5
  "experimentalDecorators": true,
package/src/tsconfig.json CHANGED
@@ -5,7 +5,8 @@
5
5
  "vite.config.mts",
6
6
  "docs.ts",
7
7
  "docs/*",
8
- "router-test.html"
8
+ "router-test.html",
9
+ "**/*.type-test.ts"
9
10
  ],
10
11
  "compilerOptions": {
11
12
  "target": "es2021",
@@ -14,6 +15,12 @@
14
15
  "module": "esnext",
15
16
  "moduleResolution": "bundler",
16
17
  "paths": {
18
+ "./_types/endpoint": [
19
+ "/sites/concorde/src/core/_types/endpoint.ts"
20
+ ],
21
+ "./_types/key": [
22
+ "/sites/concorde/src/core/_types/key.ts"
23
+ ],
17
24
  "./_types/types": [
18
25
  "/sites/concorde/src/core/_types/types.ts"
19
26
  ],
@@ -767,6 +774,12 @@
767
774
  "./decorators/Subscriber": [
768
775
  "/sites/concorde/src/core/decorators/Subscriber.ts"
769
776
  ],
777
+ "./decorators/api.spec": [
778
+ "/sites/concorde/src/core/decorators/api.spec.ts"
779
+ ],
780
+ "./decorators/api": [
781
+ "/sites/concorde/src/core/decorators/api.ts"
782
+ ],
770
783
  "./decorators/lifecycle": [
771
784
  "/sites/concorde/src/core/decorators/lifecycle.ts"
772
785
  ],
@@ -785,9 +798,33 @@
785
798
  "./decorators/subscriber/common": [
786
799
  "/sites/concorde/src/core/decorators/subscriber/common.ts"
787
800
  ],
801
+ "./decorators/subscriber/dynamicPath": [
802
+ "/sites/concorde/src/core/decorators/subscriber/dynamicPath.ts"
803
+ ],
804
+ "./decorators/subscriber/dynamicPropertyWatch": [
805
+ "/sites/concorde/src/core/decorators/subscriber/dynamicPropertyWatch.ts"
806
+ ],
788
807
  "./decorators/subscriber/onAssign": [
789
808
  "/sites/concorde/src/core/decorators/subscriber/onAssign.ts"
790
809
  ],
810
+ "./decorators/subscriber/publish.spec": [
811
+ "/sites/concorde/src/core/decorators/subscriber/publish.spec.ts"
812
+ ],
813
+ "./decorators/subscriber/publish": [
814
+ "/sites/concorde/src/core/decorators/subscriber/publish.ts"
815
+ ],
816
+ "./decorators/subscriber/publisherPath": [
817
+ "/sites/concorde/src/core/decorators/subscriber/publisherPath.ts"
818
+ ],
819
+ "./decorators/subscriber/subscribe.spec": [
820
+ "/sites/concorde/src/core/decorators/subscriber/subscribe.spec.ts"
821
+ ],
822
+ "./decorators/subscriber/subscribe": [
823
+ "/sites/concorde/src/core/decorators/subscriber/subscribe.ts"
824
+ ],
825
+ "./decorators/subscriber/subscribe.type-test": [
826
+ "/sites/concorde/src/core/decorators/subscriber/subscribe.type-test.ts"
827
+ ],
791
828
  "./directives/DataProvider": [
792
829
  "/sites/concorde/src/core/directives/DataProvider.ts"
793
830
  ],
@@ -848,6 +885,18 @@
848
885
  "./utils/api": [
849
886
  "/sites/concorde/src/core/utils/api.ts"
850
887
  ],
888
+ "./utils/dataProviderKey.spec": [
889
+ "/sites/concorde/src/core/utils/dataProviderKey.spec.ts"
890
+ ],
891
+ "./utils/dataProviderKey": [
892
+ "/sites/concorde/src/core/utils/dataProviderKey.ts"
893
+ ],
894
+ "./utils/endpoint.spec": [
895
+ "/sites/concorde/src/core/utils/endpoint.spec.ts"
896
+ ],
897
+ "./utils/endpoint": [
898
+ "/sites/concorde/src/core/utils/endpoint.ts"
899
+ ],
851
900
  "./utils/route.spec": [
852
901
  "/sites/concorde/src/core/utils/route.spec.ts"
853
902
  ],
@@ -863,6 +912,18 @@
863
912
  "./docs": [
864
913
  "/sites/concorde/src/docs/docs.ts"
865
914
  ],
915
+ "./example/decorators-demo-bind-demos": [
916
+ "/sites/concorde/src/docs/example/decorators-demo-bind-demos.ts"
917
+ ],
918
+ "./example/decorators-demo-geo": [
919
+ "/sites/concorde/src/docs/example/decorators-demo-geo.ts"
920
+ ],
921
+ "./example/decorators-demo-init": [
922
+ "/sites/concorde/src/docs/example/decorators-demo-init.ts"
923
+ ],
924
+ "./example/decorators-demo-subscribe-publish-get-demos": [
925
+ "/sites/concorde/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts"
926
+ ],
866
927
  "./example/decorators-demo": [
867
928
  "/sites/concorde/src/docs/example/decorators-demo.ts"
868
929
  ],
@@ -902,6 +963,9 @@
902
963
  "./TestUtils": [
903
964
  "/sites/concorde/src/test-utils/TestUtils.ts"
904
965
  ],
966
+ "@supersoniks/concorde/dataProviderKey": [
967
+ "/sites/concorde/src/core/utils/dataProviderKey.ts"
968
+ ],
905
969
  "@supersoniks/concorde/*": [
906
970
  "./*"
907
971
  ],
@@ -1 +1 @@
1
- {"root":["./components.ts","./concorde-loaded.ts","./dataprovider.ts","./decorators.ts","./directives.ts","./index.ts","./mixins.ts","./utils.ts","./core/core.ts","./core/_types/types.ts","./core/components/functional/functional.ts","./core/components/functional/date/date.ts","./core/components/functional/example/example.ts","./core/components/functional/fetch/fetch.ts","./core/components/functional/if/if.test.ts","./core/components/functional/if/if.ts","./core/components/functional/list/list.demo.ts","./core/components/functional/list/list.spec.ts","./core/components/functional/list/list.ts","./core/components/functional/mix/mix.ts","./core/components/functional/queue/queue.demo.ts","./core/components/functional/queue/queue.ts","./core/components/functional/router/redirect.ts","./core/components/functional/router/router.demo.ts","./core/components/functional/router/router.spec.ts","./core/components/functional/router/router.ts","./core/components/functional/sdui/SDUIDescriptorTransformer.ts","./core/components/functional/sdui/sdui-utils.ts","./core/components/functional/sdui/sdui.ts","./core/components/functional/sdui/types.ts","./core/components/functional/sonic-scope/sonic-scope.ts","./core/components/functional/states/states.demo.ts","./core/components/functional/states/states.spec.ts","./core/components/functional/states/states.ts","./core/components/functional/submit/submit.ts","./core/components/functional/subscriber/subscriber.ts","./core/components/functional/translation/translation.ts","./core/components/functional/value/value.ts","./core/components/ui/ui.ts","./core/components/ui/_css/scroll.ts","./core/components/ui/_css/shadow.ts","./core/components/ui/_css/size.ts","./core/components/ui/_css/type.ts","./core/components/ui/alert/alert.ts","./core/components/ui/alert-messages/alert-messages.ts","./core/components/ui/badge/badge.ts","./core/components/ui/button/button.ts","./core/components/ui/captcha/altchaStyles.ts","./core/components/ui/captcha/captcha.ts","./core/components/ui/card/card-footer.ts","./core/components/ui/card/card-header-descripton.ts","./core/components/ui/card/card-header.ts","./core/components/ui/card/card-main.ts","./core/components/ui/card/card.ts","./core/components/ui/divider/divider.ts","./core/components/ui/form/checkbox/checkbox.ts","./core/components/ui/form/css/form-control.ts","./core/components/ui/form/fieldset/fieldset.ts","./core/components/ui/form/fieldset/legend-description.ts","./core/components/ui/form/fieldset/legend.ts","./core/components/ui/form/form-actions/form-actions.ts","./core/components/ui/form/form-layout/form-layout.ts","./core/components/ui/form/input/input.ts","./core/components/ui/form/input/password-helper.ts","./core/components/ui/form/input/same-value-helper.ts","./core/components/ui/form/input-autocomplete/input-autocomplete.ts","./core/components/ui/form/radio/radio.ts","./core/components/ui/form/select/select.ts","./core/components/ui/form/switch/switch.ts","./core/components/ui/form/textarea/textarea.ts","./core/components/ui/group/group.ts","./core/components/ui/icon/icon.stories.ts","./core/components/ui/icon/icon.ts","./core/components/ui/icon/icons.ts","./core/components/ui/image/image.ts","./core/components/ui/link/link.ts","./core/components/ui/loader/loader.stories.ts","./core/components/ui/loader/loader.ts","./core/components/ui/loader/styles/fixed.ts","./core/components/ui/loader/styles/inline.ts","./core/components/ui/menu/menu-item.ts","./core/components/ui/menu/menu.ts","./core/components/ui/modal/modal-actions.ts","./core/components/ui/modal/modal-close.ts","./core/components/ui/modal/modal-content.ts","./core/components/ui/modal/modal-subtitle.ts","./core/components/ui/modal/modal-title.ts","./core/components/ui/modal/modal.ts","./core/components/ui/pop/pop.ts","./core/components/ui/progress/progress.ts","./core/components/ui/table/table-caption.ts","./core/components/ui/table/table-tbody.ts","./core/components/ui/table/table-td.ts","./core/components/ui/table/table-tfoot.ts","./core/components/ui/table/table-th.ts","./core/components/ui/table/table-thead.ts","./core/components/ui/table/table-tr.ts","./core/components/ui/table/table.ts","./core/components/ui/theme/theme.ts","./core/components/ui/theme/theme-collection/core-variables.ts","./core/components/ui/theme/theme-collection/dark.ts","./core/components/ui/theme/theme-collection/light.ts","./core/components/ui/toast/message-subscriber.ts","./core/components/ui/toast/toast-item.ts","./core/components/ui/toast/toast.ts","./core/components/ui/toast/types.ts","./core/components/ui/tooltip/tooltip.ts","./core/decorators/Subscriber.ts","./core/decorators/lifecycle.ts","./core/decorators/subscriber/ancestorAttribute.ts","./core/decorators/subscriber/autoFill.ts","./core/decorators/subscriber/autoSubscribe.ts","./core/decorators/subscriber/bind.ts","./core/decorators/subscriber/common.ts","./core/decorators/subscriber/onAssign.ts","./core/directives/DataProvider.ts","./core/directives/Wording.ts","./core/mixins/Fetcher.ts","./core/mixins/FormCheckable.ts","./core/mixins/FormElement.ts","./core/mixins/FormInput.ts","./core/mixins/Subscriber.ts","./core/mixins/TemplatesContainer.ts","./core/mixins/mixins.ts","./core/utils/Arrays.ts","./core/utils/DataBindObserver.ts","./core/utils/Electron.ts","./core/utils/Format.ts","./core/utils/HTML.ts","./core/utils/LocationHandler.ts","./core/utils/Objects.ts","./core/utils/PublisherProxy.ts","./core/utils/Utils.ts","./core/utils/aesCrypto.ts","./core/utils/api.ts","./core/utils/route.spec.ts","./core/utils/route.ts","./core/utils/url-pattern.ts","./test-utils/TestUtils.ts"],"version":"5.9.2"}
1
+ {"root":["./components.ts","./concorde-loaded.ts","./dataprovider.ts","./decorators.ts","./directives.ts","./index.ts","./mixins.ts","./utils.ts","./core/core.ts","./core/_types/endpoint.ts","./core/_types/key.ts","./core/_types/types.ts","./core/components/functional/functional.ts","./core/components/functional/date/date.ts","./core/components/functional/example/example.ts","./core/components/functional/fetch/fetch.ts","./core/components/functional/if/if.test.ts","./core/components/functional/if/if.ts","./core/components/functional/list/list.demo.ts","./core/components/functional/list/list.spec.ts","./core/components/functional/list/list.ts","./core/components/functional/mix/mix.ts","./core/components/functional/queue/queue.demo.ts","./core/components/functional/queue/queue.ts","./core/components/functional/router/redirect.ts","./core/components/functional/router/router.demo.ts","./core/components/functional/router/router.spec.ts","./core/components/functional/router/router.ts","./core/components/functional/sdui/SDUIDescriptorTransformer.ts","./core/components/functional/sdui/sdui-utils.ts","./core/components/functional/sdui/sdui.ts","./core/components/functional/sdui/types.ts","./core/components/functional/sonic-scope/sonic-scope.ts","./core/components/functional/states/states.demo.ts","./core/components/functional/states/states.spec.ts","./core/components/functional/states/states.ts","./core/components/functional/submit/submit.ts","./core/components/functional/subscriber/subscriber.ts","./core/components/functional/translation/translation.ts","./core/components/functional/value/value.ts","./core/components/ui/ui.ts","./core/components/ui/_css/scroll.ts","./core/components/ui/_css/shadow.ts","./core/components/ui/_css/size.ts","./core/components/ui/_css/type.ts","./core/components/ui/alert/alert.ts","./core/components/ui/alert-messages/alert-messages.ts","./core/components/ui/badge/badge.ts","./core/components/ui/button/button.ts","./core/components/ui/captcha/altchaStyles.ts","./core/components/ui/captcha/captcha.ts","./core/components/ui/card/card-footer.ts","./core/components/ui/card/card-header-descripton.ts","./core/components/ui/card/card-header.ts","./core/components/ui/card/card-main.ts","./core/components/ui/card/card.ts","./core/components/ui/divider/divider.ts","./core/components/ui/form/checkbox/checkbox.ts","./core/components/ui/form/css/form-control.ts","./core/components/ui/form/fieldset/fieldset.ts","./core/components/ui/form/fieldset/legend-description.ts","./core/components/ui/form/fieldset/legend.ts","./core/components/ui/form/form-actions/form-actions.ts","./core/components/ui/form/form-layout/form-layout.ts","./core/components/ui/form/input/input.ts","./core/components/ui/form/input/password-helper.ts","./core/components/ui/form/input/same-value-helper.ts","./core/components/ui/form/input-autocomplete/input-autocomplete.ts","./core/components/ui/form/radio/radio.ts","./core/components/ui/form/select/select.ts","./core/components/ui/form/switch/switch.ts","./core/components/ui/form/textarea/textarea.ts","./core/components/ui/group/group.ts","./core/components/ui/icon/icon.stories.ts","./core/components/ui/icon/icon.ts","./core/components/ui/icon/icons.ts","./core/components/ui/image/image.ts","./core/components/ui/link/link.ts","./core/components/ui/loader/loader.stories.ts","./core/components/ui/loader/loader.ts","./core/components/ui/loader/styles/fixed.ts","./core/components/ui/loader/styles/inline.ts","./core/components/ui/menu/menu-item.ts","./core/components/ui/menu/menu.ts","./core/components/ui/modal/modal-actions.ts","./core/components/ui/modal/modal-close.ts","./core/components/ui/modal/modal-content.ts","./core/components/ui/modal/modal-subtitle.ts","./core/components/ui/modal/modal-title.ts","./core/components/ui/modal/modal.ts","./core/components/ui/pop/pop.ts","./core/components/ui/progress/progress.ts","./core/components/ui/table/table-caption.ts","./core/components/ui/table/table-tbody.ts","./core/components/ui/table/table-td.ts","./core/components/ui/table/table-tfoot.ts","./core/components/ui/table/table-th.ts","./core/components/ui/table/table-thead.ts","./core/components/ui/table/table-tr.ts","./core/components/ui/table/table.ts","./core/components/ui/theme/theme.ts","./core/components/ui/theme/theme-collection/core-variables.ts","./core/components/ui/theme/theme-collection/dark.ts","./core/components/ui/theme/theme-collection/light.ts","./core/components/ui/toast/message-subscriber.ts","./core/components/ui/toast/toast-item.ts","./core/components/ui/toast/toast.ts","./core/components/ui/toast/types.ts","./core/components/ui/tooltip/tooltip.ts","./core/decorators/Subscriber.ts","./core/decorators/api.spec.ts","./core/decorators/api.ts","./core/decorators/lifecycle.ts","./core/decorators/subscriber/ancestorAttribute.ts","./core/decorators/subscriber/autoFill.ts","./core/decorators/subscriber/autoSubscribe.ts","./core/decorators/subscriber/bind.ts","./core/decorators/subscriber/common.ts","./core/decorators/subscriber/dynamicPath.ts","./core/decorators/subscriber/dynamicPropertyWatch.ts","./core/decorators/subscriber/onAssign.ts","./core/decorators/subscriber/publish.spec.ts","./core/decorators/subscriber/publish.ts","./core/decorators/subscriber/publisherPath.ts","./core/decorators/subscriber/subscribe.spec.ts","./core/decorators/subscriber/subscribe.ts","./core/directives/DataProvider.ts","./core/directives/Wording.ts","./core/mixins/Fetcher.ts","./core/mixins/FormCheckable.ts","./core/mixins/FormElement.ts","./core/mixins/FormInput.ts","./core/mixins/Subscriber.ts","./core/mixins/TemplatesContainer.ts","./core/mixins/mixins.ts","./core/utils/Arrays.ts","./core/utils/DataBindObserver.ts","./core/utils/Electron.ts","./core/utils/Format.ts","./core/utils/HTML.ts","./core/utils/LocationHandler.ts","./core/utils/Objects.ts","./core/utils/PublisherProxy.ts","./core/utils/Utils.ts","./core/utils/aesCrypto.ts","./core/utils/api.ts","./core/utils/dataProviderKey.spec.ts","./core/utils/dataProviderKey.ts","./core/utils/endpoint.spec.ts","./core/utils/endpoint.ts","./core/utils/route.spec.ts","./core/utils/route.ts","./core/utils/url-pattern.ts","./test-utils/TestUtils.ts"],"version":"5.9.2"}
package/src/utils.ts CHANGED
@@ -21,7 +21,12 @@ export const api = myApi.default;
21
21
  import * as myURLPattern from "@supersoniks/concorde/core/utils/url-pattern";
22
22
  export const URLPattern = myURLPattern.default;
23
23
 
24
- import {ConcordeWindow} from "./core/_types/types";
24
+ import { Endpoint } from "./core/utils/endpoint";
25
+ import { DataProviderKey } from "./core/utils/dataProviderKey";
26
+ export { Endpoint, DataProviderKey };
27
+
28
+ import { ConcordeWindow } from "./core/_types/types";
29
+
25
30
  declare const window: ConcordeWindow;
26
31
 
27
32
  window["concorde-utils"] = window["concorde-utils"] || {};
@@ -36,4 +41,6 @@ window["concorde-utils"] = {
36
41
  PublisherManager: PublisherManager,
37
42
  api: api,
38
43
  URLPattern: URLPattern,
44
+ Endpoint: Endpoint,
45
+ DataProviderKey: DataProviderKey,
39
46
  };
package/vite.config.mts CHANGED
@@ -79,6 +79,17 @@ export default defineConfig({
79
79
  },
80
80
  resolve: {
81
81
  alias: [
82
+ {
83
+ find: "@supersoniks/concorde/dataProviderKey",
84
+ replacement: path.resolve(
85
+ __dirname,
86
+ "src/core/utils/dataProviderKey.ts",
87
+ ),
88
+ },
89
+ {
90
+ find: "@supersoniks/concorde/endpoint",
91
+ replacement: path.resolve(__dirname, "src/core/utils/endpoint.ts"),
92
+ },
82
93
  {
83
94
  find: "@supersoniks/concorde",
84
95
  replacement: path.resolve(__dirname, "src"),
@@ -1,362 +0,0 @@
1
- # @bind
2
-
3
- The `@bind` decorator automatically binds a class property to a path in a publisher. The property will be automatically
4
- updated when the publisher's data changes.
5
-
6
- If you need to trigger the rendering lifecycle of a LitElement, please also add the `@state()` decorator to the property.
7
-
8
- ## Principle
9
-
10
- This decorator subscribes to a publisher via the `PublisherManager` using a path (dot notation) to access a specific property. When this property is modified in the publisher, the decorated property is automatically updated.
11
-
12
- ## Usage
13
-
14
- ### Import
15
-
16
- <sonic-code language="typescript">
17
- <template>
18
- import { bind } from "@supersoniks/concorde/decorators";
19
- </template>
20
- </sonic-code>
21
-
22
- ### Basic example
23
-
24
- <sonic-code language="typescript">
25
- <template>
26
- @customElement("demo-bind")
27
- export class DemoBind extends LitElement {
28
- static styles = [tailwind];
29
- //
30
- @bind("demoData.firstName")
31
- @state()
32
- firstName = "";
33
- //
34
- @bind("demoData.lastName")
35
- @state()
36
- lastName: string = "";
37
- //
38
- @bind("demoData.count")
39
- @state()
40
- count: number = 0;
41
- //
42
- render() {
43
- return //......
44
- }
45
- //
46
- updateData() {
47
- const demoData = PublisherManager.get("demoData");
48
- const demoUsers = PublisherManager.get("demoUsers");
49
- const randomIndex = Math.floor(Math.random() * demoUsers.get().length);
50
- const randomUser = demoUsers.get()[randomIndex];
51
- demoData.set({
52
- firstName: randomUser.firstName,
53
- lastName: randomUser.lastName,
54
- count: (demoData.count.get() || 0) + 1,
55
- });
56
- }
57
- }
58
- </template>
59
- </sonic-code>
60
-
61
- <sonic-code>
62
- <template>
63
- <demo-bind></demo-bind>
64
- </template>
65
- </sonic-code>
66
-
67
-
68
- ## Reflect (liaison bidirectionnelle)
69
-
70
- Lorsque vous avez besoin que les modifications locales se propagent également vers le publisher, activez l'option `reflect` :
71
-
72
- <sonic-code language="typescript">
73
- <template>
74
- @bind("userData.profile.avatarUrl", { reflect: true })
75
- @state()
76
- avatar: string;
77
- </template>
78
- </sonic-code>
79
-
80
- - `reflect: true` crée un getter/setter qui garde les descripteurs existants et synchronise la valeur avec le publisher.
81
- - Les mises à jour provenant du publisher sont protégées par un flag interne afin d'éviter les boucles infinies.
82
- - Toute écriture sur la propriété décorée (ex. saisie utilisateur, mise à jour durant `render`) déclenche un `publisher.set(...)`.
83
- - Pratique pour implémenter des formulaires pilotés par les publishers sans écrire manuellement la logique de synchronisation.
84
-
85
-
86
- <sonic-code language="typescript">
87
- <template>
88
- @customElement("demo-bind-reflect")
89
- export class DemoBindReflect extends LitElement {
90
- static styles = [tailwind];
91
- //
92
- @bind("bindReflectDemo.count", { reflect: true })
93
- @state()
94
- withReflect: number = 0;
95
- //
96
- @bind("bindReflectDemo.count")
97
- @state()
98
- withoutReflect: number = 0;
99
- //
100
- render() {
101
- return html`
102
- <div class="mb-3">
103
- from publisher : ${sub("bindReflectDemo.count") || 0} <br />
104
- from component with reflect : ${this.withReflect || 0} <br />
105
- from component without reflect : ${this.withoutReflect || 0}
106
- </div>
107
- <sonic-button @click=${() => this.withReflect++}
108
- >Increment with reflect</sonic-button
109
- >
110
- <sonic-button @click=${() => this.withoutReflect++}
111
- >Increment without reflect</sonic-button
112
- >
113
- `;
114
- }
115
- }
116
- </template>
117
- </sonic-code>
118
-
119
- <sonic-code toggleCode>
120
- <template>
121
- <demo-bind-reflect></demo-bind-reflect>
122
- </template>
123
- </sonic-code>
124
-
125
-
126
- ### Complex path
127
-
128
- <sonic-code language="typescript">
129
- <template>
130
- @customElement("user-profile")
131
- export class UserProfile extends LitElement {
132
- // Access to a simple property
133
- @bind("cart")
134
- @state()
135
- cart: object;
136
- //
137
- // Access to a nested property
138
- @bind("userData.profile.email")
139
- @state()
140
- userEmail: string;
141
- //
142
- // Access to an array element
143
- @bind("userData.addresses.0.city")
144
- @state()
145
- primaryCity: string;
146
- //
147
- render() {
148
- return html`
149
- <div>
150
- <p>Number of items : ${this.cart.items.length}</p>
151
- <p>Email: ${this.userEmail}</p>
152
- <p>City: ${this.primaryCity}</p>
153
- </div>
154
- `;
155
- }
156
- }
157
- </template>
158
- </sonic-code>
159
-
160
- ## Path syntax
161
-
162
- The path uses dot notation to navigate through the publisher structure:
163
-
164
- - **First segment**: dataProvider identifier (e.g., `"myDataProvider"`)
165
- - **Following segments**: nested properties (e.g., `"myDataProvider.user.profile"`)
166
- - **Array access**: use numeric index (e.g., `"myDataProvider.items.0"`)
167
-
168
-
169
-
170
- ### Dynamic path driven by class properties
171
-
172
- You can now build the path dynamically by referencing the host class properties inside the string passed to `@bind`. Two placeholder syntaxes are supported:
173
-
174
- - `` ${myProperty} `` or `` ${this.myProperty} ``
175
- - `` {$myProperty} ``
176
-
177
- Each placeholder is replaced at runtime with the current value of the corresponding property. `@bind` automatically watches those properties and:
178
-
179
- - re-evaluates the final path when one of them changes,
180
- - removes the previous subscription before attaching the new one,
181
- - keeps working with `reflect: true`.
182
- - observe the changes inside `willUpdate(changedProperties)` so nothing touche aux getters/setters.
183
-
184
-
185
- <sonic-code language="typescript">
186
- <template>
187
- @customElement("demo-bind-dynamic")
188
- export class DemoBindDynamic extends LitElement {
189
- static styles = [tailwind];
190
- //
191
- @property({ type: String })
192
- dataProvider: "demoUsers" | "demoUsersAlt" = "demoUsers";
193
- //
194
- @property({ type: Number })
195
- userIndex: number = 0;
196
- //
197
- @bind("${dataProvider}.${userIndex}")
198
- @state()
199
- user: any = {};
200
- //
201
- updateUserIndex(e: Event) {
202
- this.userIndex = parseInt((e.target as HTMLInputElement).value);
203
- }
204
- //
205
- updateDataProvider(e: Event) {
206
- this.dataProvider = (e.target as HTMLSelectElement).value as
207
- | "demoUsers"
208
- | "demoUsersAlt";
209
- }
210
- //
211
- updateCurrentUserData() {
212
- const usersPublisher = PublisherManager.get(this.dataProvider);
213
- const userPublisher = Objects.traverse(
214
- usersPublisher,
215
- [String(this.userIndex)]
216
- ) as PublisherProxy;
217
-
218
- if (userPublisher) {
219
- // Générer de nouvelles données aléatoires
220
- const randomNames = [
221
- { firstName: "Alice", lastName: "Wonder" },
222
- { firstName: "Bob", lastName: "Builder" },
223
- { firstName: "Charlie", lastName: "Chaplin" },
224
- ];
225
-
226
- const randomName =
227
- randomNames[Math.floor(Math.random() * randomNames.length)];
228
- const randomEmail = `${randomName.firstName.toLowerCase()}.${randomName.lastName.toLowerCase()}@example.com`;
229
-
230
- // Mettre à jour l'utilisateur directement
231
- const currentUser = userPublisher.get() || {};
232
- userPublisher.set({
233
- ...currentUser,
234
- firstName: randomName.firstName,
235
- lastName: randomName.lastName,
236
- email: randomEmail,
237
- });
238
- }
239
- }
240
- //
241
- render() {
242
- return html`
243
- <div class="flex flex-col gap-2">
244
- <sonic-select
245
- .value=${this.dataProvider}
246
- label="Users set"
247
- @change=${this.updateDataProvider}
248
- >
249
- <option value="demoUsers">First set of users</option>
250
- <option value="demoUsersAlt">Second set of users</option>
251
- </sonic-select>
252
- <sonic-input
253
- type="number"
254
- .value=${this.userIndex}
255
- @input=${this.updateUserIndex}
256
- min="0"
257
- max="9"
258
- label="Index"
259
- class="block"
260
- >
261
- </sonic-input>
262
- <sonic-button @click=${this.updateCurrentUserData}
263
- >Update current user data</sonic-button
264
- >
265
- <div class="flex flex-col gap-2 border p-2">
266
- <div>
267
- <sonic-icon name="user" library="heroicons"></sonic-icon>
268
- ${this.user?.firstName} ${this.user?.lastName}
269
- </div>
270
- <div>
271
- <sonic-icon name="envelope" library="heroicons"></sonic-icon>
272
- ${this.user?.email}
273
- </div>
274
- </div>
275
- </div>
276
- `;
277
- }
278
-
279
- </template>
280
- </sonic-code>
281
-
282
- <sonic-code>
283
- <template>
284
- <demo-bind-dynamic></demo-bind-dynamic>
285
- </template>
286
- </sonic-code>
287
-
288
- > ⚠️ Use a classic string literal: `@bind("${dataProvider}.${profileId}.info.title")`. Do **not** use a template literal (backticks), otherwise JavaScript would try to interpolate the value immediately.
289
- >
290
-
291
- Additional constraints:
292
-
293
- - The hosting class must expose a `willUpdate(changedProperties?: Map<PropertyKey, unknown>)` method (LitElement already le fournit) so that `@bind` peut écouter les changements de dépendances.
294
- - Dependencies need to be reactive (e.g. `@property()` on LitElement) or you must call `this.requestUpdate("myProp")` manually after changing them, otherwise `willUpdate` ne sera jamais notifié.
295
- - If you use nested expressions like `${user.id}`, the first segment (`user`) is the one being observed: you need to reassign `this.user` (e.g. with a new object) so that the binding can detect the change.
296
-
297
- ## Behavior
298
-
299
- - The property is automatically updated when the publisher's data changes
300
- - Subscription happens at the time of `connectedCallback`
301
- - Unsubscription happens automatically at the time of `disconnectedCallback`
302
- - If the path doesn't exist yet, a publisher is created with the value `null`
303
- - The value will be updated as soon as the data becomes available
304
-
305
-
306
- ## Use cases
307
-
308
- This decorator is particularly useful for:
309
-
310
- - **Binding properties** to specific data in a publisher
311
- - **Accessing sub-properties** without having to manually write subscription logic
312
- - **Simplifying code** by avoiding repetitive calls to `PublisherManager.get()` and `onAssign()`
313
-
314
- ## Complete example
315
-
316
- <sonic-code language="typescript">
317
- <template>
318
- import { html, LitElement } from "lit";
319
- import { customElement } from "lit/decorators.js";
320
- import { bind } from "@supersoniks/concorde/decorators";
321
- import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
322
- //
323
- @customElement("product-card")
324
- export class ProductCard extends LitElement {
325
- @bind("productData.name")
326
- @state()
327
- productName: string;
328
- //
329
- @bind("productData.price")
330
- @state()
331
- price: number;
332
- //
333
- @bind("productData.description")
334
- @state()
335
- description: string;
336
- //
337
- render() {
338
- return html`
339
- <div class="product-card">
340
- <h2>${this.productName}</h2>
341
- <p class="price">${this.price}€</p>
342
- <p>${this.description}</p>
343
- </div>
344
- `;
345
- }
346
- }
347
- // Somewhere in your code, update the data:
348
- const productPublisher = PublisherManager.get("productData");
349
- productPublisher.set({
350
- name: "Example product",
351
- price: 29.99,
352
- description: "A product description"
353
- });
354
- // The component properties will be automatically updated
355
- </template>
356
- </sonic-code>
357
-
358
- ## Notes
359
-
360
- - This decorator works with any component that has `connectedCallback` and `disconnectedCallback` methods (such as `LitElement` or components extending `Subscriber`)
361
- - Updates are reactive: any modification to the publisher triggers a property update
362
- - For more information about publishers, see the documentation on [Sharing data](#docs/_getting-started/pubsub.md/pubsub)
File without changes