@supersoniks/concorde 4.1.0 → 4.2.1

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.
@@ -4274,6 +4274,121 @@
4274
4274
  }
4275
4275
  }
4276
4276
  },
4277
+ {
4278
+ "search": "The @subscribe decorator is a simplified version of @bind without reflect. It accepts only Key<T> and enforces that the decorated property must be of type T:\n",
4279
+ "files": {
4280
+ "docs/_misc/bind.md": {
4281
+ "title": "@bind",
4282
+ "hashes": {
4283
+ "subscribe-read-only-strictly-typed-with-key": {
4284
+ "count": 1,
4285
+ "title": "@subscribe (read-only, strictly typed with Key)",
4286
+ "type": "paragraph"
4287
+ }
4288
+ }
4289
+ }
4290
+ }
4291
+ },
4292
+ {
4293
+ "search": "const statsKey = new Key("idDonneesDeStats");\n",
4294
+ "files": {
4295
+ "docs/_misc/bind.md": {
4296
+ "title": "@bind",
4297
+ "hashes": {
4298
+ "subscribe-read-only-strictly-typed-with-key": {
4299
+ "count": 1,
4300
+ "title": "@subscribe (read-only, strictly typed with Key)",
4301
+ "type": "paragraph"
4302
+ }
4303
+ }
4304
+ },
4305
+ "docs/_misc/key.md": {
4306
+ "title": "Key",
4307
+ "hashes": {
4308
+ "integration-with-subscribe": {
4309
+ "count": 1,
4310
+ "title": "Integration with @subscribe",
4311
+ "type": "paragraph"
4312
+ }
4313
+ }
4314
+ }
4315
+ }
4316
+ },
4317
+ {
4318
+ "search": "@subscribe(statsKey.gauge)\n@state()\ngauge: number = 0; // OK — matches Key\n",
4319
+ "files": {
4320
+ "docs/_misc/bind.md": {
4321
+ "title": "@bind",
4322
+ "hashes": {
4323
+ "subscribe-read-only-strictly-typed-with-key": {
4324
+ "count": 1,
4325
+ "title": "@subscribe (read-only, strictly typed with Key)",
4326
+ "type": "paragraph"
4327
+ }
4328
+ }
4329
+ }
4330
+ }
4331
+ },
4332
+ {
4333
+ "search": "// @subscribe(statsKey.gauge)\n// gauge: string = ""; // Error — type 'string' is not assignable to type 'number'\n \n\n",
4334
+ "files": {
4335
+ "docs/_misc/bind.md": {
4336
+ "title": "@bind",
4337
+ "hashes": {
4338
+ "subscribe-read-only-strictly-typed-with-key": {
4339
+ "count": 1,
4340
+ "title": "@subscribe (read-only, strictly typed with Key)",
4341
+ "type": "paragraph"
4342
+ }
4343
+ }
4344
+ }
4345
+ }
4346
+ },
4347
+ {
4348
+ "search": "The @publish decorator is the inverse of @subscribe: when you write to the property, the value is published to the publisher path. No subscription (no read from publisher).\n",
4349
+ "files": {
4350
+ "docs/_misc/bind.md": {
4351
+ "title": "@bind",
4352
+ "hashes": {
4353
+ "publish-write-only-inverse-of-subscribe": {
4354
+ "count": 1,
4355
+ "title": "@publish (write-only, inverse of @subscribe)",
4356
+ "type": "paragraph"
4357
+ }
4358
+ }
4359
+ }
4360
+ }
4361
+ },
4362
+ {
4363
+ "search": "const formKey = new Key("formData");\n",
4364
+ "files": {
4365
+ "docs/_misc/bind.md": {
4366
+ "title": "@bind",
4367
+ "hashes": {
4368
+ "publish-write-only-inverse-of-subscribe": {
4369
+ "count": 1,
4370
+ "title": "@publish (write-only, inverse of @subscribe)",
4371
+ "type": "paragraph"
4372
+ }
4373
+ }
4374
+ }
4375
+ }
4376
+ },
4377
+ {
4378
+ "search": "@publish(formKey.email)\n@state()\nemail = ""; // Writing to email publishes to formData.email\n \n\n",
4379
+ "files": {
4380
+ "docs/_misc/bind.md": {
4381
+ "title": "@bind",
4382
+ "hashes": {
4383
+ "publish-write-only-inverse-of-subscribe": {
4384
+ "count": 1,
4385
+ "title": "@publish (write-only, inverse of @subscribe)",
4386
+ "type": "paragraph"
4387
+ }
4388
+ }
4389
+ }
4390
+ }
4391
+ },
4277
4392
  {
4278
4393
  "search": "Lorsque vous avez besoin que les modifications locales se propagent également vers le publisher, activez l'option reflect :\n",
4279
4394
  "files": {
@@ -4344,6 +4459,21 @@
4344
4459
  }
4345
4460
  }
