@fusion.dev/helix-core 0.23.0 → 0.24.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.
@@ -1473,15 +1473,36 @@
1473
1473
  "text": "MutationObserver | undefined"
1474
1474
  }
1475
1475
  },
1476
+ {
1477
+ "kind": "field",
1478
+ "name": "#deferred",
1479
+ "privacy": "private",
1480
+ "type": {
1481
+ "text": "boolean"
1482
+ },
1483
+ "default": "false",
1484
+ "description": "Whether a hydrating render was told there was nothing, and needs the render after."
1485
+ },
1476
1486
  {
1477
1487
  "kind": "field",
1478
1488
  "name": "element",
1479
1489
  "type": {
1480
1490
  "text": "Element | null"
1481
1491
  },
1482
- "description": "The element `for` names, or null where there is nothing to name it in.\n\nNull on the server as well, since resolving an id wants a document. Every\nchart inherits that: the table is served whole and the drawing arrives on\nhydration.",
1492
+ "description": "The element `for` names, or null where there is nothing to name it in.\n\nNull on the server as well, since resolving an id wants a document. Every\nchart inherits that: the table is served whole and the drawing arrives on\nhydration.\n\n**And null while hydrating what a server sent**, which drew nothing, because\nthe render that hydrates has to be the server's: a drawing that differs is\na template Lit throws on. The update after it, which this asks for, draws.",
1483
1493
  "readonly": true
1484
1494
  },
1495
+ {
1496
+ "kind": "method",
1497
+ "name": "#resolve",
1498
+ "privacy": "private",
1499
+ "return": {
1500
+ "type": {
1501
+ "text": "Element | null"
1502
+ }
1503
+ },
1504
+ "description": "The element `for` names, whatever the host is rendering.\n\nApart from `element` because the watcher needs the table while a render\ncannot have it: attached on connect, which on a server's page is before\nthe render that hydrates, it resolved nothing there and never watched, so a\ntable a page filled afterwards drew no line."
1505
+ },
1485
1506
  {
1486
1507
  "kind": "field",
1487
1508
  "name": "series",
@@ -1500,6 +1521,15 @@
1500
1521
  }
1501
1522
  }
1502
1523
  },
1524
+ {
1525
+ "kind": "method",
1526
+ "name": "hostUpdated",
1527
+ "return": {
1528
+ "type": {
1529
+ "text": "void"
1530
+ }
1531
+ }
1532
+ },
1503
1533
  {
1504
1534
  "kind": "method",
1505
1535
  "name": "hostDisconnected",
@@ -1810,6 +1840,24 @@
1810
1840
  ],
1811
1841
  "description": "The last item that starts at or before `offset`.\n\nA binary search rather than a walk, so a reader dragging the thumb to the\nend of ten thousand rows costs fourteen comparisons rather than ten\nthousand."
1812
1842
  },
1843
+ {
1844
+ "kind": "method",
1845
+ "name": "shift",
1846
+ "return": {
1847
+ "type": {
1848
+ "text": "void"
1849
+ }
1850
+ },
1851
+ "parameters": [
1852
+ {
1853
+ "name": "by",
1854
+ "type": {
1855
+ "text": "number"
1856
+ }
1857
+ }
1858
+ ],
1859
+ "description": "Moves every height along by `by` places, for a set that grew at its start.\n\nA transcript loading its history prepends, and every item already measured\nis now `by` further down the set. Moved rather than forgotten, because the\nmeasurements are still true of the same items: forgetting would put every\none of them back at the estimate at the moment the reader is looking at them."
1860
+ },
1813
1861
  {
1814
1862
  "kind": "method",
1815
1863
  "name": "forget",
@@ -1949,6 +1997,16 @@
1949
1997
  "description": "Where each item starts, once any of them has been seen.",
1950
1998
  "default": "new Heights(() => this.options.estimate())"
1951
1999
  },
2000
+ {
2001
+ "kind": "field",
2002
+ "name": "owed",
2003
+ "type": {
2004
+ "text": "number"
2005
+ },
2006
+ "privacy": "private",
2007
+ "default": "0",
2008
+ "description": "Room `shift` added above the window, owed to the scroll offset once drawn."
2009
+ },
1952
2010
  {
1953
2011
  "kind": "method",
1954
2012
  "name": "hostConnected",
@@ -2083,6 +2141,24 @@
2083
2141
  },
2084
2142
  "description": "Measures what was just drawn, and holds the reader still if it moved.\n\n**This is the pass the fixed-estimate note warns about, made to terminate.**\nMeasuring after a render, and re-windowing on what was measured, is a loop\nthat feeds itself. What bounds it is that a height is news exactly once:\n`record` answers false for a size it already holds, so an item can move the\nwindow on the render that first shows it and never again. A set of ten\nthousand can therefore surprise this ten thousand times over its life and\nnot twice for the same row.\n\n**The scroll offset is corrected before anything is drawn again.** An item\nabove the window turning out taller than its estimate moves everything\nbelow it, including what the reader is looking at. Adding the same\ndifference to `scrollTop` puts the content back under them, which is why a\nlist of variable rows can be scrolled through without it walking away.\nSkipped at the very top, where there is nothing above to have moved."
2085
2143
  },
2144
+ {
2145
+ "kind": "method",
2146
+ "name": "shift",
2147
+ "return": {
2148
+ "type": {
2149
+ "text": "void"
2150
+ }
2151
+ },
2152
+ "parameters": [
2153
+ {
2154
+ "name": "by",
2155
+ "type": {
2156
+ "text": "number"
2157
+ }
2158
+ }
2159
+ ],
2160
+ "description": "Tells the controller the set grew by `by` items at its start.\n\nFor a host that prepends, which is what a transcript loading its history\ndoes. Every index the controller knew now names the item `by` places later,\nso the heights and the window move with them, and the scroll offset is moved\nby the room the new items take once they have been drawn. The reader stays\non the turn they were reading rather than on whatever now sits at their old\noffset, which is what loading history upward has to look like.\n\nCall it from `willUpdate`, before the render that draws the grown set."
2161
+ },
2086
2162
  {
2087
2163
  "kind": "method",
2088
2164
  "name": "forget",
@@ -2821,6 +2897,28 @@
2821
2897
  },
2822
2898
  "helix": {}
2823
2899
  },
2900
+ {
2901
+ "kind": "class",
2902
+ "description": "Fired when the reader changes which values a field is filtered by.\n\n**Not `helix-filter`, which is a different thing already taken.** That one\nsays a list narrowed itself to a string, and `Data Table` and `Listbox` both\ndispatch it with exactly that meaning. This one carries a structured filter:\na field, a comparison and a set of values, which is a shape neither of those\nhas and neither should grow.\n\nCancelable, and refusing it is how a consumer takes the decision for one\ninteraction, the way `requestChange` documents for every stateful change here.",
2903
+ "name": "HelixFacetEvent",
2904
+ "members": [
2905
+ {
2906
+ "kind": "field",
2907
+ "name": "eventName",
2908
+ "type": {
2909
+ "text": "string"
2910
+ },
2911
+ "static": true,
2912
+ "readonly": true,
2913
+ "default": "'helix-facet'"
2914
+ }
2915
+ ],
2916
+ "superclass": {
2917
+ "name": "CustomEvent",
2918
+ "module": "src/events/events.ts"
2919
+ },
2920
+ "helix": {}
2921
+ },
2824
2922
  {
2825
2923
  "kind": "class",
2826
2924
  "description": "Fired when a component narrows what it is showing.\n\nFiltering hides rather than removes, so nothing about the value changes and\n`helix-change` would be a lie. What a consumer wants to know is that the list\nin front of the reader is no longer the whole list.",
@@ -2887,6 +2985,50 @@
2887
2985
  },
