assign-gingerly 0.0.42 → 0.0.44
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/README.md +16 -0
- package/assignFeatures.js +84 -1
- package/assignFeatures.ts +112 -1
- package/index.js +1 -1
- package/index.ts +1 -1
- package/package.json +2 -2
- package/types/assign-gingerly/types.d.ts +6 -140
package/README.md
CHANGED
|
@@ -4656,6 +4656,9 @@ When the custom element's `connectedCallback` fires, the feature's `connectedCal
|
|
|
4656
4656
|
| `disconnectedCallback` | Feature needs cleanup (remove listeners, abort fetches) |
|
|
4657
4657
|
| `attributeChangedCallback` | Feature reacts to attribute changes (limited to element's `observedAttributes`) |
|
|
4658
4658
|
| `adoptedCallback` | Feature reacts to document adoption |
|
|
4659
|
+
| `formDisabledCallback` | Feature reacts to disabled state changes (form-associated elements) |
|
|
4660
|
+
| `formResetCallback` | Feature reacts to form reset (form-associated elements) |
|
|
4661
|
+
| `formStateRestoreCallback` | Feature restores state after navigation/session restore (form-associated elements) |
|
|
4659
4662
|
|
|
4660
4663
|
**Example: Feature that reads computed styles on connect**
|
|
4661
4664
|
|
|
@@ -4779,6 +4782,19 @@ await customElements.assignFeatures(MyElement, { feature: { spawn: SyncFeature }
|
|
|
4779
4782
|
// Both work — await on undefined is a no-op
|
|
4780
4783
|
```
|
|
4781
4784
|
|
|
4785
|
+
<details>
|
|
4786
|
+
<summary>Catalog of Published Custom Element Features</summary>
|
|
4787
|
+
|
|
4788
|
+
| Package | Description | Source |
|
|
4789
|
+
|---------|-------------|--------|
|
|
4790
|
+
| [truth-sourcer](https://www.npmjs.com/package/truth-sourcer) | Attribute/property binding and truth-sourcing for custom elements | [GitHub](https://github.com/bahrus/truth-sourcer) |
|
|
4791
|
+
| [be-reflective](https://www.npmjs.com/package/be-reflective) | CSS custom state reflection from computed styles | [GitHub](https://github.com/bahrus/be-reflective) |
|
|
4792
|
+
| [face-up](https://www.npmjs.com/package/face-up) | Form Associated Custom Element behavior via ElementInternals | [GitHub](https://github.com/bahrus/face-up) |
|
|
4793
|
+
| [roundabout](https://www.npmjs.com/package/roundabout) | Reactive view-model binding with template rendering and computed property orchestration | [GitHub](https://github.com/bahrus/roundabout#using-roundaboutfeature-with-assignfeatures) |
|
|
4794
|
+
| [time-ticker](https://www.npmjs.com/package/time-ticker) | Web component that fires events periodically (example of a feature-based component with no code in the class) | [GitHub](https://github.com/bahrus/time-ticker) |
|
|
4795
|
+
|
|
4796
|
+
</details>
|
|
4797
|
+
|
|
4782
4798
|
### Roadmap (future phases)
|
|
4783
4799
|
|
|
4784
4800
|
- **Nested features**: Support `?.path?.notation` keys directly in `assignFeatures` (without requiring `PropertyBag`).
|
package/assignFeatures.js
CHANGED
|
@@ -305,7 +305,10 @@ const VALID_CALLBACKS = new Set([
|
|
|
305
305
|
'connectedCallback',
|
|
306
306
|
'disconnectedCallback',
|
|
307
307
|
'attributeChangedCallback',
|
|
308
|
-
'adoptedCallback'
|
|
308
|
+
'adoptedCallback',
|
|
309
|
+
'formDisabledCallback',
|
|
310
|
+
'formResetCallback',
|
|
311
|
+
'formStateRestoreCallback'
|
|
309
312
|
]);
|
|
310
313
|
/**
|
|
311
314
|
* WeakMap tracking which callbacks have been patched on which constructors,
|
|
@@ -476,6 +479,86 @@ export function captureFeatureInitVals(instance) {
|
|
|
476
479
|
}
|
|
477
480
|
}
|
|
478
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Global store for inter-feature suggestions.
|
|
484
|
+
* Structure: Map<targetSymbol, Map<targetClass, Array<FeatureInfoSuggestion>>>
|
|
485
|
+
* Scoped per target class to prevent leaking between different custom elements.
|
|
486
|
+
*/
|
|
487
|
+
const featureInfoSuggestions = new Map();
|
|
488
|
+
/**
|
|
489
|
+
* Suggest configuration to another feature during registration.
|
|
490
|
+
*
|
|
491
|
+
* Call this in a feature's `static onAssigned` to provide config fragments
|
|
492
|
+
* (withAttrs, customData) that another feature should merge into its own config.
|
|
493
|
+
*
|
|
494
|
+
* The target feature is identified by a Symbol (stable across versions and mocks).
|
|
495
|
+
* Suggestions are scoped per target class to prevent leaking between different
|
|
496
|
+
* custom elements that use the same features.
|
|
497
|
+
*
|
|
498
|
+
* @param fromFeatureCtr - The feature class making the suggestion (for tracing)
|
|
499
|
+
* @param toFeatureSymbol - Symbol identifying the target feature
|
|
500
|
+
* @param featureInfo - Config fragments to suggest (withAttrs, customData)
|
|
501
|
+
* @param targetClass - The custom element class being configured
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* import { suggestFeatureInfo } from 'assign-gingerly/assignFeatures.js';
|
|
505
|
+
* import { ROUNDABOUT_FEATURE } from 'roundabout/symbols.js';
|
|
506
|
+
*
|
|
507
|
+
* class FaceUp {
|
|
508
|
+
* static onAssigned(ctr, featureConfig) {
|
|
509
|
+
* suggestFeatureInfo(FaceUp, ROUNDABOUT_FEATURE, {
|
|
510
|
+
* customData: { formBindings: { value: 'value' } }
|
|
511
|
+
* }, ctr);
|
|
512
|
+
* }
|
|
513
|
+
* }
|
|
514
|
+
*/
|
|
515
|
+
export function suggestFeatureInfo(fromFeatureCtr, toFeatureSymbol, featureInfo, targetClass) {
|
|
516
|
+
let symbolMap = featureInfoSuggestions.get(toFeatureSymbol);
|
|
517
|
+
if (!symbolMap) {
|
|
518
|
+
symbolMap = new Map();
|
|
519
|
+
featureInfoSuggestions.set(toFeatureSymbol, symbolMap);
|
|
520
|
+
}
|
|
521
|
+
let suggestions = symbolMap.get(targetClass);
|
|
522
|
+
if (!suggestions) {
|
|
523
|
+
suggestions = [];
|
|
524
|
+
symbolMap.set(targetClass, suggestions);
|
|
525
|
+
}
|
|
526
|
+
suggestions.push({
|
|
527
|
+
from: fromFeatureCtr,
|
|
528
|
+
...featureInfo
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Retrieve suggestions made to a feature by other features.
|
|
533
|
+
*
|
|
534
|
+
* Call this in a feature's `static onAssigned` to read config fragments
|
|
535
|
+
* suggested by other features that were processed earlier.
|
|
536
|
+
*
|
|
537
|
+
* @param toFeatureSymbol - Symbol identifying this feature (the target)
|
|
538
|
+
* @param targetClass - The custom element class being configured
|
|
539
|
+
* @returns Array of suggestions (empty if none)
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* import { getFeatureInfoSuggestions } from 'assign-gingerly/assignFeatures.js';
|
|
543
|
+
* import { ROUNDABOUT_FEATURE } from './symbols.js';
|
|
544
|
+
*
|
|
545
|
+
* class RoundaboutFeature {
|
|
546
|
+
* static onAssigned(ctr, featureConfig) {
|
|
547
|
+
* const suggestions = getFeatureInfoSuggestions(ROUNDABOUT_FEATURE, ctr);
|
|
548
|
+
* for (const suggestion of suggestions) {
|
|
549
|
+
* if (suggestion.customData) {
|
|
550
|
+
* featureConfig.customData = { ...featureConfig.customData, ...suggestion.customData };
|
|
551
|
+
* }
|
|
552
|
+
* }
|
|
553
|
+
* }
|
|
554
|
+
* }
|
|
555
|
+
*/
|
|
556
|
+
export function getFeatureInfoSuggestions(toFeatureSymbol, targetClass) {
|
|
557
|
+
const symbolMap = featureInfoSuggestions.get(toFeatureSymbol);
|
|
558
|
+
if (!symbolMap)
|
|
559
|
+
return [];
|
|
560
|
+
return symbolMap.get(targetClass) || [];
|
|
561
|
+
}
|
|
479
562
|
// =============================================================================
|
|
480
563
|
// PropertyBag — base class for nested feature containers
|
|
481
564
|
// =============================================================================
|
package/assignFeatures.ts
CHANGED
|
@@ -515,7 +515,10 @@ const VALID_CALLBACKS = new Set([
|
|
|
515
515
|
'connectedCallback',
|
|
516
516
|
'disconnectedCallback',
|
|
517
517
|
'attributeChangedCallback',
|
|
518
|
-
'adoptedCallback'
|
|
518
|
+
'adoptedCallback',
|
|
519
|
+
'formDisabledCallback',
|
|
520
|
+
'formResetCallback',
|
|
521
|
+
'formStateRestoreCallback'
|
|
519
522
|
]);
|
|
520
523
|
|
|
521
524
|
/**
|
|
@@ -728,6 +731,114 @@ export function captureFeatureInitVals(instance: any): void {
|
|
|
728
731
|
}
|
|
729
732
|
}
|
|
730
733
|
|
|
734
|
+
// =============================================================================
|
|
735
|
+
// Inter-feature communication: suggestFeatureInfo / getFeatureInfoSuggestions
|
|
736
|
+
// =============================================================================
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* A suggestion from one feature to another, containing config fragments to merge.
|
|
740
|
+
*/
|
|
741
|
+
export interface FeatureInfoSuggestion {
|
|
742
|
+
/** The feature class that made the suggestion (for debugging/tracing) */
|
|
743
|
+
from: Function;
|
|
744
|
+
/** Attribute patterns to merge into the target feature's withAttrs */
|
|
745
|
+
withAttrs?: any;
|
|
746
|
+
/** Custom data to merge into the target feature's customData */
|
|
747
|
+
customData?: any;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Global store for inter-feature suggestions.
|
|
752
|
+
* Structure: Map<targetSymbol, Map<targetClass, Array<FeatureInfoSuggestion>>>
|
|
753
|
+
* Scoped per target class to prevent leaking between different custom elements.
|
|
754
|
+
*/
|
|
755
|
+
const featureInfoSuggestions = new Map<symbol, Map<Function, FeatureInfoSuggestion[]>>();
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Suggest configuration to another feature during registration.
|
|
759
|
+
*
|
|
760
|
+
* Call this in a feature's `static onAssigned` to provide config fragments
|
|
761
|
+
* (withAttrs, customData) that another feature should merge into its own config.
|
|
762
|
+
*
|
|
763
|
+
* The target feature is identified by a Symbol (stable across versions and mocks).
|
|
764
|
+
* Suggestions are scoped per target class to prevent leaking between different
|
|
765
|
+
* custom elements that use the same features.
|
|
766
|
+
*
|
|
767
|
+
* @param fromFeatureCtr - The feature class making the suggestion (for tracing)
|
|
768
|
+
* @param toFeatureSymbol - Symbol identifying the target feature
|
|
769
|
+
* @param featureInfo - Config fragments to suggest (withAttrs, customData)
|
|
770
|
+
* @param targetClass - The custom element class being configured
|
|
771
|
+
*
|
|
772
|
+
* @example
|
|
773
|
+
* import { suggestFeatureInfo } from 'assign-gingerly/assignFeatures.js';
|
|
774
|
+
* import { ROUNDABOUT_FEATURE } from 'roundabout/symbols.js';
|
|
775
|
+
*
|
|
776
|
+
* class FaceUp {
|
|
777
|
+
* static onAssigned(ctr, featureConfig) {
|
|
778
|
+
* suggestFeatureInfo(FaceUp, ROUNDABOUT_FEATURE, {
|
|
779
|
+
* customData: { formBindings: { value: 'value' } }
|
|
780
|
+
* }, ctr);
|
|
781
|
+
* }
|
|
782
|
+
* }
|
|
783
|
+
*/
|
|
784
|
+
export function suggestFeatureInfo(
|
|
785
|
+
fromFeatureCtr: Function,
|
|
786
|
+
toFeatureSymbol: symbol,
|
|
787
|
+
featureInfo: { withAttrs?: any; customData?: any },
|
|
788
|
+
targetClass: Function
|
|
789
|
+
): void {
|
|
790
|
+
let symbolMap = featureInfoSuggestions.get(toFeatureSymbol);
|
|
791
|
+
if (!symbolMap) {
|
|
792
|
+
symbolMap = new Map();
|
|
793
|
+
featureInfoSuggestions.set(toFeatureSymbol, symbolMap);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
let suggestions = symbolMap.get(targetClass);
|
|
797
|
+
if (!suggestions) {
|
|
798
|
+
suggestions = [];
|
|
799
|
+
symbolMap.set(targetClass, suggestions);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
suggestions.push({
|
|
803
|
+
from: fromFeatureCtr,
|
|
804
|
+
...featureInfo
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Retrieve suggestions made to a feature by other features.
|
|
810
|
+
*
|
|
811
|
+
* Call this in a feature's `static onAssigned` to read config fragments
|
|
812
|
+
* suggested by other features that were processed earlier.
|
|
813
|
+
*
|
|
814
|
+
* @param toFeatureSymbol - Symbol identifying this feature (the target)
|
|
815
|
+
* @param targetClass - The custom element class being configured
|
|
816
|
+
* @returns Array of suggestions (empty if none)
|
|
817
|
+
*
|
|
818
|
+
* @example
|
|
819
|
+
* import { getFeatureInfoSuggestions } from 'assign-gingerly/assignFeatures.js';
|
|
820
|
+
* import { ROUNDABOUT_FEATURE } from './symbols.js';
|
|
821
|
+
*
|
|
822
|
+
* class RoundaboutFeature {
|
|
823
|
+
* static onAssigned(ctr, featureConfig) {
|
|
824
|
+
* const suggestions = getFeatureInfoSuggestions(ROUNDABOUT_FEATURE, ctr);
|
|
825
|
+
* for (const suggestion of suggestions) {
|
|
826
|
+
* if (suggestion.customData) {
|
|
827
|
+
* featureConfig.customData = { ...featureConfig.customData, ...suggestion.customData };
|
|
828
|
+
* }
|
|
829
|
+
* }
|
|
830
|
+
* }
|
|
831
|
+
* }
|
|
832
|
+
*/
|
|
833
|
+
export function getFeatureInfoSuggestions(
|
|
834
|
+
toFeatureSymbol: symbol,
|
|
835
|
+
targetClass: Function
|
|
836
|
+
): FeatureInfoSuggestion[] {
|
|
837
|
+
const symbolMap = featureInfoSuggestions.get(toFeatureSymbol);
|
|
838
|
+
if (!symbolMap) return [];
|
|
839
|
+
return symbolMap.get(targetClass) || [];
|
|
840
|
+
}
|
|
841
|
+
|
|
731
842
|
// =============================================================================
|
|
732
843
|
// PropertyBag — base class for nested feature containers
|
|
733
844
|
// =============================================================================
|
package/index.js
CHANGED
|
@@ -9,6 +9,6 @@ export { resolveTemplate } from './resolveTemplate.js';
|
|
|
9
9
|
export { getHost } from './getHost.js';
|
|
10
10
|
export { resolveValues, resolveValue } from './resolveValues.js';
|
|
11
11
|
export { assignFrom } from './assignFrom.js';
|
|
12
|
-
export { assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag } from './assignFeatures.js';
|
|
12
|
+
export { assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag, suggestFeatureInfo, getFeatureInfoSuggestions } from './assignFeatures.js';
|
|
13
13
|
export { installForwarding } from './installForwarding.js';
|
|
14
14
|
import './object-extension.js';
|
package/index.ts
CHANGED
|
@@ -9,6 +9,6 @@ export {resolveTemplate} from './resolveTemplate.js';
|
|
|
9
9
|
export {getHost} from './getHost.js';
|
|
10
10
|
export {resolveValues, resolveValue} from './resolveValues.js';
|
|
11
11
|
export {assignFrom} from './assignFrom.js';
|
|
12
|
-
export {assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag} from './assignFeatures.js';
|
|
12
|
+
export {assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag, suggestFeatureInfo, getFeatureInfoSuggestions} from './assignFeatures.js';
|
|
13
13
|
export {installForwarding} from './installForwarding.js';
|
|
14
14
|
import './object-extension.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assign-gingerly",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.44",
|
|
4
4
|
"description": "This package provides a utility function for carefully merging one object into another.",
|
|
5
5
|
"homepage": "https://github.com/bahrus/assign-gingerly#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@playwright/test": "1.60.0",
|
|
91
91
|
"spa-ssi": "0.0.27",
|
|
92
|
-
"@types/node": "25.
|
|
92
|
+
"@types/node": "25.8.0",
|
|
93
93
|
"typescript": "6.0.3"
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -179,13 +179,18 @@ export interface AttrConfig<T = unknown, TParserConfig = unknown> {
|
|
|
179
179
|
// * Defaults to true (initial read only)
|
|
180
180
|
// */
|
|
181
181
|
// initialOnly?: boolean;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Should make sure it is added to static observedAttribrutes
|
|
185
|
+
*/
|
|
186
|
+
sourceOfTruth?: boolean;
|
|
182
187
|
}
|
|
183
188
|
|
|
184
189
|
export type AttrPatterns<T = any> = {
|
|
185
190
|
/**
|
|
186
191
|
* Base prefix for attribute names
|
|
187
192
|
*/
|
|
188
|
-
base
|
|
193
|
+
base?: string;
|
|
189
194
|
|
|
190
195
|
/**
|
|
191
196
|
* Configuration for the base pattern
|
|
@@ -241,18 +246,6 @@ export interface IAssignGingerlyOptions {
|
|
|
241
246
|
* When the signal is aborted, all event listeners are automatically removed
|
|
242
247
|
*/
|
|
243
248
|
signal?: AbortSignal;
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* List of property names that should be treated as async methods.
|
|
247
|
-
* Works together with withMethods — async methods are awaited before
|
|
248
|
-
* continuing the chain.
|
|
249
|
-
*
|
|
250
|
-
* The path evaluation for keys containing async methods is fire-and-forget:
|
|
251
|
-
* assignGingerly remains synchronous and returns immediately.
|
|
252
|
-
*
|
|
253
|
-
* NOTE: Interaction with @each and @eachTime is not yet implemented.
|
|
254
|
-
*/
|
|
255
|
-
withAsyncMethods?: string[] | Set<string>;
|
|
256
249
|
}
|
|
257
250
|
|
|
258
251
|
/**
|
|
@@ -333,130 +326,3 @@ export interface ElementEnhancement{
|
|
|
333
326
|
dispose(registryItem: EnhancementConfig | string | symbol): void;
|
|
334
327
|
whenResolved(registryItem: EnhancementConfig | string | symbol, mountCtx?: any): Promise<any>;
|
|
335
328
|
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Context passed to feature spawn constructors
|
|
339
|
-
*/
|
|
340
|
-
export interface FeatureSpawnContext {
|
|
341
|
-
/** The feature key (e.g., 'photoTaker') */
|
|
342
|
-
key: string;
|
|
343
|
-
/** The SupportedFeatureConfig from static supportedFeatures */
|
|
344
|
-
optIn: SupportedFeatureConfig;
|
|
345
|
-
/** The FeatureConfig from assignFeatures */
|
|
346
|
-
injection: FeatureConfig;
|
|
347
|
-
/** The features registry reference */
|
|
348
|
-
featuresRegistry: FeaturesRegistry;
|
|
349
|
-
/** Shared context from the host element (via getSharedContext callback) */
|
|
350
|
-
shared?: any;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Configuration for a supported feature slot declared via static supportedFeatures
|
|
355
|
-
*/
|
|
356
|
-
export interface SupportedFeatureConfig {
|
|
357
|
-
/**
|
|
358
|
-
* Optional fallback class (or async spawner) to use if no implementation is injected.
|
|
359
|
-
*/
|
|
360
|
-
fallbackSpawn?:
|
|
361
|
-
| { new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }
|
|
362
|
-
| (() => Promise<{ new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }>);
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Optional runtime shape validation for the spawned instance.
|
|
366
|
-
* Return true if the instance is valid, false to throw.
|
|
367
|
-
*/
|
|
368
|
-
validateShape?: (spawnedInstance: any) => boolean;
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Optional callback to provide shared context (e.g., ElementInternals, private state)
|
|
372
|
-
* to the feature at construction time.
|
|
373
|
-
*
|
|
374
|
-
* Defined in the class body, this callback has access to #private fields.
|
|
375
|
-
* The returned object is passed to the feature constructor as `ctx.shared`.
|
|
376
|
-
*
|
|
377
|
-
* @param instance - The host element instance
|
|
378
|
-
* @returns An object containing shared data for the feature
|
|
379
|
-
*/
|
|
380
|
-
getSharedContext?: (instance: any) => any;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Class-level configuration for the features system.
|
|
385
|
-
* Declared as `static featuresConfig` on the class.
|
|
386
|
-
*/
|
|
387
|
-
export interface FeaturesClassConfig {
|
|
388
|
-
/**
|
|
389
|
-
* Lifecycle method configuration.
|
|
390
|
-
*
|
|
391
|
-
* If set to `true`, installs a method named 'whenFeatureReady' on the prototype.
|
|
392
|
-
* If set to an object, allows customizing the method name.
|
|
393
|
-
*
|
|
394
|
-
* The installed method accepts a feature key and returns a Promise that resolves
|
|
395
|
-
* with the feature instance once it's ready (useful for async spawners).
|
|
396
|
-
* For synchronous spawners, the Promise resolves immediately.
|
|
397
|
-
*
|
|
398
|
-
* Suggested default name: 'whenFeatureReady'
|
|
399
|
-
*/
|
|
400
|
-
lifecycleKeys?: true | {
|
|
401
|
-
/** Method name for awaiting feature readiness. Defaults to 'whenFeatureReady'. */
|
|
402
|
-
whenFeatureReady?: string;
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Configuration for a feature passed to assignFeatures.
|
|
408
|
-
* The feature equivalent of EnhancementConfig.
|
|
409
|
-
*/
|
|
410
|
-
export interface FeatureConfig {
|
|
411
|
-
/**
|
|
412
|
-
* The class to instantiate for this feature, or an async function that
|
|
413
|
-
* resolves to such a class (for lazy-loading).
|
|
414
|
-
*
|
|
415
|
-
* Synchronous: Constructor receives the host element as its first argument,
|
|
416
|
-
* a FeatureSpawnContext as second, and optional initVals as third.
|
|
417
|
-
*
|
|
418
|
-
* Asynchronous: A function (arrow or async) that returns a Promise resolving
|
|
419
|
-
* to a constructor. The getter returns a placeholder object immediately and
|
|
420
|
-
* instantiates the real class once the Promise resolves.
|
|
421
|
-
*/
|
|
422
|
-
spawn?:
|
|
423
|
-
| { new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }
|
|
424
|
-
| (() => Promise<{ new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }>);
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Attribute patterns for parsing element attributes into initVals.
|
|
428
|
-
* Attributes are the "base layer" — programmatic values override them.
|
|
429
|
-
* Always unprefixed for features (no enh- prefix).
|
|
430
|
-
*/
|
|
431
|
-
withAttrs?: AttrPatterns<any>;
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Reserved field for custom configuration data.
|
|
435
|
-
* Not interpreted by the library — available to the feature class
|
|
436
|
-
* via ctx.injection.customData in the constructor.
|
|
437
|
-
*/
|
|
438
|
-
customData?: any;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
export type SupportedFeaturesMap = Record<string, SupportedFeatureConfig>;
|
|
442
|
-
export type FeatureConfigsMap = Record<string, FeatureConfig>;
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* Registry for feature configs, keyed by constructor
|
|
446
|
-
*/
|
|
447
|
-
export declare class FeaturesRegistry {
|
|
448
|
-
has(ctr: Function): boolean;
|
|
449
|
-
get(ctr: Function): Map<string, FeatureConfig> | undefined;
|
|
450
|
-
set(ctr: Function, key: string, config: FeatureConfig): void;
|
|
451
|
-
hasKey(ctr: Function, key: string): boolean;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Core assignFeatures function.
|
|
456
|
-
* Validates inputs, registers feature configs, and installs lazy getters on the class prototype.
|
|
457
|
-
*/
|
|
458
|
-
export declare function assignFeatures(
|
|
459
|
-
ctr: Function,
|
|
460
|
-
features: FeatureConfigsMap,
|
|
461
|
-
featuresRegistry: FeaturesRegistry
|
|
462
|
-
): Promise<void> | undefined;
|