4346
4461
  },
4462
+ {
4463
+ "search": " }\n //\n render() {\n return html <div class="flex flex-col gap-2"> <sonic-select .value=${this.dataProvider} label="Users set" @change=${this.updateDataProvider} > <option value="demoUsers">First set of users</option> <option value="demoUsersAlt">Second set of users</option> </sonic-select> <sonic-input type="number" .value=${this.userIndex} @input=${this.updateUserIndex} min="0" max="9" label="Index" class="block" > </sonic-input> <sonic-button @click=${this.updateCurrentUserData} >Update current user data</sonic-button > <div class="flex flex-col gap-2 border p-2"> <div> <sonic-icon name="user" library="heroicons"></sonic-icon> ${this.user?.firstName} ${this.user?.lastName} </div> <div> <sonic-icon name="envelope" library="heroicons"></sonic-icon> ${this.user?.email} </div> </div> </div> ;\n }\n",
4464
+ "files": {
4465
+ "docs/_misc/bind.md": {
4466
+ "title": "@bind",
4467
+ "hashes": {
4468
+ "dynamic-path-driven-by-class-properties": {
4469
+ "count": 1,
4470
+ "title": "Dynamic path driven by class properties",
4471
+ "type": "paragraph"
4472
+ }
4473
+ }
4474
+ }
4475
+ }
4476
+ },
4347
4477
  {
4348
4478
  "search": "⚠️ 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.\n",
4349
4479
  "files": {
@@ -4371,6 +4501,211 @@
4371
4501
  "type": "paragraph"
4372
4502
  }
4373
4503
  }