2888
2986
  "helix": {}
2889
2987
  },
2988
+ {
2989
+ "kind": "class",
2990
+ "description": "Fired when the reader asks for the columns in a different order.\n\nCancelable, and refusing it leaves the columns where they were, so a consumer\nwho stores the order, in a URL or a preference, can take the decision the way\na server-side sort takes `helix-sort`. The detail is the whole order as\nspace-separated fields rather than one move, because the order is the fact a\nconsumer stores, and a move is only meaningful against an order they would\nthen have to keep in step.\n\nNot `helix-sort`: that reorders the rows, this reorders the columns, and a\nconsumer listening for one should not hear the other.",
2991
+ "name": "HelixReorderEvent",
2992
+ "members": [
2993
+ {
2994
+ "kind": "field",
2995
+ "name": "eventName",
2996
+ "type": {
2997
+ "text": "string"
2998
+ },
2999
+ "static": true,
3000
+ "readonly": true,
3001
+ "default": "'helix-reorder'"
3002
+ }
3003
+ ],
3004
+ "superclass": {
3005
+ "name": "CustomEvent",
3006
+ "module": "src/events/events.ts"
3007
+ },
3008
+ "helix": {}
3009
+ },
3010
+ {
3011
+ "kind": "class",
3012
+ "description": "Fired when a reader reaches the oldest turn a transcript holds, while there are\nolder ones to fetch.\n\n**A report of where the reader is, not a request to be granted**, so it is not\ncancelable: there is nothing for the transcript to do if nobody refuses, and\nnothing to stop if somebody does. The consumer answers by fetching, and says\nso through the transcript's `history` while the older turns are on their way.\n\nNo detail. The consumer holds the transcript and knows its oldest turn, which\nis the one thing a fetch needs.",
3013
+ "name": "HelixHistoryEvent",
3014
+ "members": [
3015
+ {
3016
+ "kind": "field",
3017
+ "name": "eventName",
3018
+ "type": {
3019
+ "text": "string"
3020
+ },
3021
+ "static": true,
3022
+ "readonly": true,
3023
+ "default": "'helix-history'"
3024
+ }
3025
+ ],
3026
+ "superclass": {
3027
+ "name": "CustomEvent",
3028
+ "module": "src/events/events.ts"
3029
+ },
3030
+ "helix": {}
3031
+ },
2890
3032
  {
2891
3033
  "kind": "variable",
2892
3034
  "name": "helixEventNames",
@@ -3130,6 +3272,14 @@
3130
3272
  "module": "src/events/events.ts"
3131
3273
  }
3132
3274
  },
3275
+ {
3276
+ "kind": "js",
3277
+ "name": "HelixFacetEvent",
3278
+ "declaration": {
3279
+ "name": "HelixFacetEvent",
3280
+ "module": "src/events/events.ts"
3281
+ }
3282
+ },
3133
3283
  {
3134
3284
  "kind": "js",
3135
3285
  "name": "HelixFilterEvent",
@@ -3154,6 +3304,22 @@
3154
3304
  "module": "src/events/events.ts"
3155
3305
  }
3156
3306
  },
3307
+ {
3308
+ "kind": "js",
3309
+ "name": "HelixReorderEvent",
3310
+ "declaration": {
3311
+ "name": "HelixReorderEvent",
3312
+ "module": "src/events/events.ts"
3313
+ }
3314
+ },
3315
+ {
3316
+ "kind": "js",
3317
+ "name": "HelixHistoryEvent",
3318
+ "declaration": {
3319
+ "name": "HelixHistoryEvent",
3320
+ "module": "src/events/events.ts"
3321
+ }
3322
+ },
3157
3323
  {
3158
3324
  "kind": "js",
3159
3325
  "name": "helixEventNames",
@@ -3256,6 +3422,102 @@
3256
3422
  "privacy": "private",
3257
3423
  "description": "Resolves `whenSettled`, once, from the frame that records the state."
3258
3424
  },
3425
+ {
3426
+ "kind": "field",
3427
+ "name": "fromServer",
3428
+ "type": {
3429
+ "text": "boolean"
3430
+ },
3431
+ "privacy": "private",
3432
+ "default": "false",
3433
+ "description": "Whether the shadow root was a server's, parsed from declarative shadow DOM."
3434
+ },
3435
+ {
3436
+ "kind": "field",
3437
+ "name": "hydrating",
3438
+ "type": {
3439
+ "text": "boolean"
3440
+ },
3441
+ "privacy": "protected",
3442
+ "description": "Whether this update is hydrating a server's markup, and so has to render\nexactly what the server rendered.\n\n**Lit hydrates by assuming the markup already shows the first render.** A\nvalue that differs is recorded and never written, so the page keeps the\nserver's, and a template that differs throws. The server has no children,\nso anything a component reads from its children waits for the update after\nhydration, which `finishHydration` asks for. Without a server's markup the\nfirst render reads them and there is one render.",
3443
+ "readonly": true
3444
+ },
3445
+ {
3446
+ "kind": "field",
3447
+ "name": "serverRendered",
3448
+ "type": {
3449
+ "text": "boolean"
3450
+ },
3451
+ "privacy": "protected",
3452
+ "description": "Whether this element hydrated a server's markup rather than rendering its own.\n\nFor what happened before hydration and cannot be heard after it: an image\nthe parser fetched fires `load` or `error` before any listener exists, so a\ncomponent asks the image instead, once, when this is true.",
3453
+ "readonly": true
3454
+ },
3455
+ {
3456
+ "kind": "method",
3457
+ "name": "finishHydration",
3458
+ "privacy": "protected",
3459
+ "return": {
3460
+ "type": {
3461
+ "text": "void"
3462
+ }
3463
+ },
3464
+ "description": "Asks for the update a hydration put off, so the reads it skipped happen.\n\nCalled from `firstUpdated`, the end of the hydrating update. The render it\nschedules can only follow that one, which is the exception Lit's\nchange-in-update warning names, and it happens only on a page a server\nrendered."
3465
+ },
3466
+ {
3467
+ "kind": "field",
3468
+ "name": "childrenKnown",
3469
+ "type": {
3470
+ "text": "boolean"
3471
+ },
3472
+ "privacy": "protected",
3473
+ "description": "Whether this render can know the children.\n\nA server cannot: its element shim carries attributes and no tree, so\n`children` is undefined there. A render hydrating what a server sent must\nnot, because it has to be the server's render. Anywhere else it can. A\ncomponent whose render depends on its children reads them through\n`knownChildren`, and treats \"not known\" as its own answer rather than as\n\"none\": a list that renders its empty state because nobody has looked yet is\nthe one thing an empty state must never do.",
3474
+ "readonly": true
3475
+ },
3476
+ {
3477
+ "kind": "field",
3478
+ "name": "knownChildren",
3479
+ "type": {
3480
+ "text": "Element[]"
3481
+ },
3482
+ "privacy": "protected",
3483
+ "description": "The children a render may read: all of them where they are known, and none otherwise.",
3484
+ "readonly": true
3485
+ },
3486
+ {
3487
+ "kind": "field",
3488
+ "name": "assignsByName",
3489
+ "type": {
3490
+ "text": "boolean"
3491
+ },
3492
+ "privacy": "protected",
3493
+ "description": "Whether this element's slots route by name although it asked to assign them\nby hand.\n\n**A declarative shadow root is always the by-name kind.** HTML has no way to\nask for manual assignment, so a component that assigns by hand and hydrates\na server's root gets one where `slot.assign()` does nothing, and its\nchildren land wherever their `slot` attribute sends them. The way through is\nto write that attribute, which is what `route` does. Only there: on a root\nthis element made, assignment stays manual and the consumer's markup is\nnever touched, which is what a React consumer's hydration requires.",
3494
+ "readonly": true
3495
+ },
3496
+ {
3497
+ "kind": "method",
3498
+ "name": "route",
3499
+ "privacy": "protected",
3500
+ "return": {
3501
+ "type": {
3502
+ "text": "void"
3503
+ }
3504
+ },
3505
+ "parameters": [
3506
+ {
3507
+ "name": "child",
3508
+ "type": {
3509
+ "text": "Element"
3510
+ }
3511
+ },
3512
+ {
3513
+ "name": "name",
3514
+ "type": {
3515
+ "text": "string | undefined"
3516
+ }
3517
+ }
3518
+ ],
3519
+ "description": "Sends a child to a slot by name, on a root that routes by name.\n\n`undefined` is the default slot. Written only when it differs, so routing\nthe same child again on every update writes nothing."
3520
+ },
3259
3521
  {
3260
3522
  "kind": "field",
3261
3523
  "name": "stopInner",
@@ -3324,6 +3586,30 @@
3324
3586
  "tier": "core"
3325
3587
  },
