@fusion.dev/helix-core 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +389 -1
- package/dist/controllers/virtualize-controller/heights.d.ts +9 -0
- package/dist/controllers/virtualize-controller/heights.js +13 -0
- package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +15 -0
- package/dist/controllers/virtualize-controller/virtualize-controller.js +23 -0
- package/dist/events/events.d.ts +89 -0
- package/dist/events/events.js +36 -0
- package/dist/helix-element/helix-element.d.ts +58 -0
- package/dist/helix-element/helix-element.js +34 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mixins/mixin-collection/mixin-collection.d.ts +5 -2
- package/dist/mixins/mixin-collection/mixin-collection.js +11 -5
- package/package.json +4 -4
package/custom-elements.json
CHANGED
|
@@ -1810,6 +1810,24 @@
|
|
|
1810
1810
|
],
|
|
1811
1811
|
"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
1812
|
},
|
|
1813
|
+
{
|
|
1814
|
+
"kind": "method",
|
|
1815
|
+
"name": "shift",
|
|
1816
|
+
"return": {
|
|
1817
|
+
"type": {
|
|
1818
|
+
"text": "void"
|
|
1819
|
+
}
|
|
1820
|
+
},
|
|
1821
|
+
"parameters": [
|
|
1822
|
+
{
|
|
1823
|
+
"name": "by",
|
|
1824
|
+
"type": {
|
|
1825
|
+
"text": "number"
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
],
|
|
1829
|
+
"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."
|
|
1830
|
+
},
|
|
1813
1831
|
{
|
|
1814
1832
|
"kind": "method",
|
|
1815
1833
|
"name": "forget",
|
|
@@ -1949,6 +1967,16 @@
|
|
|
1949
1967
|
"description": "Where each item starts, once any of them has been seen.",
|
|
1950
1968
|
"default": "new Heights(() => this.options.estimate())"
|
|
1951
1969
|
},
|
|
1970
|
+
{
|
|
1971
|
+
"kind": "field",
|
|
1972
|
+
"name": "owed",
|
|
1973
|
+
"type": {
|
|
1974
|
+
"text": "number"
|
|
1975
|
+
},
|
|
1976
|
+
"privacy": "private",
|
|
1977
|
+
"default": "0",
|
|
1978
|
+
"description": "Room `shift` added above the window, owed to the scroll offset once drawn."
|
|
1979
|
+
},
|
|
1952
1980
|
{
|
|
1953
1981
|
"kind": "method",
|
|
1954
1982
|
"name": "hostConnected",
|
|
@@ -2083,6 +2111,24 @@
|
|
|
2083
2111
|
},
|
|
2084
2112
|
"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
2113
|
},
|
|
2114
|
+
{
|
|
2115
|
+
"kind": "method",
|
|
2116
|
+
"name": "shift",
|
|
2117
|
+
"return": {
|
|
2118
|
+
"type": {
|
|
2119
|
+
"text": "void"
|
|
2120
|
+
}
|
|
2121
|
+
},
|
|
2122
|
+
"parameters": [
|
|
2123
|
+
{
|
|
2124
|
+
"name": "by",
|
|
2125
|
+
"type": {
|
|
2126
|
+
"text": "number"
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
],
|
|
2130
|
+
"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."
|
|
2131
|
+
},
|
|
2086
2132
|
{
|
|
2087
2133
|
"kind": "method",
|
|
2088
2134
|
"name": "forget",
|
|
@@ -2821,6 +2867,28 @@
|
|
|
2821
2867
|
},
|
|
2822
2868
|
"helix": {}
|
|
2823
2869
|
},
|
|
2870
|
+
{
|
|
2871
|
+
"kind": "class",
|
|
2872
|
+
"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.",
|
|
2873
|
+
"name": "HelixFacetEvent",
|
|
2874
|
+
"members": [
|
|
2875
|
+
{
|
|
2876
|
+
"kind": "field",
|
|
2877
|
+
"name": "eventName",
|
|
2878
|
+
"type": {
|
|
2879
|
+
"text": "string"
|
|
2880
|
+
},
|
|
2881
|
+
"static": true,
|
|
2882
|
+
"readonly": true,
|
|
2883
|
+
"default": "'helix-facet'"
|
|
2884
|
+
}
|
|
2885
|
+
],
|
|
2886
|
+
"superclass": {
|
|
2887
|
+
"name": "CustomEvent",
|
|
2888
|
+
"module": "src/events/events.ts"
|
|
2889
|
+
},
|
|
2890
|
+
"helix": {}
|
|
2891
|
+
},
|
|
2824
2892
|
{
|
|
2825
2893
|
"kind": "class",
|
|
2826
2894
|
"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 +2955,50 @@
|
|
|
2887
2955
|
},
|
|
2888
2956
|
"helix": {}
|
|
2889
2957
|
},
|
|
2958
|
+
{
|
|
2959
|
+
"kind": "class",
|
|
2960
|
+
"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.",
|
|
2961
|
+
"name": "HelixReorderEvent",
|
|
2962
|
+
"members": [
|
|
2963
|
+
{
|
|
2964
|
+
"kind": "field",
|
|
2965
|
+
"name": "eventName",
|
|
2966
|
+
"type": {
|
|
2967
|
+
"text": "string"
|
|
2968
|
+
},
|
|
2969
|
+
"static": true,
|
|
2970
|
+
"readonly": true,
|
|
2971
|
+
"default": "'helix-reorder'"
|
|
2972
|
+
}
|
|
2973
|
+
],
|
|
2974
|
+
"superclass": {
|
|
2975
|
+
"name": "CustomEvent",
|
|
2976
|
+
"module": "src/events/events.ts"
|
|
2977
|
+
},
|
|
2978
|
+
"helix": {}
|
|
2979
|
+
},
|
|
2980
|
+
{
|
|
2981
|
+
"kind": "class",
|
|
2982
|
+
"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.",
|
|
2983
|
+
"name": "HelixHistoryEvent",
|
|
2984
|
+
"members": [
|
|
2985
|
+
{
|
|
2986
|
+
"kind": "field",
|
|
2987
|
+
"name": "eventName",
|
|
2988
|
+
"type": {
|
|
2989
|
+
"text": "string"
|
|
2990
|
+
},
|
|
2991
|
+
"static": true,
|
|
2992
|
+
"readonly": true,
|
|
2993
|
+
"default": "'helix-history'"
|
|
2994
|
+
}
|
|
2995
|
+
],
|
|
2996
|
+
"superclass": {
|
|
2997
|
+
"name": "CustomEvent",
|
|
2998
|
+
"module": "src/events/events.ts"
|
|
2999
|
+
},
|
|
3000
|
+
"helix": {}
|
|
3001
|
+
},
|
|
2890
3002
|
{
|
|
2891
3003
|
"kind": "variable",
|
|
2892
3004
|
"name": "helixEventNames",
|
|
@@ -3130,6 +3242,14 @@
|
|
|
3130
3242
|
"module": "src/events/events.ts"
|
|
3131
3243
|
}
|
|
3132
3244
|
},
|
|
3245
|
+
{
|
|
3246
|
+
"kind": "js",
|
|
3247
|
+
"name": "HelixFacetEvent",
|
|
3248
|
+
"declaration": {
|
|
3249
|
+
"name": "HelixFacetEvent",
|
|
3250
|
+
"module": "src/events/events.ts"
|
|
3251
|
+
}
|
|
3252
|
+
},
|
|
3133
3253
|
{
|
|
3134
3254
|
"kind": "js",
|
|
3135
3255
|
"name": "HelixFilterEvent",
|
|
@@ -3154,6 +3274,22 @@
|
|
|
3154
3274
|
"module": "src/events/events.ts"
|
|
3155
3275
|
}
|
|
3156
3276
|
},
|
|
3277
|
+
{
|
|
3278
|
+
"kind": "js",
|
|
3279
|
+
"name": "HelixReorderEvent",
|
|
3280
|
+
"declaration": {
|
|
3281
|
+
"name": "HelixReorderEvent",
|
|
3282
|
+
"module": "src/events/events.ts"
|
|
3283
|
+
}
|
|
3284
|
+
},
|
|
3285
|
+
{
|
|
3286
|
+
"kind": "js",
|
|
3287
|
+
"name": "HelixHistoryEvent",
|
|
3288
|
+
"declaration": {
|
|
3289
|
+
"name": "HelixHistoryEvent",
|
|
3290
|
+
"module": "src/events/events.ts"
|
|
3291
|
+
}
|
|
3292
|
+
},
|
|
3157
3293
|
{
|
|
3158
3294
|
"kind": "js",
|
|
3159
3295
|
"name": "helixEventNames",
|
|
@@ -3256,6 +3392,92 @@
|
|
|
3256
3392
|
"privacy": "private",
|
|
3257
3393
|
"description": "Resolves `whenSettled`, once, from the frame that records the state."
|
|
3258
3394
|
},
|
|
3395
|
+
{
|
|
3396
|
+
"kind": "field",
|
|
3397
|
+
"name": "fromServer",
|
|
3398
|
+
"type": {
|
|
3399
|
+
"text": "boolean"
|
|
3400
|
+
},
|
|
3401
|
+
"privacy": "private",
|
|
3402
|
+
"default": "false",
|
|
3403
|
+
"description": "Whether the shadow root was a server's, parsed from declarative shadow DOM."
|
|
3404
|
+
},
|
|
3405
|
+
{
|
|
3406
|
+
"kind": "field",
|
|
3407
|
+
"name": "hydrating",
|
|
3408
|
+
"type": {
|
|
3409
|
+
"text": "boolean"
|
|
3410
|
+
},
|
|
3411
|
+
"privacy": "protected",
|
|
3412
|
+
"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.",
|
|
3413
|
+
"readonly": true
|
|
3414
|
+
},
|
|
3415
|
+
{
|
|
3416
|
+
"kind": "method",
|
|
3417
|
+
"name": "finishHydration",
|
|
3418
|
+
"privacy": "protected",
|
|
3419
|
+
"return": {
|
|
3420
|
+
"type": {
|
|
3421
|
+
"text": "void"
|
|
3422
|
+
}
|
|
3423
|
+
},
|
|
3424
|
+
"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."
|
|
3425
|
+
},
|
|
3426
|
+
{
|
|
3427
|
+
"kind": "field",
|
|
3428
|
+
"name": "childrenKnown",
|
|
3429
|
+
"type": {
|
|
3430
|
+
"text": "boolean"
|
|
3431
|
+
},
|
|
3432
|
+
"privacy": "protected",
|
|
3433
|
+
"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.",
|
|
3434
|
+
"readonly": true
|
|
3435
|
+
},
|
|
3436
|
+
{
|
|
3437
|
+
"kind": "field",
|
|
3438
|
+
"name": "knownChildren",
|
|
3439
|
+
"type": {
|
|
3440
|
+
"text": "Element[]"
|
|
3441
|
+
},
|
|
3442
|
+
"privacy": "protected",
|
|
3443
|
+
"description": "The children a render may read: all of them where they are known, and none otherwise.",
|
|
3444
|
+
"readonly": true
|
|
3445
|
+
},
|
|
3446
|
+
{
|
|
3447
|
+
"kind": "field",
|
|
3448
|
+
"name": "assignsByName",
|
|
3449
|
+
"type": {
|
|
3450
|
+
"text": "boolean"
|
|
3451
|
+
},
|
|
3452
|
+
"privacy": "protected",
|
|
3453
|
+
"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.",
|
|
3454
|
+
"readonly": true
|
|
3455
|
+
},
|
|
3456
|
+
{
|
|
3457
|
+
"kind": "method",
|
|
3458
|
+
"name": "route",
|
|
3459
|
+
"privacy": "protected",
|
|
3460
|
+
"return": {
|
|
3461
|
+
"type": {
|
|
3462
|
+
"text": "void"
|
|
3463
|
+
}
|
|
3464
|
+
},
|
|
3465
|
+
"parameters": [
|
|
3466
|
+
{
|
|
3467
|
+
"name": "child",
|
|
3468
|
+
"type": {
|
|
3469
|
+
"text": "Element"
|
|
3470
|
+
}
|
|
3471
|
+
},
|
|
3472
|
+
{
|
|
3473
|
+
"name": "name",
|
|
3474
|
+
"type": {
|
|
3475
|
+
"text": "string | undefined"
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
],
|
|
3479
|
+
"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."
|
|
3480
|
+
},
|
|
3259
3481
|
{
|
|
3260
3482
|
"kind": "field",
|
|
3261
3483
|
"name": "stopInner",
|
|
@@ -3548,6 +3770,120 @@
|
|
|
3548
3770
|
"module": "src/helix-element/helix-element.ts"
|
|
3549
3771
|
}
|
|
3550
3772
|
},
|
|
3773
|
+
{
|
|
3774
|
+
"kind": "field",
|
|
3775
|
+
"name": "fromServer",
|
|
3776
|
+
"type": {
|
|
3777
|
+
"text": "boolean"
|
|
3778
|
+
},
|
|
3779
|
+
"privacy": "private",
|
|
3780
|
+
"default": "false",
|
|
3781
|
+
"description": "Whether the shadow root was a server's, parsed from declarative shadow DOM.",
|
|
3782
|
+
"inheritedFrom": {
|
|
3783
|
+
"name": "HelixElement",
|
|
3784
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3785
|
+
}
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
"kind": "field",
|
|
3789
|
+
"name": "hydrating",
|
|
3790
|
+
"type": {
|
|
3791
|
+
"text": "boolean"
|
|
3792
|
+
},
|
|
3793
|
+
"privacy": "protected",
|
|
3794
|
+
"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.",
|
|
3795
|
+
"readonly": true,
|
|
3796
|
+
"inheritedFrom": {
|
|
3797
|
+
"name": "HelixElement",
|
|
3798
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3799
|
+
}
|
|
3800
|
+
},
|
|
3801
|
+
{
|
|
3802
|
+
"kind": "method",
|
|
3803
|
+
"name": "finishHydration",
|
|
3804
|
+
"privacy": "protected",
|
|
3805
|
+
"return": {
|
|
3806
|
+
"type": {
|
|
3807
|
+
"text": "void"
|
|
3808
|
+
}
|
|
3809
|
+
},
|
|
3810
|
+
"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.",
|
|
3811
|
+
"inheritedFrom": {
|
|
3812
|
+
"name": "HelixElement",
|
|
3813
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3814
|
+
}
|
|
3815
|
+
},
|
|
3816
|
+
{
|
|
3817
|
+
"kind": "field",
|
|
3818
|
+
"name": "childrenKnown",
|
|
3819
|
+
"type": {
|
|
3820
|
+
"text": "boolean"
|
|
3821
|
+
},
|
|
3822
|
+
"privacy": "protected",
|
|
3823
|
+
"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.",
|
|
3824
|
+
"readonly": true,
|
|
3825
|
+
"inheritedFrom": {
|
|
3826
|
+
"name": "HelixElement",
|
|
3827
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3828
|
+
}
|
|
3829
|
+
},
|
|
3830
|
+
{
|
|
3831
|
+
"kind": "field",
|
|
3832
|
+
"name": "knownChildren",
|
|
3833
|
+
"type": {
|
|
3834
|
+
"text": "Element[]"
|
|
3835
|
+
},
|
|
3836
|
+
"privacy": "protected",
|
|
3837
|
+
"description": "The children a render may read: all of them where they are known, and none otherwise.",
|
|
3838
|
+
"readonly": true,
|
|
3839
|
+
"inheritedFrom": {
|
|
3840
|
+
"name": "HelixElement",
|
|
3841
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3842
|
+
}
|
|
3843
|
+
},
|
|
3844
|
+
{
|
|
3845
|
+
"kind": "field",
|
|
3846
|
+
"name": "assignsByName",
|
|
3847
|
+
"type": {
|
|
3848
|
+
"text": "boolean"
|
|
3849
|
+
},
|
|
3850
|
+
"privacy": "protected",
|
|
3851
|
+
"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.",
|
|
3852
|
+
"readonly": true,
|
|
3853
|
+
"inheritedFrom": {
|
|
3854
|
+
"name": "HelixElement",
|
|
3855
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3856
|
+
}
|
|
3857
|
+
},
|
|
3858
|
+
{
|
|
3859
|
+
"kind": "method",
|
|
3860
|
+
"name": "route",
|
|
3861
|
+
"privacy": "protected",
|
|
3862
|
+
"return": {
|
|
3863
|
+
"type": {
|
|
3864
|
+
"text": "void"
|
|
3865
|
+
}
|
|
3866
|
+
},
|
|
3867
|
+
"parameters": [
|
|
3868
|
+
{
|
|
3869
|
+
"name": "child",
|
|
3870
|
+
"type": {
|
|
3871
|
+
"text": "Element"
|
|
3872
|
+
}
|
|
3873
|
+
},
|
|
3874
|
+
{
|
|
3875
|
+
"name": "name",
|
|
3876
|
+
"type": {
|
|
3877
|
+
"text": "string | undefined"
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3880
|
+
],
|
|
3881
|
+
"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.",
|
|
3882
|
+
"inheritedFrom": {
|
|
3883
|
+
"name": "HelixElement",
|
|
3884
|
+
"module": "src/helix-element/helix-element.ts"
|
|
3885
|
+
}
|
|
3886
|
+
},
|
|
3551
3887
|
{
|
|
3552
3888
|
"kind": "field",
|
|
3553
3889
|
"name": "stopInner",
|
|
@@ -4017,6 +4353,14 @@
|
|
|
4017
4353
|
"module": "./events/events.js"
|
|
4018
4354
|
}
|
|
4019
4355
|
},
|
|
4356
|
+
{
|
|
4357
|
+
"kind": "js",
|
|
4358
|
+
"name": "FacetDetail",
|
|
4359
|
+
"declaration": {
|
|
4360
|
+
"name": "FacetDetail",
|
|
4361
|
+
"module": "./events/events.js"
|
|
4362
|
+
}
|
|
4363
|
+
},
|
|
4020
4364
|
{
|
|
4021
4365
|
"kind": "js",
|
|
4022
4366
|
"name": "FilterDetail",
|
|
@@ -4169,6 +4513,14 @@
|
|
|
4169
4513
|
"module": "./events/events.js"
|
|
4170
4514
|
}
|
|
4171
4515
|
},
|
|
4516
|
+
{
|
|
4517
|
+
"kind": "js",
|
|
4518
|
+
"name": "HelixFacetEvent",
|
|
4519
|
+
"declaration": {
|
|
4520
|
+
"name": "HelixFacetEvent",
|
|
4521
|
+
"module": "./events/events.js"
|
|
4522
|
+
}
|
|
4523
|
+
},
|
|
4172
4524
|
{
|
|
4173
4525
|
"kind": "js",
|
|
4174
4526
|
"name": "HelixFilterEvent",
|
|
@@ -4177,6 +4529,14 @@
|
|
|
4177
4529
|
"module": "./events/events.js"
|
|
4178
4530
|
}
|
|
4179
4531
|
},
|
|
4532
|
+
{
|
|
4533
|
+
"kind": "js",
|
|
4534
|
+
"name": "HelixHistoryEvent",
|
|
4535
|
+
"declaration": {
|
|
4536
|
+
"name": "HelixHistoryEvent",
|
|
4537
|
+
"module": "./events/events.js"
|
|
4538
|
+
}
|
|
4539
|
+
},
|
|
4180
4540
|
{
|
|
4181
4541
|
"kind": "js",
|
|
4182
4542
|
"name": "HelixNavigateEvent",
|
|
@@ -4209,6 +4569,14 @@
|
|
|
4209
4569
|
"module": "./events/events.js"
|
|
4210
4570
|
}
|
|
4211
4571
|
},
|
|
4572
|
+
{
|
|
4573
|
+
"kind": "js",
|
|
4574
|
+
"name": "HelixReorderEvent",
|
|
4575
|
+
"declaration": {
|
|
4576
|
+
"name": "HelixReorderEvent",
|
|
4577
|
+
"module": "./events/events.js"
|
|
4578
|
+
}
|
|
4579
|
+
},
|
|
4212
4580
|
{
|
|
4213
4581
|
"kind": "js",
|
|
4214
4582
|
"name": "HelixResizeEvent",
|
|
@@ -5448,6 +5816,16 @@
|
|
|
5448
5816
|
],
|
|
5449
5817
|
"description": "Binds to a rows slot's `slotchange`, and answers `hasRows` from it."
|
|
5450
5818
|
},
|
|
5819
|
+
{
|
|
5820
|
+
"kind": "field",
|
|
5821
|
+
"name": "slotted",
|
|
5822
|
+
"type": {
|
|
5823
|
+
"text": "Element[]"
|
|
5824
|
+
},
|
|
5825
|
+
"privacy": "protected",
|
|
5826
|
+
"description": "What the rows slot is given, read from the host so a first render has it.",
|
|
5827
|
+
"readonly": true
|
|
5828
|
+
},
|
|
5451
5829
|
{
|
|
5452
5830
|
"kind": "field",
|
|
5453
5831
|
"name": "hasRows",
|
|
@@ -5515,7 +5893,7 @@
|
|
|
5515
5893
|
},
|
|
5516
5894
|
"privacy": "private",
|
|
5517
5895
|
"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
|
|
5896
|
+
"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
5897
|
},
|
|
5520
5898
|
{
|
|
5521
5899
|
"kind": "method",
|
|
@@ -5545,6 +5923,16 @@
|
|
|
5545
5923
|
"privacy": "protected",
|
|
5546
5924
|
"readonly": true
|
|
5547
5925
|
},
|
|
5926
|
+
{
|
|
5927
|
+
"kind": "field",
|
|
5928
|
+
"name": "slotted",
|
|
5929
|
+
"type": {
|
|
5930
|
+
"text": "Element[]"
|
|
5931
|
+
},
|
|
5932
|
+
"privacy": "protected",
|
|
5933
|
+
"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.",
|
|
5934
|
+
"readonly": true
|
|
5935
|
+
},
|
|
5548
5936
|
{
|
|
5549
5937
|
"kind": "method",
|
|
5550
5938
|
"name": "renderStatus",
|
|
@@ -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
|
}
|
package/dist/events/events.d.ts
CHANGED
|
@@ -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;
|
package/dist/events/events.js
CHANGED
|
@@ -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,64 @@ 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
|
+
* Asks for the update a hydration put off, so the reads it skipped happen.
|
|
139
|
+
*
|
|
140
|
+
* Called from `firstUpdated`, the end of the hydrating update. The render it
|
|
141
|
+
* schedules can only follow that one, which is the exception Lit's
|
|
142
|
+
* change-in-update warning names, and it happens only on a page a server
|
|
143
|
+
* rendered.
|
|
144
|
+
*/
|
|
145
|
+
protected finishHydration(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Whether this render can know the children.
|
|
148
|
+
*
|
|
149
|
+
* A server cannot: its element shim carries attributes and no tree, so
|
|
150
|
+
* `children` is undefined there. A render hydrating what a server sent must
|
|
151
|
+
* not, because it has to be the server's render. Anywhere else it can. A
|
|
152
|
+
* component whose render depends on its children reads them through
|
|
153
|
+
* `knownChildren`, and treats "not known" as its own answer rather than as
|
|
154
|
+
* "none": a list that renders its empty state because nobody has looked yet is
|
|
155
|
+
* the one thing an empty state must never do.
|
|
156
|
+
*/
|
|
157
|
+
protected get childrenKnown(): boolean;
|
|
158
|
+
/** The children a render may read: all of them where they are known, and none otherwise. */
|
|
159
|
+
protected get knownChildren(): Element[];
|
|
160
|
+
/**
|
|
161
|
+
* Whether this element's slots route by name although it asked to assign them
|
|
162
|
+
* by hand.
|
|
163
|
+
*
|
|
164
|
+
* **A declarative shadow root is always the by-name kind.** HTML has no way to
|
|
165
|
+
* ask for manual assignment, so a component that assigns by hand and hydrates
|
|
166
|
+
* a server's root gets one where `slot.assign()` does nothing, and its
|
|
167
|
+
* children land wherever their `slot` attribute sends them. The way through is
|
|
168
|
+
* to write that attribute, which is what `route` does. Only there: on a root
|
|
169
|
+
* this element made, assignment stays manual and the consumer's markup is
|
|
170
|
+
* never touched, which is what a React consumer's hydration requires.
|
|
171
|
+
*/
|
|
172
|
+
protected get assignsByName(): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Sends a child to a slot by name, on a root that routes by name.
|
|
175
|
+
*
|
|
176
|
+
* `undefined` is the default slot. Written only when it differs, so routing
|
|
177
|
+
* the same child again on every update writes nothing.
|
|
178
|
+
*/
|
|
179
|
+
protected route(child: Element, name: string | undefined): void;
|
|
122
180
|
/**
|
|
123
181
|
* Announces an event, having first bound whatever React is holding for it.
|
|
124
182
|
*
|
|
@@ -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,39 @@ 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
|
+
finishHydration() {
|
|
152
|
+
if (this.fromServer) {
|
|
153
|
+
this.requestUpdate();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
get childrenKnown() {
|
|
157
|
+
return this.children !== undefined && !this.hydrating;
|
|
158
|
+
}
|
|
159
|
+
get knownChildren() {
|
|
160
|
+
return this.childrenKnown ? [...this.children] : [];
|
|
161
|
+
}
|
|
162
|
+
get assignsByName() {
|
|
163
|
+
const asked = this.constructor.shadowRootOptions.slotAssignment;
|
|
164
|
+
return (asked === 'manual' &&
|
|
165
|
+
typeof ShadowRoot !== 'undefined' &&
|
|
166
|
+
this.renderRoot instanceof ShadowRoot &&
|
|
167
|
+
this.renderRoot.slotAssignment !== 'manual');
|
|
168
|
+
}
|
|
169
|
+
route(child, name) {
|
|
170
|
+
if (name === undefined) {
|
|
171
|
+
child.removeAttribute('slot');
|
|
172
|
+
}
|
|
173
|
+
else if (child.getAttribute('slot') !== name) {
|
|
174
|
+
child.setAttribute('slot', name);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
143
177
|
dispatchEvent(event) {
|
|
144
178
|
bindReactHandler(this, event);
|
|
145
179
|
return super.dispatchEvent(event);
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ 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';
|
|
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
18
|
export { HelixElement } 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';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ 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';
|
|
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
18
|
export { HelixElement } 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';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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<
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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 =
|
|
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.
|
|
4
|
+
"version": "0.24.0",
|
|
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.
|
|
37
|
+
"@fusion.dev/helix-icons": "0.24.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
41
|
-
"@fusion.dev/helix-cem": "0.
|
|
42
|
-
"@fusion.dev/helix-testing": "0.
|
|
41
|
+
"@fusion.dev/helix-cem": "0.24.0",
|
|
42
|
+
"@fusion.dev/helix-testing": "0.24.0",
|
|
43
43
|
"lit": "^3.2.1"
|
|
44
44
|
},
|
|
45
45
|
"homepage": "https://fusion.dev",
|