4504
+ },
4505
+ "docs/_misc/on-assign.md": {
4506
+ "title": "@onAssign",
4507
+ "hashes": {
4508
+ "dynamic-path-driven-by-class-properties": {
4509
+ "count": 1,
4510
+ "title": "Dynamic path driven by class properties",
4511
+ "type": "paragraph"
4512
+ }
4513
+ }
4514
+ }
4515
+ }
4516
+ },
4517
+ {
4518
+ "search": "Key",
4519
+ "files": {
4520
+ "docs/_misc/key.md": {
4521
+ "title": "Key",
4522
+ "hashes": {
4523
+ "key": {
4524
+ "count": 1,
4525
+ "title": "",
4526
+ "type": "page"
4527
+ }
4528
+ }
4529
+ }
4530
+ }
4531
+ },
4532
+ {
4533
+ "search": "The Key<T> utility provides type-safe navigation through composite data structures. Each property or index access extends the path, and the final key can be retrieved via toString() or the path property.\n",
4534
+ "files": {
4535
+ "docs/_misc/key.md": {
4536
+ "title": "Key",
4537
+ "hashes": {
4538
+ "key": {
4539
+ "count": 1,
4540
+ "title": "",
4541
+ "type": "paragraph"
4542
+ }
4543
+ }
4544
+ }
4545
+ }
4546
+ },
4547
+ {
4548
+ "search": "Key uses a Proxy to intercept property access and build a cumulative path string. TypeScript infers the nested type at each level, so myKey.checkedTickets[0] is correctly typed as Key<LegacyCheckedTicket> when checkedTickets is LegacyCheckedTicket[].\n",
4549
+ "files": {
4550
+ "docs/_misc/key.md": {
4551
+ "title": "Key",
4552
+ "hashes": {
4553
+ "principle": {
4554
+ "count": 1,
4555
+ "title": "Principle",
4556
+ "type": "paragraph"
4557
+ }
4558
+ }
4559
+ }
4560
+ }
4561
+ },
4562
+ {
4563
+ "search": "// Create a key and navigate through the structure\nconst myKey = new Key("idDonneesDeStats").checkedTickets[0];\n",
4564
+ "files": {
4565
+ "docs/_misc/key.md": {
4566
+ "title": "Key",
4567
+ "hashes": {
4568
+ "basic-example": {
4569
+ "count": 1,
4570
+ "title": "Basic example",
4571
+ "type": "paragraph"
4572
+ }
4573
+ }
4574
+ }
4575
+ }
4576
+ },
4577
+ {
4578
+ "search": "// Equivalent to: new Key("idDonneesDeStats.checkedTickets.0")\nmyKey.toString(); // "idDonneesDeStats.checkedTickets.0"\nmyKey.path; // same value\n// myKey is typed as Key\n \n\n",
4579
+ "files": {
4580
+ "docs/_misc/key.md": {
4581
+ "title": "Key",
4582
+ "hashes": {
4583
+ "basic-example": {
4584
+ "count": 1,
4585
+ "title": "Basic example",
4586
+ "type": "paragraph"
4587
+ }
4588
+ }
4589
+ }
4590
+ }
4591
+ },
4592
+ {
4593
+ "search": "const firstTicket = ticketsKey[0];\nfirstTicket.path; // "data.checkedTickets.0"\n// firstTicket is Key\n \n\n",
4594
+ "files": {
4595
+ "docs/_misc/key.md": {
4596
+ "title": "Key",
4597
+ "hashes": {
4598
+ "array-index-access": {
4599
+ "count": 1,
4600
+ "title": "Array index access",
4601
+ "type": "paragraph"
4602
+ }
4603
+ }
4604
+ }
4605
+ }
4606
+ },
4607
+ {
4608
+ "search": "const key = Key("root");\nkey.path; // "root"\n \n\n",
4609
+ "files": {
4610
+ "docs/_misc/key.md": {
4611
+ "title": "Key",
4612
+ "hashes": {
4613
+ "usage-without-new": {
4614
+ "count": 1,
4615
+ "title": "Usage without `new`",
4616
+ "type": "paragraph"
4617
+ }
4618
+ }
4619
+ }
4620
+ }
4621
+ },
4622
+ {
4623
+ "search": "The final path is built by concatenating each accessed property with a dot:\n",
4624
+ "files": {
4625
+ "docs/_misc/key.md": {
4626
+ "title": "Key",
4627
+ "hashes": {
4628
+ "path-retrieval": {
4629
+ "count": 1,
4630
+ "title": "Path retrieval",
4631
+ "type": "paragraph"
4632
+ }
4633
+ }
4634
+ }
4635
+ }
4636
+ },
4637
+ {
4638
+ "search": "Use toString() or path to get the full path string:\n",
4639
+ "files": {
4640
+ "docs/_misc/key.md": {
4641
+ "title": "Key",
4642
+ "hashes": {
4643
+ "path-retrieval": {
4644
+ "count": 1,
4645
+ "title": "Path retrieval",
4646
+ "type": "paragraph"
4647
+ }
4648
+ }
4649
+ }
4650
+ }
4651
+ },
4652
+ {
4653
+ "search": "Use Key with the @subscribe decorator for strictly typed, read-only bindings (no reflect). The decorated property must match the Key type:\n",
4654
+ "files": {
4655
+ "docs/_misc/key.md": {
4656
+ "title": "Key",
4657
+ "hashes": {
4658
+ "integration-with-subscribe": {
4659
+ "count": 1,
4660
+ "title": "Integration with @subscribe",
4661
+ "type": "paragraph"
4662
+ }
4663
+ }
4664
+ }
4665
+ }
4666
+ },
4667
+ {
4668
+ "search": "@customElement("stats-gauge")\nexport class StatsGauge extends LitElement {\n @subscribe(statsKey.gauge)\n @state()\n gauge: number = 0; // Type enforced: must be number\n",
4669
+ "files": {
4670
+ "docs/_misc/key.md": {
4671
+ "title": "Key",
4672
+ "hashes": {
4673
+ "integration-with-subscribe": {
4674
+ "count": 1,
4675
+ "title": "Integration with @subscribe",
4676
+ "type": "paragraph"
4677
+ }
4678
+ }
4679
+ }
4680
+ }
4681
+ },
4682
+ {
4683
+ "search": " render() {\n return html<span>Gauge: ${this.gauge}</span>;\n }\n}\n \n\n",
4684
+ "files": {
4685
+ "docs/_misc/key.md": {
4686
+ "title": "Key",
4687
+ "hashes": {
4688
+ "integration-with-subscribe": {
4689
+ "count": 1,
4690
+ "title": "Integration with @subscribe",
4691
+ "type": "paragraph"
4692
+ }
4693
+ }
4694
+ }
4695
+ }
4696
+ },
4697
+ {
4698
+ "search": "If you declare gauge: string with @subscribe(statsKey.gauge) (Key), TypeScript will error.\n",
4699
+ "files": {
4700
+ "docs/_misc/key.md": {
4701
+ "title": "Key",
4702
+ "hashes": {
4703
+ "integration-with-subscribe": {
4704
+ "count": 1,
4705
+ "title": "Integration with @subscribe",
4706
+ "type": "paragraph"
4707
+ }
4708
+ }
4374
4709
  }
4375
4710
  }
4376
4711
  },
