assign-gingerly 0.0.53 → 0.0.55
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 +847 -5
- package/assignFrom.js +229 -9
- package/assignFrom.ts +338 -9
- package/assignGingerly.js +34 -1
- package/assignGingerly.ts +54 -1
- package/beVigilant.js +73 -0
- package/beVigilant.ts +85 -0
- package/enhanceAll.js +106 -0
- package/enhanceAll.ts +138 -0
- package/handlers/join.js +74 -0
- package/handlers/join.ts +80 -0
- package/handlers/lazyLoad.js +212 -0
- package/handlers/lazyLoad.ts +307 -0
- package/handlers/lazyLoadSwitch.js +58 -0
- package/handlers/lazyLoadSwitch.ts +63 -0
- package/handlers/microDataJoin.js +184 -0
- package/handlers/microDataJoin.ts +270 -0
- package/inferencer/.gitmodules +3 -0
- package/inferencer/.vscode/settings.json +2 -0
- package/inferencer/InferencedPropagator.js +230 -0
- package/inferencer/InferencedPropagator.ts +269 -0
- package/inferencer/LICENSE +21 -0
- package/inferencer/README.md +524 -0
- package/inferencer/Requirements/SupportForPropagator.md +368 -0
- package/inferencer/imports.html +7 -0
- package/inferencer/inferencer.js +254 -0
- package/inferencer/inferencer.ts +292 -0
- package/inferencer/package-lock.json +129 -0
- package/inferencer/package.json +60 -0
- package/inferencer/playwright-report/data/507ad515125e13390ea07de92f22331c913fa068.md +55 -0
- package/inferencer/playwright-report/index.html +90 -0
- package/inferencer/playwright.config.ts +54 -0
- package/inferencer/test-results/.last-run.json +6 -0
- package/inferencer/test-results/inferencer-Inferencer-Enha-535bc-inferencer-tests-in-browser-chromium/error-context.md +55 -0
- package/inferencer/tests/inferencedPropagator.html +428 -0
- package/inferencer/tests/inferencedPropagator.spec.ts +18 -0
- package/inferencer/tests/inferencer.html +355 -0
- package/inferencer/tests/inferencer.spec.ts +19 -0
- package/inferencer/tsconfig.json +19 -0
- package/inferencer/types/.kiro/specs/conversion-template/README.md +128 -0
- package/inferencer/types/.kiro/specs/conversion-template/design.md +360 -0
- package/inferencer/types/.kiro/specs/conversion-template/requirements.md +191 -0
- package/inferencer/types/.kiro/specs/conversion-template/tasks.md +174 -0
- package/inferencer/types/.kiro/steering/coding-standards.md +53 -0
- package/inferencer/types/.kiro/steering/conversion-guide.md +108 -0
- package/inferencer/types/.kiro/steering/declarative-configuration.md +108 -0
- package/inferencer/types/.kiro/steering/emc-json-serializability.md +306 -0
- package/inferencer/types/EnhancementConversionInstructions.md +1854 -0
- package/inferencer/types/LICENSE +21 -0
- package/inferencer/types/NewCustomElement.md +388 -0
- package/inferencer/types/NewCustomElementFeature.md +683 -0
- package/inferencer/types/NewEnhancementInstructions.md +705 -0
- package/inferencer/types/README.md +2 -0
- package/inferencer/types/agrace/types.d.ts +11 -0
- package/inferencer/types/assign-gingerly/types.d.ts +572 -0
- package/inferencer/types/be-a-beacon/types.d.ts +17 -0
- package/inferencer/types/be-bound/types.d.ts +66 -0
- package/inferencer/types/be-buttoned-up/types.d.ts +19 -0
- package/inferencer/types/be-calculating/types.d.ts +54 -0
- package/inferencer/types/be-clonable/types.d.ts +38 -0
- package/inferencer/types/be-committed/types.d.ts +22 -0
- package/inferencer/types/be-consoling/types.d.ts +24 -0
- package/inferencer/types/be-decked-with/types.d.ts +26 -0
- package/inferencer/types/be-delible/types.d.ts +27 -0
- package/inferencer/types/be-dispatching/types.d.ts +34 -0
- package/inferencer/types/be-evanescent/types.d.ts +20 -0
- package/inferencer/types/be-flashy/types.d.ts +21 -0
- package/inferencer/types/be-gone/types.d.ts +25 -0
- package/inferencer/types/be-observing/types.d.ts +55 -0
- package/inferencer/types/be-reflective/types.d.ts +78 -0
- package/inferencer/types/be-reformable/types.d.ts +49 -0
- package/inferencer/types/be-render-neutral/types.d.ts +32 -0
- package/inferencer/types/be-switched/types.d.ts +146 -0
- package/inferencer/types/be-typed/types.d.ts +32 -0
- package/inferencer/types/be-valued/types.d.ts +22 -0
- package/inferencer/types/data-props/types.d.ts +34 -0
- package/inferencer/types/do-inc/types.d.ts +56 -0
- package/inferencer/types/do-invoke/types.d.ts +38 -0
- package/inferencer/types/do-merge/types.d.ts +28 -0
- package/inferencer/types/do-toggle/types.d.ts +31 -0
- package/inferencer/types/face-up/types.d.ts +100 -0
- package/inferencer/types/fetch-for/types.d.ts +36 -0
- package/inferencer/types/folder-picker/types.d.ts +21 -0
- package/inferencer/types/global.d.ts +29 -0
- package/inferencer/types/id-generation/types.d.ts +26 -0
- package/inferencer/types/inferencer/types.d.ts +46 -0
- package/inferencer/types/mount-observer/types.d.ts +363 -0
- package/inferencer/types/nested-regex-groups/types.d.ts +107 -0
- package/inferencer/types/pipe-in/types.d.ts +52 -0
- package/inferencer/types/roundabout/types.d.ts +268 -0
- package/inferencer/types/soak-up/types.d.ts +40 -0
- package/inferencer/types/templ-maker/types.d.ts +43 -0
- package/inferencer/types/time-ticker/types.d.ts +62 -0
- package/inferencer/types/truth-sourcer/types.d.ts +44 -0
- package/inferencer/upSearch.js +27 -0
- package/inferencer/upSearch.ts +26 -0
- package/inferencer/withScopePerimeter.js +27 -0
- package/inferencer/withScopePerimeter.ts +33 -0
- package/inferredAssignments.js +38 -0
- package/inferredAssignments.ts +65 -0
- package/isAllowedImportPath.js +42 -0
- package/isAllowedImportPath.ts +53 -0
- package/package.json +57 -3
- package/paths.js +231 -0
- package/paths.ts +413 -0
- package/processHandlerCommands.js +188 -0
- package/processHandlerCommands.ts +217 -0
- package/resolveIdRef.js +144 -0
- package/resolveIdRef.ts +170 -0
- package/resolveValues.js +41 -2
- package/resolveValues.ts +41 -1
- package/transitionHelper.js +109 -0
- package/transitionHelper.ts +132 -0
- package/types/assign-gingerly/types.d.ts +89 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
export type Key<T = any> = keyof T & string;
|
|
2
|
+
|
|
3
|
+
export type Keysh<T = any> = Key<T> | Array<Key<T>>;
|
|
4
|
+
|
|
5
|
+
type PropsToProps<Props> = (x: Props) => (Promise<Partial<Props>> | Partial<Props>)
|
|
6
|
+
|
|
7
|
+
export interface LogicOp<Props = any, TActions = Props>{
|
|
8
|
+
/**
|
|
9
|
+
* Supported by trans-render
|
|
10
|
+
*/
|
|
11
|
+
ifAllOf?: Keysh<Props>,
|
|
12
|
+
|
|
13
|
+
ifKeyIn?: Keysh<Props>,
|
|
14
|
+
|
|
15
|
+
ifNoneOf?: Keysh<Props>,
|
|
16
|
+
|
|
17
|
+
ifEquals?: Array<Key<Props>>,
|
|
18
|
+
|
|
19
|
+
ifAtLeastOneOf?: Keysh<Props>,
|
|
20
|
+
|
|
21
|
+
ifNotAllOf?: Keysh<Props>,
|
|
22
|
+
|
|
23
|
+
debug?: boolean,
|
|
24
|
+
|
|
25
|
+
delay?: number,
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extends LogicOp with a `do` property for specifying which function to call.
|
|
31
|
+
* Used by positractions where the function is generic and view-model-neutral.
|
|
32
|
+
*/
|
|
33
|
+
export interface LogicOpWithDo<Props = any, TActions = Props> extends LogicOp<Props, TActions>{
|
|
34
|
+
do?:
|
|
35
|
+
| Function
|
|
36
|
+
| (keyof TActions & string)
|
|
37
|
+
| PropsToProps<Props>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type Actions<TProps = any, TActions = TProps> =
|
|
41
|
+
Partial<{[key in keyof TActions & string]: LogicOp<TProps>}>
|
|
42
|
+
//& Partial<{[key in `do_${keyof TActions & string}_on`]: Key<TActions> | Array<Key<TActions>> }>
|
|
43
|
+
;
|
|
44
|
+
|
|
45
|
+
export type Compacts<TProps = any, TActions = TProps, TEvents extends string = string> =
|
|
46
|
+
Partial<{[key in `negate_${keyof TProps & string}_to_${keyof TProps & string}`]: number}>
|
|
47
|
+
| Partial<{[key in `pass_length_of_${keyof TProps & string}_to_${keyof TProps & string}`]: number}>
|
|
48
|
+
| Partial<{[key in `echo_${keyof TProps & string}_to_${keyof TProps & string}`]: number}>
|
|
49
|
+
| Partial<{[key in `echo_${keyof TProps & string}_to_${keyof TProps & string}_after`]: keyof TProps}>
|
|
50
|
+
| Partial<{[key in `when_${keyof TProps & string}_changes_call_${keyof TActions & string}`]: number}>
|
|
51
|
+
| Partial<{[key in `when_${keyof TProps & string}_changes_toggle_${keyof TProps & string}`]: number}>
|
|
52
|
+
| Partial<{[key in `when_${keyof TProps & string}_changes_inc_${keyof TProps & string}_by`]: number}>
|
|
53
|
+
| Partial<{[key in `when_${keyof TProps & string}_changes_dispatch`]: string}>
|
|
54
|
+
| Partial<{[key in `on_${TEvents}_of_${keyof TProps & string}_inc_${keyof TProps & string}_by`]: number}>
|
|
55
|
+
| Partial<{[key in `on_${TEvents}_of_${keyof TProps & string}_set_${keyof TProps & string}_to`]: any}>
|
|
56
|
+
;
|
|
57
|
+
|
|
58
|
+
export type Hitches<TProps = any, TActions = TProps> =
|
|
59
|
+
| Partial<{[key in `when_${keyof TProps & string}_emits_${keyof TProps & string}_inc_${keyof TProps & string}_by`]: number}>
|
|
60
|
+
;
|
|
61
|
+
|
|
62
|
+
export type Handlers<ETProps = any, TActions = ETProps> =
|
|
63
|
+
| Partial<{[key in `${keyof ETProps & string}_to_${keyof TActions & string}_on` & string]: string }>;
|
|
64
|
+
|
|
65
|
+
export type Positractions<TProps = any, TActions = TProps> =
|
|
66
|
+
| Array<Positraction<TProps, TActions>>;
|
|
67
|
+
|
|
68
|
+
export interface Positraction<TProps = any, TActions = TProps> extends LogicOpWithDo<TProps, TActions> {
|
|
69
|
+
do:
|
|
70
|
+
| Function
|
|
71
|
+
| (keyof TActions & string)
|
|
72
|
+
| PropsToProps<TProps>
|
|
73
|
+
ifKeyIn?: Array<keyof TProps & string>,
|
|
74
|
+
ifAllOf?: Array<keyof TProps & string>,
|
|
75
|
+
//ifNoneOf: Array<keyof TProps & string>,
|
|
76
|
+
|
|
77
|
+
pass?: Array<(keyof TProps & string) | number | boolean | '$0' | '$0+' | `\`${string}\``>,
|
|
78
|
+
assignTo?: Array<null | (keyof TProps & string)>
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* A merge is a fully JSON-serializable reactive rule.
|
|
83
|
+
* When its conditions are met, it calls assignFrom(vm, assignFrom, { from: vm })
|
|
84
|
+
* to resolve RHS path strings against the vm and assign the results into the vm.
|
|
85
|
+
* No method or code is required.
|
|
86
|
+
*/
|
|
87
|
+
export interface Merge<TProps = any> extends LogicOp<TProps> {
|
|
88
|
+
/**
|
|
89
|
+
* Pattern object whose keys are LHS assignGingerly paths and whose
|
|
90
|
+
* values are RHS `?.`-prefixed path strings resolved against the vm.
|
|
91
|
+
*/
|
|
92
|
+
assign: Record<string, any>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type Merges<TProps = any> = Array<Merge<TProps>>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A yield derives a value from a collection using an index or key.
|
|
99
|
+
* Scenario I: Single selection by index — when the source array or index changes,
|
|
100
|
+
* the target property is set to source[index].
|
|
101
|
+
*/
|
|
102
|
+
export interface YieldConfig<TProps = any> {
|
|
103
|
+
/** The source array/collection property name */
|
|
104
|
+
from: keyof TProps & string;
|
|
105
|
+
/** The index property name (for array index lookup) */
|
|
106
|
+
atIndex?: keyof TProps & string;
|
|
107
|
+
/**
|
|
108
|
+
* Behavior when the index is out of bounds.
|
|
109
|
+
* - 'undefined' (default): set target to undefined
|
|
110
|
+
* - 'clamp': reset the index to 0 (selects first item)
|
|
111
|
+
*/
|
|
112
|
+
outOfBounds?: 'undefined' | 'clamp';
|
|
113
|
+
// Future: atKey, atIndices, keyProp, etc.
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type Yields<TProps = any> = {
|
|
117
|
+
[K in keyof TProps & string]?: YieldConfig<TProps>;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export interface RAConfig<
|
|
121
|
+
TProps = unknown, TActions = TProps, ETProps = TProps,
|
|
122
|
+
TCustomData = unknown, TEvents extends string = string > {
|
|
123
|
+
actions?: Actions<TProps,TActions>,
|
|
124
|
+
compacts?: Compacts<TProps, TActions, TEvents>,
|
|
125
|
+
//onsets?: Onsets<TProps, TActions>,
|
|
126
|
+
handlers?: Handlers<ETProps, TActions>,
|
|
127
|
+
hitches?: Hitches<TProps, TActions>,
|
|
128
|
+
positractions?: Positractions<TProps>,
|
|
129
|
+
merges?: Merges<TProps>,
|
|
130
|
+
yields?: Yields<TProps>,
|
|
131
|
+
/**
|
|
132
|
+
* Properties to explicitly monitor and propagate changes for.
|
|
133
|
+
* Use this to ensure getter/setters are installed for properties
|
|
134
|
+
* that aren't referenced by actions, compacts, merges, etc.
|
|
135
|
+
* but still need to fire propagator events (e.g., attribute-parsed
|
|
136
|
+
* properties that other features subscribe to).
|
|
137
|
+
*/
|
|
138
|
+
propagate?: keyof TProps & string | Array<keyof TProps & string>,
|
|
139
|
+
/**
|
|
140
|
+
* Configure automatic WeakRef wrapping for properties
|
|
141
|
+
*
|
|
142
|
+
* Properties listed here will automatically wrap values in WeakRef when set,
|
|
143
|
+
* and automatically deref when accessed. This prevents memory leaks for
|
|
144
|
+
* DOM elements and other objects that should be garbage collected.
|
|
145
|
+
*
|
|
146
|
+
* Options:
|
|
147
|
+
* - Array of property names: ['trigger', 'enhancedElement']
|
|
148
|
+
* - Object with configuration: { properties: ['trigger'], logIfCollected: 'warn' }
|
|
149
|
+
*
|
|
150
|
+
* When a WeakRef'd value is garbage collected, the getter returns undefined.
|
|
151
|
+
* Use logIfCollected to get notified when this happens.
|
|
152
|
+
*/
|
|
153
|
+
weakRef?: WeakRefConfig<TProps>,
|
|
154
|
+
|
|
155
|
+
defaultPropVals?: Partial<{[key in keyof TProps & string]: unknown}>,
|
|
156
|
+
|
|
157
|
+
customData?: TCustomData,
|
|
158
|
+
|
|
159
|
+
initialPropVals?: Partial<{[key in keyof TProps & string]: unknown}>,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface RoundaboutOptions<TProps = unknown, TActions = TProps, ETProps = TProps> extends RAConfig<TProps, TActions, ETProps> {
|
|
163
|
+
vm?: TProps & TActions & RoundaboutReady,
|
|
164
|
+
//for enhanced elements, pass in the container, referenced via $0.
|
|
165
|
+
container?: EventTarget,
|
|
166
|
+
|
|
167
|
+
//mountObservers?: Set<IMountObserver>
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Enable internal routing optimization for actions (default: false)
|
|
171
|
+
*
|
|
172
|
+
* When true: Action results are batched and cascaded before firing events.
|
|
173
|
+
* - Eliminates redundant action calls in diamond dependency patterns
|
|
174
|
+
* - More predictable: actions run once per logical change
|
|
175
|
+
* - Best for: Complex cascades, multiple properties returned from actions
|
|
176
|
+
*
|
|
177
|
+
* When false: Uses traditional approach with immediate event firing.
|
|
178
|
+
* - Simpler execution model, easier to debug
|
|
179
|
+
* - Slightly faster for simple linear cascades
|
|
180
|
+
* - Best for: Simple cascades, performance-critical paths
|
|
181
|
+
*
|
|
182
|
+
* Enable if you have:
|
|
183
|
+
* - Actions that return multiple properties
|
|
184
|
+
* - Multiple actions monitoring the same properties
|
|
185
|
+
* - Diamond dependencies (A→B, A→C, B→D, C→D)
|
|
186
|
+
*/
|
|
187
|
+
internalRouting?: boolean,
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Options passed to every internal assignGingerly call.
|
|
191
|
+
* See IAssignGingerlyOptions in assign-gingerly for details.
|
|
192
|
+
*/
|
|
193
|
+
assignGingerlyOptions?: import('../assign-gingerly/types.js').IAssignGingerlyOptions,
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Protocol handlers for resolving protocol-prefixed values in initialPropVals.
|
|
197
|
+
* When present, roundabout uses assignFrom (with protocol resolution and "..." spread)
|
|
198
|
+
* instead of plain assignGingerly for applying initial property values.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* protocols: {
|
|
202
|
+
* globalThis: (key) => globalThis[key],
|
|
203
|
+
* localStorage: (key) => JSON.parse(localStorage.getItem(key) || 'null')
|
|
204
|
+
* }
|
|
205
|
+
*/
|
|
206
|
+
protocols?: Record<string, (key: string) => any | Promise<any>>,
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Configuration for automatic WeakRef wrapping
|
|
213
|
+
*/
|
|
214
|
+
export interface WeakRefConfig<TProps = any> {
|
|
215
|
+
/**
|
|
216
|
+
* Properties to automatically wrap in WeakRef
|
|
217
|
+
*/
|
|
218
|
+
properties: Array<keyof TProps & string>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Logging behavior when deref returns null/undefined
|
|
222
|
+
* - 'error': console.error (default)
|
|
223
|
+
* - 'warn': console.warn
|
|
224
|
+
* - 'silent': no logging
|
|
225
|
+
* - function: custom logging function
|
|
226
|
+
*/
|
|
227
|
+
logIfCollected?: 'error' | 'warn' | 'silent' | ((propName: string) => void);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface RoundaboutReady{
|
|
231
|
+
/**
|
|
232
|
+
* Allow for assigning to read only props via the "backdoor"
|
|
233
|
+
* Bypasses getters / setters, sets directly to (private) memory slots
|
|
234
|
+
* Doesn't do any notification
|
|
235
|
+
* Allows for nested property setting
|
|
236
|
+
*/
|
|
237
|
+
covertAssignment(obj: any): Promise<void>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* fires event with name matching the name of the property when the value changes (but not via covertAssignment)
|
|
241
|
+
* when property is set via public interface, not (immediately) via an action method's return object
|
|
242
|
+
*/
|
|
243
|
+
readonly propagator : EventTarget | undefined;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
*
|
|
247
|
+
* https://github.com/whatwg/dom/issues/1296
|
|
248
|
+
*/
|
|
249
|
+
//readonly disconnectedSignal: AbortSignal
|
|
250
|
+
|
|
251
|
+
RAController: AbortController;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* During this time, queues/buses continue to perform "bookkeeping"
|
|
255
|
+
* but doesn't process the queue until sleep property becomes falsy.
|
|
256
|
+
* If truthy, can call await awake() before processing should resume
|
|
257
|
+
* [TODO]
|
|
258
|
+
*/
|
|
259
|
+
readonly sleep?: number | undefined;
|
|
260
|
+
|
|
261
|
+
awake(): Promise<void>;
|
|
262
|
+
|
|
263
|
+
//make the value sleep 1 step closer to be falsy
|
|
264
|
+
nudge(): void;
|
|
265
|
+
|
|
266
|
+
//make the value of sleep 1 step further away from being falsy
|
|
267
|
+
rock(): void;
|
|
268
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ElementEnhancementGateway, SpawnContext } from "../assign-gingerly/types";
|
|
2
|
+
import { StatementsResult } from "../nested-regex-groups/types";
|
|
3
|
+
|
|
4
|
+
export interface SoakUpParameters {
|
|
5
|
+
propMap: string;
|
|
6
|
+
sourceSpecifierString: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PropMap {
|
|
10
|
+
srcProp: string;
|
|
11
|
+
destProp?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SoakUpRule {
|
|
15
|
+
propMap: string;
|
|
16
|
+
sourceSpecifierString: string;
|
|
17
|
+
parsedPropMap?: PropMap[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface EndUserProps {
|
|
21
|
+
soakUpRules: StatementsResult<SoakUpParameters>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AllProps extends EndUserProps {
|
|
25
|
+
enhancedElement: Element;
|
|
26
|
+
parsedRules: SoakUpRule[];
|
|
27
|
+
resolved: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type AP = AllProps;
|
|
31
|
+
|
|
32
|
+
export type PAP = Partial<AP>;
|
|
33
|
+
|
|
34
|
+
export type ProPAP = Promise<PAP>;
|
|
35
|
+
|
|
36
|
+
export interface Actions {
|
|
37
|
+
init(self: AP, enhancedElement: Element & ElementEnhancementGateway, ctx: SpawnContext, initVals: PAP): Promise<void>;
|
|
38
|
+
fullyParse(self: AP): PAP;
|
|
39
|
+
hydrate(self: AP): ProPAP;
|
|
40
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context passed to the TemplateMaker feature constructor
|
|
3
|
+
*/
|
|
4
|
+
export interface FeatureSpawnContext {
|
|
5
|
+
key: string;
|
|
6
|
+
optIn: any;
|
|
7
|
+
injection: any;
|
|
8
|
+
featuresRegistry: any;
|
|
9
|
+
shared?: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Tracks whether the seed DOM fragment came from a shadow root or light DOM children.
|
|
14
|
+
*/
|
|
15
|
+
export type TemplateSource = 'shadow' | 'light';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Properties that the TemplateMaker feature exposes.
|
|
19
|
+
*/
|
|
20
|
+
export interface TemplateMakerProps {
|
|
21
|
+
/**
|
|
22
|
+
* The cloned DocumentFragment from the stored template.
|
|
23
|
+
*/
|
|
24
|
+
clone: DocumentFragment | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Internal state
|
|
29
|
+
*/
|
|
30
|
+
export interface AllProps extends TemplateMakerProps {
|
|
31
|
+
/**
|
|
32
|
+
* WeakRef to the host custom element
|
|
33
|
+
*/
|
|
34
|
+
hostRef: WeakRef<Element> | null;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Whether the template source was shadow DOM or light DOM.
|
|
38
|
+
*/
|
|
39
|
+
templateSource: TemplateSource | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type AP = AllProps;
|
|
43
|
+
export type PAP = Partial<AP>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { SpawnContext } from "../assign-gingerly/types";
|
|
2
|
+
import {FaceUpProps} from "../face-up/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration/properties that the TimeTicker feature exposes
|
|
6
|
+
*/
|
|
7
|
+
export interface FeatureProps {
|
|
8
|
+
/**
|
|
9
|
+
* Duration in milliseconds between ticks
|
|
10
|
+
*/
|
|
11
|
+
duration: number;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Whether the ticker is disabled (stops ticking when true)
|
|
15
|
+
*/
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Internal state (not exposed to consumers)
|
|
21
|
+
*/
|
|
22
|
+
export interface AllFeatureProps extends FeatureProps {
|
|
23
|
+
host: WeakRef<Element>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type AFP = AllFeatureProps;
|
|
27
|
+
export type PAFP = Partial<AFP>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Context passed to the feature constructor
|
|
31
|
+
*/
|
|
32
|
+
export interface FeatureSpawnContext extends SpawnContext {
|
|
33
|
+
key: string;
|
|
34
|
+
optIn: any;
|
|
35
|
+
injection: any;
|
|
36
|
+
featuresRegistry: any;
|
|
37
|
+
shared?: any;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface TimeTickerElementEndUserProps<T = any> extends FaceUpProps {
|
|
41
|
+
/**
|
|
42
|
+
* Duration in milliseconds between ticks
|
|
43
|
+
*/
|
|
44
|
+
duration: number;
|
|
45
|
+
|
|
46
|
+
items: T[];
|
|
47
|
+
|
|
48
|
+
name: string;
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface TimeTickerElementAllProps<T = any> extends TimeTickerElementEndUserProps{
|
|
53
|
+
item: T;
|
|
54
|
+
|
|
55
|
+
idx: number;
|
|
56
|
+
|
|
57
|
+
timeTicker: EventTarget;
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type T = TimeTickerElementAllProps;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context passed to the TruthSourcer feature constructor
|
|
3
|
+
*/
|
|
4
|
+
export interface FeatureSpawnContext {
|
|
5
|
+
key: string;
|
|
6
|
+
optIn: any;
|
|
7
|
+
injection: any;
|
|
8
|
+
featuresRegistry: any;
|
|
9
|
+
shared?: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Properties that the TruthSourcer feature manages
|
|
14
|
+
*/
|
|
15
|
+
export interface TruthSourcerProps {
|
|
16
|
+
/**
|
|
17
|
+
* The EventTarget that the host element uses to propagate property change events.
|
|
18
|
+
* TruthSourcer listens for events matching attribute names to sync property -> attribute.
|
|
19
|
+
*/
|
|
20
|
+
hostPropagator: EventTarget | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Internal state
|
|
25
|
+
*/
|
|
26
|
+
export interface AllProps extends TruthSourcerProps {
|
|
27
|
+
/**
|
|
28
|
+
* WeakRef to the host custom element
|
|
29
|
+
*/
|
|
30
|
+
hostRef: WeakRef<HTMLElement> | null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The list of observed attribute names (from static observedAttributes)
|
|
34
|
+
*/
|
|
35
|
+
observedAttributes: string[];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* AbortController for cleaning up event listeners
|
|
39
|
+
*/
|
|
40
|
+
abortController: AbortController | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type AP = AllProps;
|
|
44
|
+
export type PAP = Partial<AP>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export async function upSearch(element, id) {
|
|
2
|
+
if (id) {
|
|
3
|
+
const target = element.getRootNode().getElementById(id);
|
|
4
|
+
if (!target)
|
|
5
|
+
throw 404;
|
|
6
|
+
return await waitForIt(target);
|
|
7
|
+
}
|
|
8
|
+
const itemscope = element.closest('[itemscope]');
|
|
9
|
+
if (!itemscope) {
|
|
10
|
+
const host = element.getRootNode().host;
|
|
11
|
+
if (!host)
|
|
12
|
+
throw 404;
|
|
13
|
+
return await waitForIt(host);
|
|
14
|
+
}
|
|
15
|
+
if (element.getAttribute('itemscope')) {
|
|
16
|
+
//has actual value, need to work with itemscope manager
|
|
17
|
+
throw 'NI';
|
|
18
|
+
}
|
|
19
|
+
return waitForIt(itemscope);
|
|
20
|
+
}
|
|
21
|
+
async function waitForIt(element) {
|
|
22
|
+
const { localName } = element;
|
|
23
|
+
if (localName.includes('-')) {
|
|
24
|
+
await (element.customElementRegistry || customElements).whenDefined(localName);
|
|
25
|
+
}
|
|
26
|
+
return element;
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export async function upSearch(element: Element, id?: string){
|
|
2
|
+
if(id){
|
|
3
|
+
const target = (element.getRootNode() as DocumentFragment).getElementById(id);
|
|
4
|
+
if(!target) throw 404;
|
|
5
|
+
return await waitForIt(target);
|
|
6
|
+
}
|
|
7
|
+
const itemscope = element.closest('[itemscope]');
|
|
8
|
+
if(!itemscope) {
|
|
9
|
+
const host = (element.getRootNode() as ShadowRoot).host;
|
|
10
|
+
if(!host) throw 404;
|
|
11
|
+
return await waitForIt(host);
|
|
12
|
+
}
|
|
13
|
+
if(element.getAttribute('itemscope')){
|
|
14
|
+
//has actual value, need to work with itemscope manager
|
|
15
|
+
throw 'NI';
|
|
16
|
+
}
|
|
17
|
+
return waitForIt(itemscope);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function waitForIt(element: Element){
|
|
21
|
+
const {localName} = element;
|
|
22
|
+
if(localName.includes('-')){
|
|
23
|
+
await (element.customElementRegistry || customElements).whenDefined(localName);
|
|
24
|
+
}
|
|
25
|
+
return element;
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if an element is outside (not inside) any ancestor matching a selector.
|
|
3
|
+
* This implements "donut hole" scoping — useful for ensuring itemprop queries
|
|
4
|
+
* don't reach into nested itemscopes.
|
|
5
|
+
*
|
|
6
|
+
* @param rootNode - The root node to stop traversal at (not checked against selector)
|
|
7
|
+
* @param matchCandidate - The element to check
|
|
8
|
+
* @param outside - CSS selector for excluding ancestors (e.g., '[itemscope]')
|
|
9
|
+
* @returns true if element is outside all matching ancestors, false otherwise
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Find itemprop elements that aren't inside a nested itemscope:
|
|
13
|
+
* const candidates = container.querySelectorAll('[itemprop="name"]');
|
|
14
|
+
* const scoped = Array.from(candidates).filter(el =>
|
|
15
|
+
* withScopePerimeter(container, el, '[itemscope]')
|
|
16
|
+
* );
|
|
17
|
+
*/
|
|
18
|
+
export function withScopePerimeter(rootNode, matchCandidate, outside) {
|
|
19
|
+
let current = matchCandidate.parentElement;
|
|
20
|
+
while (current && current !== rootNode) {
|
|
21
|
+
if (current.matches(outside)) {
|
|
22
|
+
return false; // Found an excluding ancestor
|
|
23
|
+
}
|
|
24
|
+
current = current.parentElement;
|
|
25
|
+
}
|
|
26
|
+
return true; // No excluding ancestors found
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if an element is outside (not inside) any ancestor matching a selector.
|
|
3
|
+
* This implements "donut hole" scoping — useful for ensuring itemprop queries
|
|
4
|
+
* don't reach into nested itemscopes.
|
|
5
|
+
*
|
|
6
|
+
* @param rootNode - The root node to stop traversal at (not checked against selector)
|
|
7
|
+
* @param matchCandidate - The element to check
|
|
8
|
+
* @param outside - CSS selector for excluding ancestors (e.g., '[itemscope]')
|
|
9
|
+
* @returns true if element is outside all matching ancestors, false otherwise
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Find itemprop elements that aren't inside a nested itemscope:
|
|
13
|
+
* const candidates = container.querySelectorAll('[itemprop="name"]');
|
|
14
|
+
* const scoped = Array.from(candidates).filter(el =>
|
|
15
|
+
* withScopePerimeter(container, el, '[itemscope]')
|
|
16
|
+
* );
|
|
17
|
+
*/
|
|
18
|
+
export function withScopePerimeter(
|
|
19
|
+
rootNode: Node,
|
|
20
|
+
matchCandidate: Element,
|
|
21
|
+
outside: string
|
|
22
|
+
): boolean {
|
|
23
|
+
let current = matchCandidate.parentElement;
|
|
24
|
+
|
|
25
|
+
while (current && current !== rootNode) {
|
|
26
|
+
if (current.matches(outside)) {
|
|
27
|
+
return false; // Found an excluding ancestor
|
|
28
|
+
}
|
|
29
|
+
current = current.parentElement;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return true; // No excluding ancestors found
|
|
33
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inferredAssignments.ts — Handles inferred property assignment based on DOM structure.
|
|
3
|
+
*
|
|
4
|
+
* Dynamically imported by assignFrom when `inferredAssignments` option is present.
|
|
5
|
+
* Uses the inferencer submodule to determine the correct property for each element.
|
|
6
|
+
*/
|
|
7
|
+
import { Infer } from './inferencer/inferencer.js';
|
|
8
|
+
/**
|
|
9
|
+
* Process inferred assignments for a target element.
|
|
10
|
+
*
|
|
11
|
+
* @param target - The DOM element to search within
|
|
12
|
+
* @param from - The source object containing values to distribute
|
|
13
|
+
* @param config - The inferredAssignments configuration
|
|
14
|
+
*/
|
|
15
|
+
export async function processInferredAssignments(target, from, config) {
|
|
16
|
+
if (!(target instanceof Element))
|
|
17
|
+
return;
|
|
18
|
+
if (!from || typeof from !== 'object')
|
|
19
|
+
return;
|
|
20
|
+
const { byItemprop } = config;
|
|
21
|
+
if (byItemprop) {
|
|
22
|
+
const keys = byItemprop === true
|
|
23
|
+
? Object.keys(from)
|
|
24
|
+
: byItemprop;
|
|
25
|
+
const infer = new Infer(target);
|
|
26
|
+
for (const key of keys) {
|
|
27
|
+
if (!(key in from))
|
|
28
|
+
continue;
|
|
29
|
+
const value = from[key];
|
|
30
|
+
// Use inferencer's ['|'] method — scoped by itemscope boundary
|
|
31
|
+
const matches = infer['|'](key);
|
|
32
|
+
for (const match of matches) {
|
|
33
|
+
// Infer sets the right property (textContent, value, checked, dateTime, ish)
|
|
34
|
+
match.value = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inferredAssignments.ts — Handles inferred property assignment based on DOM structure.
|
|
3
|
+
*
|
|
4
|
+
* Dynamically imported by assignFrom when `inferredAssignments` option is present.
|
|
5
|
+
* Uses the inferencer submodule to determine the correct property for each element.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Infer } from './inferencer/inferencer.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for inferred assignments.
|
|
12
|
+
*/
|
|
13
|
+
export interface InferredAssignmentsConfig {
|
|
14
|
+
/**
|
|
15
|
+
* Array of property keys to distribute by itemprop attribute.
|
|
16
|
+
* For each key, finds [itemprop="${key}"] elements within scope (respecting
|
|
17
|
+
* itemscope boundaries) and sets the value using the inferred property.
|
|
18
|
+
*
|
|
19
|
+
* Pass `true` to infer all keys from the `from` source object.
|
|
20
|
+
*/
|
|
21
|
+
byItemprop?: string[] | true;
|
|
22
|
+
|
|
23
|
+
// Phase II:
|
|
24
|
+
// byName?: string[] | true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Process inferred assignments for a target element.
|
|
29
|
+
*
|
|
30
|
+
* @param target - The DOM element to search within
|
|
31
|
+
* @param from - The source object containing values to distribute
|
|
32
|
+
* @param config - The inferredAssignments configuration
|
|
33
|
+
*/
|
|
34
|
+
export async function processInferredAssignments(
|
|
35
|
+
target: any,
|
|
36
|
+
from: any,
|
|
37
|
+
config: InferredAssignmentsConfig
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
if (!(target instanceof Element)) return;
|
|
40
|
+
if (!from || typeof from !== 'object') return;
|
|
41
|
+
|
|
42
|
+
const { byItemprop } = config;
|
|
43
|
+
|
|
44
|
+
if (byItemprop) {
|
|
45
|
+
const keys = byItemprop === true
|
|
46
|
+
? Object.keys(from)
|
|
47
|
+
: byItemprop;
|
|
48
|
+
|
|
49
|
+
const infer = new Infer(target);
|
|
50
|
+
|
|
51
|
+
for (const key of keys) {
|
|
52
|
+
if (!(key in from)) continue;
|
|
53
|
+
|
|
54
|
+
const value = from[key];
|
|
55
|
+
|
|
56
|
+
// Use inferencer's ['|'] method — scoped by itemscope boundary
|
|
57
|
+
const matches: Infer[] = infer['|'](key);
|
|
58
|
+
|
|
59
|
+
for (const match of matches) {
|
|
60
|
+
// Infer sets the right property (textContent, value, checked, dateTime, ish)
|
|
61
|
+
match.value = value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|