3326
3588
  "customElement": true
3589
+ },
3590
+ {
3591
+ "kind": "function",
3592
+ "name": "whenHydrated",
3593
+ "return": {
3594
+ "type": {
3595
+ "text": "void"
3596
+ }
3597
+ },
3598
+ "parameters": [
3599
+ {
3600
+ "name": "element",
3601
+ "type": {
3602
+ "text": "Element"
3603
+ }
3604
+ },
3605
+ {
3606
+ "name": "write",
3607
+ "type": {
3608
+ "text": "() => void"
3609
+ }
3610
+ }
3611
+ ],
3612
+ "description": "Writes to a child element once it has hydrated, or now where it is not\nhydrating.\n\n**For a parent that sets state on the elements it holds.** On a page a server\nrendered, the parent's `updated` can run before a child's own first update,\nand a property written then is in the child's hydrating render, which has to\nbe the server's: a mark the markup never showed, and Lit throws. Waiting for\nthat render lets it match and the write land in the one after. Anywhere else\nthe write is immediate, so a client's first render already has it."
3327
3613
  }
3328
3614
  ],
3329
3615
  "exports": [
@@ -3334,6 +3620,14 @@
3334
3620
  "name": "HelixElement",
3335
3621
  "module": "src/helix-element/helix-element.ts"
3336
3622
  }
3623
+ },
3624
+ {
3625
+ "kind": "js",
3626
+ "name": "whenHydrated",
3627
+ "declaration": {
3628
+ "name": "whenHydrated",
3629
+ "module": "src/helix-element/helix-element.ts"
3630
+ }
3337
3631
  }
3338
3632
  ]
3339
3633
  },
@@ -3548,6 +3842,134 @@
3548
3842
  "module": "src/helix-element/helix-element.ts"
3549
3843
  }
3550
3844
  },