@@ -4434,6 +4769,51 @@
4434
4769
  }
4435
4770
  }
4436
4771
  },
4772
+ {
4773
+ "search": "You can now build the paths dynamically by referencing the host class properties inside the strings passed to @onAssign. Two placeholder syntaxes are supported:\n",
4774
+ "files": {
4775
+ "docs/_misc/on-assign.md": {
4776
+ "title": "@onAssign",
4777
+ "hashes": {
4778
+ "dynamic-path-driven-by-class-properties": {
4779
+ "count": 1,
4780
+ "title": "Dynamic path driven by class properties",
4781
+ "type": "paragraph"
4782
+ }
4783
+ }
4784
+ }
4785
+ }
4786
+ },
4787
+ {
4788
+ "search": "Each placeholder is replaced at runtime with the current value of the corresponding property. @onAssign automatically watches those properties and:\n",
4789
+ "files": {
4790
+ "docs/_misc/on-assign.md": {
4791
+ "title": "@onAssign",
4792
+ "hashes": {
4793
+ "dynamic-path-driven-by-class-properties": {
4794
+ "count": 1,
4795
+ "title": "Dynamic path driven by class properties",
4796
+ "type": "paragraph"
4797
+ }
4798
+ }
4799
+ }
4800
+ }
4801
+ },
4802
+ {
4803
+ "search": "⚠️ Use classic string literals: @onAssign("${dataProvider}.${profileId}", "settings.${profileId}"). Do not use template literals (backticks), otherwise JavaScript would try to interpolate the value immediately.\n",
4804
+ "files": {
4805
+ "docs/_misc/on-assign.md": {
4806
+ "title": "@onAssign",
4807
+ "hashes": {
4808
+ "dynamic-path-driven-by-class-properties": {
4809
+ "count": 1,
4810
+ "title": "Dynamic path driven by class properties",
4811
+ "type": "paragraph"
4812
+ }
4813
+ }
4814
+ }
4815
+ }
4816
+ },
4437
4817
  {
4438
4818
  "search": "Templates Demo",
4439
4819
  "files": {
@@ -4463,5 +4843,215 @@
4463
4843
  }
4464
4844
  }
4465
4845
  }
4846
+ },
4847
+ {
4848
+ "search": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4849
+ "files": {
4850
+ "docs/_misc/wait-for-ancestors.md": {
4851
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4852
+ "hashes": {
4853
+ "awaitconnectedancestors-and-dispatchconnectedevent": {
4854
+ "count": 1,
4855
+ "title": "",
4856
+ "type": "page"
4857
+ }
4858
+ }
4859
+ }
4860
+ }
4861
+ },
4862
+ {
4863
+ "search": "The @awaitConnectedAncestors and @dispatchConnectedEvent decorators delay a web component's initialization until its matching ancestors have executed their connectedCallback. This is when contextual elements (publisher, dataProvider, etc.) are configured.\n",
4864
+ "files": {
4865
+ "docs/_misc/wait-for-ancestors.md": {
4866
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4867
+ "hashes": {
4868
+ "awaitconnectedancestors-and-dispatchconnectedevent": {
4869
+ "count": 1,
4870
+ "title": "",
4871
+ "type": "paragraph"
4872
+ }
4873
+ }
4874
+ }
4875
+ }
4876
+ },
4877
+ {
4878
+ "search": "When a child component attaches to the DOM, its ancestors may not yet be initialized (especially if custom element definitions are loaded asynchronously). The @awaitConnectedAncestors decorator delays the component's connectedCallback until all ancestors matching the provided CSS selectors have executed their connectedCallback.\n",
4879
+ "files": {
4880
+ "docs/_misc/wait-for-ancestors.md": {
4881
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4882
+ "hashes": {
4883
+ "principle": {
4884
+ "count": 1,
4885
+ "title": "Principle",
4886
+ "type": "paragraph"
4887
+ }
4888
+ }
4889
+ }
4890
+ }
4891
+ },
4892
+ {
4893
+ "search": "The @dispatchConnectedEvent decorator allows ancestors to signal they are ready by dispatching the sonic-connected event at the end of their connectedCallback. The event bubbles, so it can be listened to from anywhere (e.g. document.addEventListener(CONNECTED, handler)).\n",
4894
+ "files": {
4895
+ "docs/_misc/wait-for-ancestors.md": {
4896
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4897
+ "hashes": {
4898
+ "principle": {
4899
+ "count": 1,
4900
+ "title": "Principle",
4901
+ "type": "paragraph"
4902
+ }
4903
+ }
4904
+ }
4905
+ }
4906
+ },
4907
+ {
4908
+ "search": "Ancestors that are not web components (no hyphen in tag name) are considered connected by default and do not need to emit the event.\n",
4909
+ "files": {
4910
+ "docs/_misc/wait-for-ancestors.md": {
4911
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4912
+ "hashes": {
4913
+ "principle": {
4914
+ "count": 1,
4915
+ "title": "Principle",
4916
+ "type": "paragraph"
4917
+ }
4918
+ }
4919
+ }
4920
+ }
4921
+ },
4922
+ {
4923
+ "search": "An ancestor container decorated with @dispatchConnectedEvent() signals when it is ready. A child component decorated with @awaitConnectedAncestors("demo-wait-ancestor-container[dataProvider]") waits for this container to be initialized before initializing itself. Parameters are CSS selectors (element.matches()).\n",
4924
+ "files": {
4925
+ "docs/_misc/wait-for-ancestors.md": {
4926
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4927
+ "hashes": {
4928
+ "basic-example": {
4929
+ "count": 1,
4930
+ "title": "Basic example",
4931
+ "type": "paragraph"
4932
+ }
4933
+ }
4934
+ }
4935
+ }
4936
+ },
4937
+ {
4938
+ "search": "The parent is registered via customElements.define() (vanilla JS) rather than @customElement, so it can be defined later—e.g. when the user clicks a button. This demonstrates the child waiting until the parent exists.\n",
4939
+ "files": {
4940
+ "docs/_misc/wait-for-ancestors.md": {
4941
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4942
+ "hashes": {
4943
+ "basic-example": {
4944
+ "count": 1,
4945
+ "title": "Basic example",
4946
+ "type": "paragraph"
4947
+ }
4948
+ }
4949
+ }
4950
+ }
4951
+ },
4952
+ {
4953
+ "search": "The child waits for all specified ancestors. Register outer first, then inner — the child initializes only when both are ready.\n",
4954
+ "files": {
4955
+ "docs/_misc/wait-for-ancestors.md": {
4956
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4957
+ "hashes": {
4958
+ "multiple-ancestors": {
4959
+ "count": 1,
4960
+ "title": "Multiple ancestors",
4961
+ "type": "paragraph"
4962
+ }
4963
+ }
4964
+ }
4965
+ }
4966
+ },
4967
+ {
4968
+ "search": "When the parent is defined at load and already in the DOM, the child initializes immediately (no delay).\n",
4969
+ "files": {
4970
+ "docs/_misc/wait-for-ancestors.md": {
4971
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4972
+ "hashes": {
4973
+ "ancestors-already-connected": {
4974
+ "count": 1,
4975
+ "title": "Ancestors already connected",
4976
+ "type": "paragraph"
4977
+ }
4978
+ }
4979
+ }
4980
+ }
4981
+ },
4982
+ {
4983
+ "search": "Static (both in DOM from start):\n",
4984
+ "files": {
4985
+ "docs/_misc/wait-for-ancestors.md": {
4986
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
4987
+ "hashes": {
4988
+ "ancestors-already-connected": {
4989
+ "count": 1,
4990
+ "title": "Ancestors already connected",
4991
+ "type": "paragraph"
4992
+ }
4993
+ }
4994
+ }
4995
+ }
4996
+ },
4997
+ {
4998
+ "search": "Dynamic (child added on button click):\n",
4999
+ "files": {
5000
+ "docs/_misc/wait-for-ancestors.md": {
5001
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
5002
+ "hashes": {
5003
+ "ancestors-already-connected": {
5004
+ "count": 1,
5005
+ "title": "Ancestors already connected",
5006
+ "type": "paragraph"
5007
+ }
5008
+ }
5009
+ }
5010
+ }
5011
+ },
5012
+ {
5013
+ "search": "Parameters are CSS selectors matched via element.matches() — e.g. "sonic-subscriber", "sonic-subscriber[dataProvider]", ".my-container", or multiple: "sonic-subscriber", "sonic-sdui".\n",
5014
+ "files": {
5015
+ "docs/_misc/wait-for-ancestors.md": {
5016
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
5017
+ "hashes": {
5018
+ "css-selector-support": {
5019
+ "count": 1,
5020
+ "title": "CSS selector support",
5021
+ "type": "paragraph"
5022
+ }
5023
+ }
5024
+ }
5025
+ }
5026
+ },
5027
+ {
5028
+ "search": "These decorators are particularly useful for:\n",
5029
+ "files": {
5030
+ "docs/_misc/wait-for-ancestors.md": {
5031
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
5032
+ "hashes": {
5033
+ "use-cases": {
5034
+ "count": 1,
5035
+ "title": "Use cases",
5036
+ "type": "paragraph"
5037
+ }
5038
+ }
5039
+ }
5040
+ }
5041
+ },
5042
+ {
5043
+ "search": "The sonic-connected event bubbles, so you can listen to it from anywhere:\n",
5044
+ "files": {
5045
+ "docs/_misc/wait-for-ancestors.md": {
5046
+ "title": "@awaitConnectedAncestors and @dispatchConnectedEvent",
5047
+ "hashes": {
5048
+ "listening-to-the-connected-event": {
5049
+ "count": 1,
5050
+ "title": "Listening to the connected event",
5051
+ "type": "paragraph"
5052
+ }
5053
+ }
5054
+ }
5055
+ }
4466
5056
  }
4467
5057
  ]
@@ -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,