3845
+ {
3846
+ "kind": "field",
3847
+ "name": "fromServer",
3848
+ "type": {
3849
+ "text": "boolean"
3850
+ },
3851
+ "privacy": "private",
3852
+ "default": "false",
3853
+ "description": "Whether the shadow root was a server's, parsed from declarative shadow DOM.",
3854
+ "inheritedFrom": {
3855
+ "name": "HelixElement",
3856
+ "module": "src/helix-element/helix-element.ts"
3857
+ }
3858
+ },
3859
+ {
3860
+ "kind": "field",
3861
+ "name": "hydrating",
3862
+ "type": {
3863
+ "text": "boolean"
3864
+ },
3865
+ "privacy": "protected",
3866
+ "description": "Whether this update is hydrating a server's markup, and so has to render\nexactly what the server rendered.\n\n**Lit hydrates by assuming the markup already shows the first render.** A\nvalue that differs is recorded and never written, so the page keeps the\nserver's, and a template that differs throws. The server has no children,\nso anything a component reads from its children waits for the update after\nhydration, which `finishHydration` asks for. Without a server's markup the\nfirst render reads them and there is one render.",
3867
+ "readonly": true,
3868
+ "inheritedFrom": {
3869
+ "name": "HelixElement",
3870
+ "module": "src/helix-element/helix-element.ts"
3871
+ }
3872
+ },
3873
+ {
3874
+ "kind": "field",
3875
+ "name": "serverRendered",
3876
+ "type": {
3877
+ "text": "boolean"
3878
+ },
3879
+ "privacy": "protected",
3880
+ "description": "Whether this element hydrated a server's markup rather than rendering its own.\n\nFor what happened before hydration and cannot be heard after it: an image\nthe parser fetched fires `load` or `error` before any listener exists, so a\ncomponent asks the image instead, once, when this is true.",
3881
+ "readonly": true,
3882
+ "inheritedFrom": {
3883
+ "name": "HelixElement",
3884
+ "module": "src/helix-element/helix-element.ts"
3885
+ }
3886
+ },
3887
+ {
3888
+ "kind": "method",
3889
+ "name": "finishHydration",
3890
+ "privacy": "protected",
3891
+ "return": {
3892
+ "type": {
3893
+ "text": "void"
3894
+ }
3895
+ },
3896
+ "description": "Asks for the update a hydration put off, so the reads it skipped happen.\n\nCalled from `firstUpdated`, the end of the hydrating update. The render it\nschedules can only follow that one, which is the exception Lit's\nchange-in-update warning names, and it happens only on a page a server\nrendered.",
3897
+ "inheritedFrom": {
3898
+ "name": "HelixElement",
3899
+ "module": "src/helix-element/helix-element.ts"
3900
+ }
3901
+ },
3902
+ {
3903
+ "kind": "field",
3904
+ "name": "childrenKnown",
3905
+ "type": {
3906
+ "text": "boolean"
3907
+ },
3908
+ "privacy": "protected",
3909
+ "description": "Whether this render can know the children.\n\nA server cannot: its element shim carries attributes and no tree, so\n`children` is undefined there. A render hydrating what a server sent must\nnot, because it has to be the server's render. Anywhere else it can. A\ncomponent whose render depends on its children reads them through\n`knownChildren`, and treats \"not known\" as its own answer rather than as\n\"none\": a list that renders its empty state because nobody has looked yet is\nthe one thing an empty state must never do.",
3910
+ "readonly": true,
3911
+ "inheritedFrom": {
3912
+ "name": "HelixElement",
3913
+ "module": "src/helix-element/helix-element.ts"
3914
+ }
3915
+ },
3916
+ {
3917
+ "kind": "field",
3918
+ "name": "knownChildren",
3919
+ "type": {
3920
+ "text": "Element[]"
3921
+ },
3922
+ "privacy": "protected",
3923
+ "description": "The children a render may read: all of them where they are known, and none otherwise.",
3924
+ "readonly": true,
3925
+ "inheritedFrom": {
3926
+ "name": "HelixElement",
3927
+ "module": "src/helix-element/helix-element.ts"
3928
+ }
3929
+ },
3930
+ {
3931
+ "kind": "field",
3932
+ "name": "assignsByName",
3933
+ "type": {
3934
+ "text": "boolean"
3935
+ },
3936
+ "privacy": "protected",
3937
+ "description": "Whether this element's slots route by name although it asked to assign them\nby hand.\n\n**A declarative shadow root is always the by-name kind.** HTML has no way to\nask for manual assignment, so a component that assigns by hand and hydrates\na server's root gets one where `slot.assign()` does nothing, and its\nchildren land wherever their `slot` attribute sends them. The way through is\nto write that attribute, which is what `route` does. Only there: on a root\nthis element made, assignment stays manual and the consumer's markup is\nnever touched, which is what a React consumer's hydration requires.",
3938
+ "readonly": true,
3939
+ "inheritedFrom": {
3940
+ "name": "HelixElement",
3941
+ "module": "src/helix-element/helix-element.ts"
3942
+ }
3943
+ },
3944
+ {
3945
+ "kind": "method",
3946
+ "name": "route",
3947
+ "privacy": "protected",
3948
+ "return": {
3949
+ "type": {
3950
+ "text": "void"
3951
+ }
3952
+ },
3953
+ "parameters": [
3954
+ {
3955
+ "name": "child",
3956
+ "type": {
3957
+ "text": "Element"
3958
+ }
3959
+ },
3960
+ {
3961
+ "name": "name",
3962
+ "type": {
3963
+ "text": "string | undefined"
3964
+ }
3965
+ }
3966
+ ],
3967
+ "description": "Sends a child to a slot by name, on a root that routes by name.\n\n`undefined` is the default slot. Written only when it differs, so routing\nthe same child again on every update writes nothing.",
3968
+ "inheritedFrom": {
3969
+ "name": "HelixElement",
3970
+ "module": "src/helix-element/helix-element.ts"
3971
+ }
3972
+ },
3551
3973
  {
3552
3974
  "kind": "field",
3553
3975
  "name": "stopInner",
@@ -4017,6 +4439,14 @@
4017
4439
  "module": "./events/events.js"
4018
4440
  }
4019
4441
  },
4442
+ {
4443
+ "kind": "js",
4444
+ "name": "FacetDetail",
4445
+ "declaration": {
4446
+ "name": "FacetDetail",
4447
+ "module": "./events/events.js"
4448
+ }
4449
+ },
4020
4450
  {
4021
4451
  "kind": "js",
4022
4452
  "name": "FilterDetail",
@@ -4169,6 +4599,14 @@
4169
4599
  "module": "./events/events.js"
4170
4600
  }
4171
4601
  },
4602
+ {
4603
+ "kind": "js",
4604
+ "name": "HelixFacetEvent",
4605
+ "declaration": {
4606
+ "name": "HelixFacetEvent",
4607
+ "module": "./events/events.js"
4608
+ }
4609
+ },
4172
4610
  {
4173
4611
  "kind": "js",
4174
4612
  "name": "HelixFilterEvent",
@@ -4177,6 +4615,14 @@
4177
4615
  "module": "./events/events.js"
4178
4616
  }
4179
4617
  },
4618
+ {
4619
+ "kind": "js",
4620
+ "name": "HelixHistoryEvent",
4621
+ "declaration": {
4622
+ "name": "HelixHistoryEvent",
4623
+ "module": "./events/events.js"
4624
+ }
4625
+ },
4180
4626
  {
4181
4627
  "kind": "js",
4182
4628
  "name": "HelixNavigateEvent",
@@ -4209,6 +4655,14 @@
4209
4655
  "module": "./events/events.js"
4210
4656
  }
4211
4657
  },
4658
+ {
4659
+ "kind": "js",
4660
+ "name": "HelixReorderEvent",
4661
+ "declaration": {
4662
+ "name": "HelixReorderEvent",
4663
+ "module": "./events/events.js"
4664
+ }
4665
+ },
4212
4666
  {
4213
4667
  "kind": "js",
4214
4668
  "name": "HelixResizeEvent",
@@ -4377,6 +4831,14 @@
4377
4831
  "module": "./helix-element/helix-element.js"
4378
4832
  }
4379
4833
  },
4834
+ {
4835
+ "kind": "js",
4836
+ "name": "whenHydrated",
4837
+ "declaration": {
4838
+ "name": "whenHydrated",
4839
+ "module": "./helix-element/helix-element.js"
4840
+ }
4841
+ },
4380
4842
  {
4381
4843
  "kind": "js",
4382
4844
  "name": "HelixFormElement",
@@ -5448,6 +5910,16 @@
5448
5910
  ],
5449
5911
  "description": "Binds to a rows slot's `slotchange`, and answers `hasRows` from it."
5450
5912
  },
5913
+ {
5914
+ "kind": "field",
5915
+ "name": "slotted",
5916
+ "type": {
5917
+ "text": "Element[]"
5918
+ },
5919
+ "privacy": "protected",
5920
+ "description": "What the rows slot is given, read from the host so a first render has it.",
5921
+ "readonly": true
5922
+ },
5451
5923
  {
5452
5924
  "kind": "field",
5453
5925
  "name": "hasRows",
@@ -5515,7 +5987,7 @@
5515
5987
  },
5516
5988
  "privacy": "private",
5517
5989
  "default": "0",
5518
- "description": "How many there were, the last time anyone looked.\n\n**Never name this `rows`.** TypeScript's `private` is a compile-time\nclaim and the runtime field is whatever it is named, so a subclass\ndeclaring `@property() rows` for the data a consumer hands it would share\none field with this counter: the slot count would overwrite the\nconsumer's array on every `updated`, and `hasRows` would read the array's\nlength as a slot count. Nothing would throw. `helix-data-table` takes\nexactly that property."
5990
+ "description": "How many there were, the last time anyone looked.\n\n**Never name this `rows`.** TypeScript's `private` is a compile-time\nclaim and the runtime field is whatever it is named, so a subclass\ndeclaring `@property() rows` for the data a consumer hands it would share\none field with this counter: the slot count would overwrite the\nconsumer's array on every update, and `hasRows` would read the array's\nlength as a slot count. Nothing would throw. `helix-data-table` takes\nexactly that property."
5519
5991
  },
5520
5992
  {
5521
5993
  "kind": "method",
@@ -5545,6 +6017,16 @@
5545
6017
  "privacy": "protected",
5546
6018
  "readonly": true
5547
6019
  },
6020
+ {
6021
+ "kind": "field",
6022
+ "name": "slotted",
6023
+ "type": {
6024
+ "text": "Element[]"
6025
+ },
6026
+ "privacy": "protected",
6027
+ "description": "What the rows slot is given: every child without a `slot`.\n\nThe default slot, because that is where every collection in this library\nputs its rows: Listbox its options, Tree its items, Table its rows, Menu\nand Drilldown their pages. A named slot is a header or a footer, and\nneither is content.\n\n**The host's children rather than the slot's assigned elements**, which\nare the same elements, because a slot exists only once a render has made\nit and the count is wanted by the first render. A collection that assigns\nits slots by hand says what it assigns.",
6028
+ "readonly": true
6029
+ },
5548
6030
  {
5549
6031
  "kind": "method",
5550
6032
  "name": "renderStatus",
@@ -36,11 +36,16 @@ export declare class SourceController implements ReactiveController {
36
36
  * Null on the server as well, since resolving an id wants a document. Every
37
37
  * chart inherits that: the table is served whole and the drawing arrives on
38
38
  * hydration.
39
+ *
40
+ * **And null while hydrating what a server sent**, which drew nothing, because
41
+ * the render that hydrates has to be the server's: a drawing that differs is
42
+ * a template Lit throws on. The update after it, which this asks for, draws.
39
43
  */
40
44
  get element(): Element | null;
41
45
  /** The series it holds, or none. */
42
46
  get series(): Series[];
43
47
  hostConnected(): void;
48
+ hostUpdated(): void;
44
49
  hostDisconnected(): void;
45
50
  /**
46
51
  * Points the watcher at whatever `for` names now.
@@ -2,11 +2,19 @@ import { readSeries } from '../../utils/read-series/read-series.js';
2
2
  export class SourceController {
3
3
  #host;
4
4
  #observer;
5
+ #deferred = false;
5
6
  constructor(host) {
6
7
  this.#host = host;
7
8
  host.addController(this);
8
9
  }
9
10
  get element() {
11
+ if (this.#host.hydrating === true) {
12
+ this.#deferred = this.#host.for !== '';
13
+ return null;
14
+ }
15
+ return this.#resolve();
16
+ }
17
+ #resolve() {
10
18
  const host = this.#host;
11
19
  if (host.for === '') {
12
20
  return null;
@@ -31,13 +39,19 @@ export class SourceController {
31
39
  hostConnected() {
32
40
  this.watch();
33
41
  }
42
+ hostUpdated() {
43
+ if (this.#deferred) {
44
+ this.#deferred = false;
45
+ this.#host.requestUpdate();
46
+ }
47
+ }
34
48
  hostDisconnected() {
35
49
  this.#observer?.disconnect();
36
50
  this.#observer = undefined;
37
51
  }
38
52
  watch() {
39
53
  this.#observer?.disconnect();
40
- const element = this.element;
54
+ const element = this.#resolve();
41
55
  if (!element || typeof MutationObserver === 'undefined') {
42
56
  return;
43
57
  }
@@ -52,6 +52,15 @@ export declare class Heights {
52
52
  * thousand.
53
53
  */
54
54
  indexAt(offset: number, count: number): number;
55
+ /**
56
+ * Moves every height along by `by` places, for a set that grew at its start.
57
+ *
58
+ * A transcript loading its history prepends, and every item already measured
59
+ * is now `by` further down the set. Moved rather than forgotten, because the
60
+ * measurements are still true of the same items: forgetting would put every
61
+ * one of them back at the estimate at the moment the reader is looking at them.
62
+ */
63
+ shift(by: number): void;
55
64
  /**
56
65
  * Drops everything, for a set that is no longer the same set.
57
66
  *
@@ -51,6 +51,19 @@ export class Heights {
51
51
  }
52
52
  return Math.min(low, count - 1);
53
53
  }
54
+ shift(by) {
55
+ if (by === 0) {
56
+ return;
57
+ }
58
+ const moved = [...this.seen].map(([index, size]) => [index + by, size]);
59
+ this.seen.clear();
60
+ for (const [index, size] of moved) {
61
+ if (index >= 0) {
62
+ this.seen.set(index, size);
63
+ }
64
+ }
65
+ this.dirty = 0;
66
+ }
54
67
  forget() {
55
68
  this.seen.clear();
56
69
  this.dirty = 0;
@@ -138,6 +138,8 @@ export declare class VirtualizeController implements ReactiveController {
138
138
  window: Window;
139
139
  /** Where each item starts, once any of them has been seen. */
140
140
  private readonly heights;
141
+ /** Room `shift` added above the window, owed to the scroll offset once drawn. */
142
+ private owed;
141
143
  constructor(host: ReactiveControllerHost, options: VirtualizeOptions);
142
144
  hostConnected(): void;
143
145
  hostDisconnected(): void;
@@ -183,6 +185,19 @@ export declare class VirtualizeController implements ReactiveController {
183
185
  * Skipped at the very top, where there is nothing above to have moved.
184
186
  */
185
187
  hostUpdated(): void;
188
+ /**
189
+ * Tells the controller the set grew by `by` items at its start.
190
+ *
191
+ * For a host that prepends, which is what a transcript loading its history
192
+ * does. Every index the controller knew now names the item `by` places later,
193
+ * so the heights and the window move with them, and the scroll offset is moved
194
+ * by the room the new items take once they have been drawn. The reader stays
195
+ * on the turn they were reading rather than on whatever now sits at their old
196
+ * offset, which is what loading history upward has to look like.
197
+ *
198
+ * Call it from `willUpdate`, before the render that draws the grown set.
199
+ */
200
+ shift(by: number): void;
186
201
  /**
187
202
  * Drops every measurement, for a host that swapped its data.
188
203
  *
@@ -6,6 +6,7 @@ export class VirtualizeController {
6
6
  this.settling = 0;
7
7
  this.warned = false;
8
8
  this.window = { after: 0, before: 0, first: 0, last: 0 };
9
+ this.owed = 0;
9
10
  this.handleScroll = () => {
10
11
  this.settling = 0;
11
12
  this.measure();
@@ -95,6 +96,13 @@ export class VirtualizeController {
95
96
  };
96
97
  }
97
98
  hostUpdated() {
99
+ if (this.owed !== 0) {
100
+ const box = this.options.container();
101
+ if (box) {
102
+ box.scrollTop += this.owed;
103
+ }
104
+ this.owed = 0;
105
+ }
98
106
  if (!this.measuring()) {
99
107
  return;
100
108
  }
@@ -121,6 +129,21 @@ export class VirtualizeController {
121
129
  }
122
130
  this.measure();
123
131
  }
132
+ shift(by) {
133
+ if (by <= 0) {
134
+ return;
135
+ }
136
+ const count = Math.max(0, this.options.count());
137
+ this.heights.shift(by);
138
+ const room = this.heights.before(by, count);
139
+ this.window = {
140
+ ...this.window,
141
+ before: this.window.before + room,
142
+ first: this.window.first + by,
143
+ last: this.window.last + by,
144
+ };
145
+ this.owed += room;
146
+ }
124
147
  forget() {
125
148
  this.heights.forget();
126
149
  }
@@ -80,6 +80,43 @@ export interface FilterDetail {
80
80
  /** What the list is being narrowed to. */
81
81
  value: string;
82
82
  }
83
+ /**
84
+ * Detail carried by `helix-facet`.
85
+ *
86
+ * **Everything needed to draw the chip, so nothing has to be looked up again.**
87
+ * A consumer hearing this renders a `FilterChip` from it and stops: the labels
88
+ * are the reader's words and the names are their own model's, and both are here
89
+ * because only the thing that read the declarations knows both.
90
+ */
91
+ export interface FacetDetail {
92
+ /**
93
+ * How many values the comparison in force takes.
94
+ *
95
+ * **What tells an empty filter from no filter.** `values` empty usually means
96
+ * the field is not being filtered any more, and a consumer drops the chip; a
97
+ * comparison of arity `none`, `is empty` or `is set`, is a filter that has no
98
+ * values to carry and never will. Without this the two arrive identical, and
99
+ * the thing that read the declaration is the only thing that could say which.
100
+ */
101
+ arity: 'many' | 'none' | 'one';
102
+ /** What the consumer's model calls the field. */
103
+ field: string;
104
+ /** What a reader is shown for the field. */
105
+ label: string;
106
+ /** What the consumer's model calls the comparison in force. */
107
+ operator: string;
108
+ /**
109
+ * The comparison as a reader sees it, and **empty for the field's usual one**.
110
+ *
111
+ * Passed straight to a chip's `operator-label`, which draws the segment only
112
+ * where there is one. Deciding it here is the point: the thing that read the
113
+ * field knows which of its operators is the default, and the chip never has
114
+ * to.
115
+ */
116
+ operatorLabel: string;
117
+ /** What the field is compared to, as the consumer's own values. */
118
+ values: readonly string[];
119
+ }
83
120
  /** Detail carried by `helix-read`. */
84
121
  export interface ReadDetail {
85
122
  /**
@@ -589,6 +626,22 @@ export declare class HelixSortEvent extends CustomEvent<SortDetail> {
589
626
  static readonly eventName = "helix-sort";
590
627
  constructor(detail: SortDetail);
591
628
  }
629
+ /**
630
+ * Fired when the reader changes which values a field is filtered by.
631
+ *
632
+ * **Not `helix-filter`, which is a different thing already taken.** That one
633
+ * says a list narrowed itself to a string, and `Data Table` and `Listbox` both
634
+ * dispatch it with exactly that meaning. This one carries a structured filter:
635
+ * a field, a comparison and a set of values, which is a shape neither of those
636
+ * has and neither should grow.
637
+ *
638
+ * Cancelable, and refusing it is how a consumer takes the decision for one
639
+ * interaction, the way `requestChange` documents for every stateful change here.
640
+ */
641
+ export declare class HelixFacetEvent extends CustomEvent<FacetDetail> {
642
+ static readonly eventName = "helix-facet";
643
+ constructor(detail: FacetDetail);
644
+ }
592
645
  /**
593
646
  * Fired when a component narrows what it is showing.
594
647
  *
@@ -633,6 +686,39 @@ export declare class HelixSelectEvent extends CustomEvent<SelectDetail> {
633
686
  static readonly eventName = "helix-select";
634
687
  constructor(detail: SelectDetail);
635
688
  }
689
+ /**
690
+ * Fired when the reader asks for the columns in a different order.
691
+ *
692
+ * Cancelable, and refusing it leaves the columns where they were, so a consumer
693
+ * who stores the order, in a URL or a preference, can take the decision the way
694
+ * a server-side sort takes `helix-sort`. The detail is the whole order as
695
+ * space-separated fields rather than one move, because the order is the fact a
696
+ * consumer stores, and a move is only meaningful against an order they would
697
+ * then have to keep in step.
698
+ *
699
+ * Not `helix-sort`: that reorders the rows, this reorders the columns, and a
700
+ * consumer listening for one should not hear the other.
701
+ */
702
+ export declare class HelixReorderEvent extends CustomEvent<ChangeDetail> {
703
+ static readonly eventName = "helix-reorder";
704
+ constructor(detail: ChangeDetail);
705
+ }
706
+ /**
707
+ * Fired when a reader reaches the oldest turn a transcript holds, while there are
708
+ * older ones to fetch.
709
+ *
710
+ * **A report of where the reader is, not a request to be granted**, so it is not
711
+ * cancelable: there is nothing for the transcript to do if nobody refuses, and
712
+ * nothing to stop if somebody does. The consumer answers by fetching, and says
713
+ * so through the transcript's `history` while the older turns are on their way.
714
+ *
715
+ * No detail. The consumer holds the transcript and knows its oldest turn, which
716
+ * is the one thing a fetch needs.
717
+ */
718
+ export declare class HelixHistoryEvent extends CustomEvent<Record<string, never>> {
719
+ static readonly eventName = "helix-history";
720
+ constructor();
721
+ }
636
722
  /**
637
723
  * Every event this file publishes, and the one place a new one is added.
638
724
  *
@@ -663,11 +749,14 @@ declare const registry: {
663
749
  readonly HelixCopyEvent: typeof HelixCopyEvent;
664
750
  readonly HelixCreateEvent: typeof HelixCreateEvent;
665
751
  readonly HelixDismissEvent: typeof HelixDismissEvent;
752
+ readonly HelixFacetEvent: typeof HelixFacetEvent;
666
753
  readonly HelixFilterEvent: typeof HelixFilterEvent;
754
+ readonly HelixHistoryEvent: typeof HelixHistoryEvent;
667
755
  readonly HelixNavigateEvent: typeof HelixNavigateEvent;
668
756
  readonly HelixNextEvent: typeof HelixNextEvent;
669
757
  readonly HelixPreviousEvent: typeof HelixPreviousEvent;
670
758
  readonly HelixReadEvent: typeof HelixReadEvent;
759
+ readonly HelixReorderEvent: typeof HelixReorderEvent;
671
760
  readonly HelixResizeEvent: typeof HelixResizeEvent;
672
761
  readonly HelixSampleEndEvent: typeof HelixSampleEndEvent;
673
762
  readonly HelixSampleStartEvent: typeof HelixSampleStartEvent;
@@ -306,6 +306,17 @@ export class HelixSortEvent extends CustomEvent {
306
306
  });
307
307
  }
308
308
  }
309
+ export class HelixFacetEvent extends CustomEvent {
310
+ static { this.eventName = 'helix-facet'; }
311
+ constructor(detail) {
312
+ super(HelixFacetEvent.eventName, {
313
+ bubbles: true,
314
+ cancelable: true,
315
+ composed: true,
316
+ detail,
317
+ });
318
+ }
319
+ }
309
320
  export class HelixFilterEvent extends CustomEvent {
310
321
  static { this.eventName = 'helix-filter'; }
311
322
  constructor(detail) {
@@ -339,6 +350,28 @@ export class HelixSelectEvent extends CustomEvent {
339
350
  });
340
351
  }
341
352
  }
353
+ export class HelixReorderEvent extends CustomEvent {
354
+ static { this.eventName = 'helix-reorder'; }
355
+ constructor(detail) {
356
+ super(HelixReorderEvent.eventName, {
357
+ bubbles: true,
358
+ cancelable: true,
359
+ composed: true,
360
+ detail,
361
+ });
362
+ }
363
+ }
364
+ export class HelixHistoryEvent extends CustomEvent {
365
+ static { this.eventName = 'helix-history'; }
366
+ constructor() {
367
+ super(HelixHistoryEvent.eventName, {
368
+ bubbles: true,
369
+ cancelable: false,
370
+ composed: true,
371
+ detail: {},
372
+ });
373
+ }
374
+ }
342
375
  const registry = {
343
376
  HelixActivateEvent,
344
377
  HelixBeforeActivateEvent,
@@ -358,11 +391,14 @@ const registry = {
358
391
  HelixCopyEvent,
359
392
  HelixCreateEvent,
360
393
  HelixDismissEvent,
394
+ HelixFacetEvent,
361
395
  HelixFilterEvent,
396
+ HelixHistoryEvent,
362
397
  HelixNavigateEvent,
363
398
  HelixNextEvent,
364
399
  HelixPreviousEvent,
365
400
  HelixReadEvent,
401
+ HelixReorderEvent,
366
402
  HelixResizeEvent,
367
403
  HelixSampleEndEvent,
368
404
  HelixSampleStartEvent,
@@ -119,6 +119,72 @@ export declare class HelixElement extends LitElement {
119
119
  /** Resolves `whenSettled`, once, from the frame that records the state. */
120
120
  private resolveSettled;
121
121
  constructor();
122
+ /** Whether the shadow root was a server's, parsed from declarative shadow DOM. */
123
+ private fromServer;
124
+ protected createRenderRoot(): HTMLElement | DocumentFragment;
125
+ /**
126
+ * Whether this update is hydrating a server's markup, and so has to render
127
+ * exactly what the server rendered.
128
+ *
129
+ * **Lit hydrates by assuming the markup already shows the first render.** A
130
+ * value that differs is recorded and never written, so the page keeps the
131
+ * server's, and a template that differs throws. The server has no children,
132
+ * so anything a component reads from its children waits for the update after
133
+ * hydration, which `finishHydration` asks for. Without a server's markup the
134
+ * first render reads them and there is one render.
135
+ */
136
+ protected get hydrating(): boolean;
137
+ /**
138
+ * Whether this element hydrated a server's markup rather than rendering its own.
139
+ *
140
+ * For what happened before hydration and cannot be heard after it: an image
141
+ * the parser fetched fires `load` or `error` before any listener exists, so a
142
+ * component asks the image instead, once, when this is true.
143
+ */
144
+ protected get serverRendered(): boolean;
145
+ /**
146
+ * Asks for the update a hydration put off, so the reads it skipped happen.
147
+ *
148
+ * Called from `firstUpdated`, the end of the hydrating update. The render it
149
+ * schedules can only follow that one, which is the exception Lit's
150
+ * change-in-update warning names, and it happens only on a page a server
151
+ * rendered.
152
+ */
153
+ protected finishHydration(): void;
154
+ /**
155
+ * Whether this render can know the children.
156
+ *
157
+ * A server cannot: its element shim carries attributes and no tree, so
158
+ * `children` is undefined there. A render hydrating what a server sent must
159
+ * not, because it has to be the server's render. Anywhere else it can. A
160
+ * component whose render depends on its children reads them through
161
+ * `knownChildren`, and treats "not known" as its own answer rather than as
162
+ * "none": a list that renders its empty state because nobody has looked yet is
163
+ * the one thing an empty state must never do.
164
+ */
165
+ protected get childrenKnown(): boolean;
166
+ /** The children a render may read: all of them where they are known, and none otherwise. */
167
+ protected get knownChildren(): Element[];
168
+ /**
169
+ * Whether this element's slots route by name although it asked to assign them
170
+ * by hand.
171
+ *
172
+ * **A declarative shadow root is always the by-name kind.** HTML has no way to
173
+ * ask for manual assignment, so a component that assigns by hand and hydrates
174
+ * a server's root gets one where `slot.assign()` does nothing, and its
175
+ * children land wherever their `slot` attribute sends them. The way through is
176
+ * to write that attribute, which is what `route` does. Only there: on a root
177
+ * this element made, assignment stays manual and the consumer's markup is
178
+ * never touched, which is what a React consumer's hydration requires.
179
+ */
180
+ protected get assignsByName(): boolean;
181
+ /**
182
+ * Sends a child to a slot by name, on a root that routes by name.
183
+ *
184
+ * `undefined` is the default slot. Written only when it differs, so routing
185
+ * the same child again on every update writes nothing.
186
+ */
187
+ protected route(child: Element, name: string | undefined): void;
122
188
  /**
123
189
  * Announces an event, having first bound whatever React is holding for it.
124
190
  *
@@ -191,3 +257,15 @@ export declare class HelixElement extends LitElement {
191
257
  */
192
258
  protected firstUpdated(changed: PropertyValues): void;
193
259
  }
260
+ /**
261
+ * Writes to a child element once it has hydrated, or now where it is not
262
+ * hydrating.
263
+ *
264
+ * **For a parent that sets state on the elements it holds.** On a page a server
265
+ * rendered, the parent's `updated` can run before a child's own first update,
266
+ * and a property written then is in the child's hydrating render, which has to
267
+ * be the server's: a mark the markup never showed, and Lit throws. Waiting for
268
+ * that render lets it match and the write land in the one after. Anywhere else
269
+ * the write is immediate, so a client's first render already has it.
270
+ */
271
+ export declare const whenHydrated: (element: Element, write: () => void) => void;
@@ -130,6 +130,7 @@ export class HelixElement extends LitElement {
130
130
  constructor() {
131
131
  super();
132
132
  this.resolveSettled = () => { };
133
+ this.fromServer = false;
133
134
  this.stopInner = (event) => {
134
135
  if (event.target !== this) {
135
136
  event.stopPropagation();
@@ -140,6 +141,42 @@ export class HelixElement extends LitElement {
140
141
  this.resolveSettled = resolve;
141
142
  });
142
143
  }
144
+ createRenderRoot() {
145
+ this.fromServer = this.shadowRoot !== null;
146
+ return super.createRenderRoot();
147
+ }
148
+ get hydrating() {
149
+ return this.fromServer && !this.hasUpdated;
150
+ }
151
+ get serverRendered() {
152
+ return this.fromServer;
153
+ }
154
+ finishHydration() {
155
+ if (this.fromServer) {
156
+ this.requestUpdate();
157
+ }
158
+ }
159
+ get childrenKnown() {
160
+ return this.children !== undefined && !this.hydrating;
161
+ }
162
+ get knownChildren() {
163
+ return this.childrenKnown ? [...this.children] : [];
164
+ }
165
+ get assignsByName() {
166
+ const asked = this.constructor.shadowRootOptions.slotAssignment;
167
+ return (asked === 'manual' &&
168
+ typeof ShadowRoot !== 'undefined' &&
169
+ this.renderRoot instanceof ShadowRoot &&
170
+ this.renderRoot.slotAssignment !== 'manual');
171
+ }
172
+ route(child, name) {
173
+ if (name === undefined) {
174
+ child.removeAttribute('slot');
175
+ }
176
+ else if (child.getAttribute('slot') !== name) {
177
+ child.setAttribute('slot', name);
178
+ }
179
+ }
143
180
  dispatchEvent(event) {
144
181
  bindReactHandler(this, event);
145
182
  return super.dispatchEvent(event);
@@ -171,3 +208,12 @@ export class HelixElement extends LitElement {
171
208
  });
172
209
  }
173
210
  }
211
+ export const whenHydrated = (element, write) => {
212
+ const child = element;
213
+ if (child.hydrating === true && child.updateComplete) {
214
+ void child.updateComplete.then(write);
215
+ }
216
+ else {
217
+ write();
218
+ }
219
+ };
package/dist/index.d.ts CHANGED
@@ -14,8 +14,8 @@ export { SourceController, type SourceHost, } from './controllers/source-control
14
14
  export { type TokenColor, TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
15
15
  export { type Rendered, VirtualizeController, type VirtualizeOptions, type Window as VirtualizeWindow, } from './controllers/virtualize-controller/virtualize-controller.js';
16
16
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
17
- export { type CaretDetail, type ChangeDetail, type CompleteDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FilterDetail, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCaretEvent, HelixCompleteEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFilterEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, type NavigateDetail, type OpenDetail, type ReadDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, } from './events/events.js';
18
- export { HelixElement } from './helix-element/helix-element.js';
17
+ export { type CaretDetail, type ChangeDetail, type CompleteDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCaretEvent, HelixCompleteEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixHistoryEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, type NavigateDetail, type OpenDetail, type ReadDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, } from './events/events.js';
18
+ export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
19
19
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
20
20
  export { MixinChartSource, type MixinChartSourceInterface, PALETTE, seriesIndex, } from './mixins/mixin-chart-source/mixin-chart-source.js';
21
21
  export { type CollectionElement, MixinCollection, } from './mixins/mixin-collection/mixin-collection.js';
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ export { SourceController, } from './controllers/source-controller/source-contro
14
14
  export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
15
15
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
16
16
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
17
- export { HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCaretEvent, HelixCompleteEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFilterEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, } from './events/events.js';
18
- export { HelixElement } from './helix-element/helix-element.js';
17
+ export { HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCaretEvent, HelixCompleteEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixHistoryEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, } from './events/events.js';
18
+ export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
19
19
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
20
20
  export { MixinChartSource, PALETTE, seriesIndex, } from './mixins/mixin-chart-source/mixin-chart-source.js';
21
21
  export { MixinCollection, } from './mixins/mixin-collection/mixin-collection.js';
@@ -1,4 +1,5 @@
1
- import { type LitElement, nothing, type TemplateResult } from 'lit';
1
+ import { nothing, type TemplateResult } from 'lit';
2
+ import type { HelixElement } from '../../helix-element/helix-element.js';
2
3
  type Constructor<T> = new (...args: any[]) => T;
3
4
  /**
4
5
  * The API a collection has for the two states that are not its content.
@@ -18,6 +19,8 @@ export declare class CollectionElement {
18
19
  protected renderStatus(hasContent: boolean): TemplateResult | typeof nothing;
19
20
  /** Binds to a rows slot's `slotchange`, and answers `hasRows` from it. */
20
21
  protected countRows(event: Event): void;
22
+ /** What the rows slot is given, read from the host so a first render has it. */
23
+ protected get slotted(): Element[];
21
24
  /**
22
25
  * Whether there is anything to show, as far as anything can tell.
23
26
  *
@@ -48,5 +51,5 @@ export declare class CollectionElement {
48
51
  * apply this, rather than here.** See `MixinField` for why a class-level tag on
49
52
  * a mixin reaches no manifest.
50
53
  */
51
- export declare const MixinCollection: <T extends Constructor<LitElement>>(Base: T) => Constructor<CollectionElement> & T;
54
+ export declare const MixinCollection: <T extends Constructor<HelixElement>>(Base: T) => Constructor<CollectionElement> & T;
52
55
  export {};
@@ -23,18 +23,24 @@ export const MixinCollection = (Base) => {
23
23
  get hasRows() {
24
24
  return this.slotCounted ? this.slotRows > 0 : true;
25
25
  }
26
- updated(changed) {
27
- super.updated?.(changed);
28
- const slot = this.renderRoot?.querySelector?.('slot:not([name])');
29
- if (!slot) {
26
+ get slotted() {
27
+ return [...(this.children ?? [])].filter((child) => child.slot === '');
28
+ }
29
+ willUpdate(changed) {
30
+ super.willUpdate(changed);
31
+ if (this.children === undefined || this.hydrating) {
30
32
  return;
31
33
  }
32
- const rows = slot.assignedElements().length;
34
+ const rows = this.slotted.length;
33
35
  this.slotCounted = true;
34
36
  if (rows !== this.slotRows) {
35
37
  this.slotRows = rows;
36
38
  }
37
39
  }
40
+ firstUpdated(changed) {
41
+ super.firstUpdated(changed);
42
+ this.finishHydration();
43
+ }
38
44
  renderStatus(hasContent) {
39
45
  if (this.loading) {
40
46
  return html `<p part="loading" role="status">${this.loadingText}</p>`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-core",
3
3
  "description": "Helix element primitives: base classes, mixins, decorators, utilities.",
4
- "version": "0.23.0",
4
+ "version": "0.24.1",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -34,12 +34,12 @@
34
34
  "bugs": "https://github.com/project-fusion/fusion/issues",
35
35
  "dependencies": {
36
36
  "@floating-ui/dom": "^1.8.0",
37
- "@fusion.dev/helix-icons": "0.23.0"
37
+ "@fusion.dev/helix-icons": "0.24.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@custom-elements-manifest/analyzer": "^0.11.0",
41
- "@fusion.dev/helix-cem": "0.23.0",
42
- "@fusion.dev/helix-testing": "0.23.0",
41
+ "@fusion.dev/helix-cem": "0.24.1",
42
+ "@fusion.dev/helix-testing": "0.24.1",
43
43
  "lit": "^3.2.1"
44
44
  },
45
45
  "homepage": "https://fusion.dev",