assign-gingerly 0.0.64 → 0.0.65

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.
@@ -261,6 +261,149 @@ export interface IAssignGingerlyOptions {
261
261
  signal?: AbortSignal;
262
262
  }
263
263
 
264
+ /**
265
+ * Options for assignTentatively — reversible assignment with change tracking.
266
+ *
267
+ * Supports a subset of assignGingerly's path features (nested paths, +=, =!, -=)
268
+ * with the addition of reversal tracking.
269
+ */
270
+ export interface IAssignTentativelyOptions {
271
+ /**
272
+ * Object to accumulate reversal entries into.
273
+ * If omitted, a new object is created internally.
274
+ * Pass an existing object to accumulate reversals across multiple calls.
275
+ *
276
+ * The reversal object can be passed to assignGingerly to undo all changes:
277
+ * @example
278
+ * const reversal = {};
279
+ * assignTentatively(obj, { name: 'Bob' }, { reversal });
280
+ * // Later:
281
+ * assignGingerly(obj, reversal); // restores name to original value
282
+ */
283
+ reversal?: Record<string | symbol, any>;
284
+
285
+ /**
286
+ * Alias mappings for property and method names.
287
+ * Same semantics as IAssignGingerlyOptions.aka — substituted before path evaluation.
288
+ */
289
+ aka?: Record<string, string>;
290
+ }
291
+
292
+ /**
293
+ * Options for assignFrom / assignFromAsync.
294
+ */
295
+ export interface AssignFromOptions {
296
+ /** Source object to resolve RHS path strings against */
297
+ from: any;
298
+
299
+ /** Protocol handlers (sync or async) */
300
+ protocols?: Record<string, (key: string) => any | Promise<any>>;
301
+
302
+ /** Method names to call during path evaluation */
303
+ withMethods?: string[] | Set<string>;
304
+
305
+ /** Alias mappings for path segments */
306
+ aka?: Record<string, string>;
307
+
308
+ /** AbortSignal for cleanup */
309
+ signal?: AbortSignal;
310
+
311
+ /** Loop variable bindings — expand pattern entries containing ${x} */
312
+ where_x_in?: string[];
313
+ /** Loop variable bindings — expand pattern entries containing ${y} */
314
+ where_y_in?: string[];
315
+ /** Loop variable bindings — expand pattern entries containing ${z} */
316
+ where_z_in?: string[];
317
+
318
+ /**
319
+ * Pin element references by variable name.
320
+ * Used with `#[varName]` syntax in LHS keys for fast repeated element access.
321
+ *
322
+ * - String value: existing element ID (uses getElementById)
323
+ * - Object value: { qry: 'selector' } — finds element via querySelector on target, auto-assigns an ID
324
+ * - Object value: { path: [...], expect?, fallback? } — child index path + auto-ID + optional validation
325
+ */
326
+ pin?: Record<string, string | { qry: string } | { path: number[]; expect?: string; fallback?: boolean }>;
327
+
328
+ /**
329
+ * Positional element references for use with `#[varName]` syntax.
330
+ * Resolves elements by child index path — no IDs assigned, no caching.
331
+ */
332
+ at?: Record<string, number[] | { path: number[]; expect?: string; fallback?: boolean }>;
333
+
334
+ /**
335
+ * Handler implementations scoped to this call.
336
+ * Key: the `do` name referenced in handler configs.
337
+ * Value: a class constructor, an import path, or a builtIns.* alias string.
338
+ */
339
+ handlers?: Record<string, AssignFromHandlerConstructor | string>;
340
+
341
+ /**
342
+ * Inferred assignments — automatically distribute source values to matching
343
+ * DOM elements based on structural conventions (itemprop, name, etc.).
344
+ */
345
+ infer?: {
346
+ byItemprop?: string[] | true;
347
+ '|'?: string[] | true;
348
+ byName?: string[] | true | { props: string[] | true; outside: string };
349
+ '@'?: string[] | true | { props: string[] | true; outside: string };
350
+ beVigilant?: boolean;
351
+ };
352
+
353
+ /**
354
+ * Bulk enhancement application via EMC JSON configs.
355
+ */
356
+ enhance?: Array<{ emc: string; matching?: string; parse?: boolean }>;
357
+
358
+ /** Registry for enhancement dependency injection (inherited from IAssignGingerlyOptions) */
359
+ registry?: any;
360
+
361
+ [key: string]: any;
362
+ }
363
+
364
+ /**
365
+ * Options for synchronous value resolution (getValues / getValue).
366
+ * Extends IAssignGingerlyOptions with synchronous protocol handlers.
367
+ */
368
+ export interface GetValuesOptions extends IAssignGingerlyOptions {
369
+ /**
370
+ * Internal root object for special $0 references.
371
+ * This is used by assignFrom to resolve values relative to the target object.
372
+ */
373
+ root?: any;
374
+
375
+ /**
376
+ * Synchronous protocol handlers for resolving protocol-prefixed values.
377
+ * Each handler receives the key portion and MUST return synchronously.
378
+ * For async protocols, use ResolveValuesOptions / resolveValues instead.
379
+ *
380
+ * @example
381
+ * protocols: {
382
+ * globalThis: (key) => globalThis[key],
383
+ * localStorage: (key) => JSON.parse(localStorage.getItem(key) || 'null')
384
+ * }
385
+ */
386
+ protocols?: Record<string, (key: string) => any>;
387
+ }
388
+
389
+ /**
390
+ * Options for async value resolution (resolveValues).
391
+ * Same as GetValuesOptions but protocol handlers may return Promises.
392
+ */
393
+ export interface ResolveValuesOptions extends IAssignGingerlyOptions {
394
+ /**
395
+ * Internal root object for special $0 references.
396
+ * This is used by assignFrom to resolve values relative to the target object.
397
+ */
398
+ root?: any;
399
+
400
+ /**
401
+ * Protocol handlers for resolving protocol-prefixed values (e.g., 'globalThis://key').
402
+ * Each handler receives the key portion and returns the resolved value (sync or async).
403
+ */
404
+ protocols?: Record<string, (key: string) => any | Promise<any>>;
405
+ }
406
+
264
407
  /**
265
408
  * Event dispatched when enhancement configs are registered
266
409
  */
@@ -538,15 +681,140 @@ export interface LazyLoadConfig extends HandlerConfig {
538
681
  if: string;
539
682
  /** Template element to clone (resolved via protocol or path) */
540
683
  instantiate: string;
541
- /** Insert method: 'appendChild' (default) or 'prepend' */
684
+ /** Insert method: 'appendChild' (default), 'prepend', or 'after' (sibling after target) */
542
685
  method?: string;
543
686
  /** If true, removes nodes when hiding instead of adding hidden attribute */
544
687
  forget?: boolean | string;
688
+ /** Enable view transitions */
689
+ transitional?: boolean | string;
690
+ /** CSS class for hiding (default: 'ag-hide', only used when transitional: true) */
691
+ hideClass?: string;
692
+ /** Custom CSS for the hide class (default: 'display: none') */
693
+ hideCss?: string;
545
694
  /** Optional async callback invoked after cloning, resolved from the VM */
546
695
  onInstantiated?: string;
696
+ /** Override auto-derived marker name */
697
+ markerName?: string;
698
+ /** Set inert attribute on hidden elements */
699
+ toggleInert?: boolean | string;
700
+ /** Set disabled property on hidden form elements */
701
+ toggleDisabled?: boolean | string;
547
702
  };
548
703
  }
549
704
 
705
+ /**
706
+ * Resolved parameters received by LazyLoadHandler.assign() after resolveValues processing.
707
+ */
708
+ export interface LazyLoadResolvedParams {
709
+ /** Condition — resolved to actual truthy/falsy value */
710
+ if: any;
711
+ /** Template element — resolved to HTMLTemplateElement or DocumentFragment */
712
+ instantiate: HTMLTemplateElement | DocumentFragment;
713
+ /** Insertion method (default: 'appendChild') */
714
+ method?: 'appendChild' | 'prepend' | 'after';
715
+ /** Remove nodes on hide instead of using hidden attribute */
716
+ forget?: boolean;
717
+ /** Enable view transitions */
718
+ transitional?: boolean;
719
+ /** CSS class for hiding (default: 'ag-hide', only used when transitional: true) */
720
+ hideClass?: string;
721
+ /** Custom CSS for the hide class (default: 'display: none') */
722
+ hideCss?: string;
723
+ /** Callback after clone+insert */
724
+ onInstantiated?: (ctx: LazyLoadInstantiatedContext) => void | Promise<void>;
725
+ /** Override auto-derived marker name */
726
+ markerName?: string;
727
+ /** Set inert attribute on hidden elements (removes from a11y tree + interaction) */
728
+ toggleInert?: boolean;
729
+ /** Set disabled property on hidden form elements */
730
+ toggleDisabled?: boolean;
731
+ /** Name of a pre-existing marker pair whose content should be removed on first activation.
732
+ * Used for SSR placeholder content (e.g., "Loading..." text) that disappears once real content loads. */
733
+ placeholder?: string;
734
+ /** Assignment config applied to cloned content before insertion.
735
+ * Same shape as manageTemplateList's fromEachItem: { assignToFragment, withOptions } or { configs: [...] } */
736
+ assign?: {
737
+ assignToFragment?: Record<string, any>;
738
+ withOptions?: Record<string, any>;
739
+ configs?: Array<{ assignToFragment?: Record<string, any>; withOptions?: Record<string, any> }>;
740
+ };
741
+ }
742
+
743
+ /**
744
+ * Configuration for the builtIns.lazyLoadSwitch handler.
745
+ */
746
+ export interface LazyLoadSwitchConfig extends HandlerConfig {
747
+ do: 'builtIns.lazyLoadSwitch';
748
+ resolve: {
749
+ /** Left-hand side of comparison (resolved from VM) */
750
+ lhs: string;
751
+ /** Comparison operator (default: '===') */
752
+ op?: '===' | '!==' | '==' | '!=' | '<' | '>' | '<=' | '>=';
753
+ /** Right-hand side of comparison (resolved from VM or literal) */
754
+ rhs: string;
755
+ /** Template element to clone (resolved via protocol or path) */
756
+ instantiate: string;
757
+ /** Insert method: 'appendChild' (default), 'prepend', or 'after' */
758
+ method?: string;
759
+ /** If true, removes nodes when hiding instead of adding hidden attribute */
760
+ forget?: boolean | string;
761
+ /** Enable view transitions */
762
+ transitional?: boolean | string;
763
+ /** CSS class for hiding (default: 'ag-hide', only used when transitional: true) */
764
+ hideClass?: string;
765
+ /** Custom CSS for the hide class (default: 'display: none') */
766
+ hideCss?: string;
767
+ /** Optional async callback invoked after cloning, resolved from the VM */
768
+ onInstantiated?: string;
769
+ };
770
+ }
771
+
772
+ /**
773
+ * Resolved parameters received by LazyLoadSwitchHandler.assign() after resolveValues processing.
774
+ */
775
+ export interface LazyLoadSwitchResolvedParams extends Omit<LazyLoadResolvedParams, 'if'> {
776
+ /** Left-hand side — resolved to actual value */
777
+ lhs: any;
778
+ /** Comparison operator (default: '===') */
779
+ op?: '===' | '!==' | '==' | '!=' | '<' | '>' | '<=' | '>=';
780
+ /** Right-hand side — resolved to actual value */
781
+ rhs: any;
782
+ }
783
+
784
+ export interface FromEachItemConfig {
785
+ assignToFragment?: Record<string, any>;
786
+ withOptions?: AssignFromOptions;
787
+ resolve?: {
788
+ key?: string;
789
+ }
790
+ }
791
+
792
+ export interface ManageTemplateListConfig extends HandlerConfig {
793
+ do: 'builtIns.manageTemplateList';
794
+ resolve: ManageTemplateListResolvedParams;
795
+ fromEachItem: FromEachItemConfig;
796
+ }
797
+
798
+ /**
799
+ * Resolved parameters received by ManageTemplateListHandler.assign().
800
+ */
801
+ export interface ManageTemplateListResolvedParams {
802
+ /** The iterable to loop over (resolved from VM) */
803
+ forEach: Iterable<any>;
804
+ /** Template element to clone per item */
805
+ instantiate: HTMLTemplateElement | DocumentFragment;
806
+ /** Insertion method (default: 'appendChild') */
807
+ method?: 'appendChild' | 'prepend' | 'after';
808
+ /** Remove nodes on hide instead of using hidden attribute */
809
+ forget?: boolean;
810
+ /** Override auto-derived marker name */
811
+ markerName?: string;
812
+ /** Wait for async rendering before DOM commit */
813
+ waitForSettled?: boolean | { idleMs?: number; timeout?: number };
814
+ /** Yield to browser every N items to prevent jank (default: undefined = no yielding) */
815
+ yieldEvery?: number;
816
+ }
817
+
550
818
  /**
551
819
  * Context passed to onInstantiated callbacks after template cloning.
552
820
  */
@@ -1,6 +1,6 @@
1
1
  // Core types for MountObserver v2 - Polyfill Supported Scenario I
2
2
 
3
- import {EnhancementConfigBase, EnhKey, AttrPatterns} from '../assign-gingerly/types';
3
+ import {EnhancementConfigBase, EnhKey, AttrPatterns, AssignFromOptions} from '../assign-gingerly/types';
4
4
 
5
5
  export type Constructor = new (...args: any[]) => any;
6
6
 
@@ -189,6 +189,14 @@ export interface MountConfig<TKeys extends string = string, TCustomData = unknow
189
189
  */
190
190
  stageOnMount?: Record<string, any>;
191
191
 
192
+ /**
193
+ * Options passed to assign-gingerly for assignOnMount, assignOnDismount, and stageOnMount.
194
+ * Enables features like method calls (withMethods), aliases (aka), async methods, and signal-based cleanup.
195
+ * Shared across all assign operations on this observer.
196
+ * @example { withMethods: ['setAttribute', 'removeAttribute'], aka: { '$': 'querySelector' } }
197
+ */
198
+ assignOptions?: Record<string, any>;
199
+
192
200
  /**
193
201
  * When true, enables detailed event dispatching for debugging and monitoring.
194
202
  * Provides granular lifecycle events for observation.
@@ -342,7 +350,7 @@ export interface IMountObserver extends EventTarget {
342
350
  observe(observedNode: Node): Promise<void>;
343
351
  disconnect(): void;
344
352
  disconnectedSignal: AbortSignal;
345
- assignGingerly(config: Record<string, any> | undefined): Promise<void>;
353
+ assign(config: Record<string, any> | undefined, options?: Record<string, any>): Promise<void>;
346
354
  getNotifier(element: Element): EventTarget;
347
355
  readonly options: MountObserverOptions;
348
356
  }
@@ -190,7 +190,7 @@ export interface RoundaboutOptions<TProps = unknown, TActions = TProps, ETProps
190
190
  * Options passed to every internal assignGingerly call.
191
191
  * See IAssignGingerlyOptions in assign-gingerly for details.
192
192
  */
193
- assignGingerlyOptions?: import('../assign-gingerly/types.js').IAssignGingerlyOptions,
193
+ assignOptions?: import('../assign-gingerly/types.js').IAssignGingerlyOptions,
194
194
 
195
195
  /**
196
196
  * Protocol handlers for resolving protocol-prefixed values in initialPropVals.
@@ -0,0 +1,18 @@
1
+ import { ElementEnhancementGateway, SpawnContext, FromEachItemConfig } from "../assign-gingerly/types";
2
+
3
+ export interface EndUserProps{
4
+ /**
5
+ * Property of host to pull list from.
6
+ * If not provided, the host itself is
7
+ * assumed to be iterable.
8
+ */
9
+ listProp?: string,
10
+
11
+ /**
12
+ * Specify id of peer element to pull list from.
13
+ */
14
+ src?: string;
15
+ each: FromEachItemConfig,
16
+ target: string,
17
+ updateOn: string,
18
+ }
@@ -432,7 +432,7 @@ Object.defineProperty(Object.prototype, 'assignGingerly', {
432
432
  Object.defineProperty(Object.prototype, 'assignTentatively', {
433
433
  value: function (source, options) {
434
434
  const reversal = options?.reversal ?? {};
435
- assignTentatively(this, source, { reversal });
435
+ assignTentatively(this, source, { ...options, reversal });
436
436
  return reversal;
437
437
  },
438
438
  writable: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assign-gingerly",
3
- "version": "0.0.64",
3
+ "version": "0.0.65",
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": {
@@ -169,6 +169,14 @@
169
169
  "./evaluatePathWithAsyncMethods.js": {
170
170
  "default": "./evaluatePathWithAsyncMethods.js",
171
171
  "types": "./evaluatePathWithAsyncMethods.ts"
172
+ },
173
+ "./handlers/nudge.js": {
174
+ "default": "./handlers/nudge.js",
175
+ "types": "./handlers/nudge.ts"
176
+ },
177
+ "./handlers/arr.js": {
178
+ "default": "./handlers/arr.js",
179
+ "types": "./handlers/arr.ts"
172
180
  }
173
181
  },
174
182
  "main": "index.js",
package/paths.ts CHANGED
@@ -287,7 +287,7 @@ export function doAssign(...pairs: Record<string, any>[]): { assign: Record<stri
287
287
  * const merges = [
288
288
  * ...forEachKeyIn<Person>(['firstName', 'lastName'], (key, $) => ({
289
289
  * ifKeyIn: [key],
290
- * assignOptions: { withIds: { [key]: { qry: `[name="${key}"]` } } },
290
+ * assignOptions: { pin: { [key]: { qry: `[name="${key}"]` } } },
291
291
  * ...doAssign(set($['#' + key]).to($[key]))
292
292
  * })),
293
293
  * ];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * withIdsCorrector.ts — Dev-time diagnostic for stale withIds coordinates.
2
+ * pinCorrector.ts — Dev-time diagnostic for stale pin coordinates.
3
3
  *
4
4
  * Dynamically imported only on mismatch — zero cost in production or when coordinates are correct.
5
5
  * Computes and logs the correct child index path for a given selector.
@@ -24,24 +24,24 @@ function computeChildPath(root, target) {
24
24
  return current === root ? path : null;
25
25
  }
26
26
  /**
27
- * Log a correction suggestion for a mismatched withIds config.
27
+ * Log a correction suggestion for a mismatched pin config.
28
28
  */
29
29
  export function logConfigCorrection(target, varName, config) {
30
30
  if (!config.expect)
31
31
  return;
32
32
  const correctEl = target.querySelector?.(config.expect);
33
33
  if (!correctEl) {
34
- console.warn(`withIds["${varName}"]: path [${config.path}] did not match "${config.expect}" ` +
34
+ console.warn(`pin["${varName}"]: path [${config.path}] did not match "${config.expect}" ` +
35
35
  `and querySelector also found no match. Check that the selector is correct.`);
36
36
  return;
37
37
  }
38
38
  const correctPath = computeChildPath(target, correctEl);
39
39
  if (correctPath) {
40
- console.warn(`withIds["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
40
+ console.warn(`pin["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
41
41
  `Suggested correction: [${correctPath.join(', ')}]`);
42
42
  }
43
43
  else {
44
- console.warn(`withIds["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
44
+ console.warn(`pin["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
45
45
  `Could not compute a child index path (element may not be a descendant of target).`);
46
46
  }
47
47
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * withIdsCorrector.ts — Dev-time diagnostic for stale withIds coordinates.
2
+ * pinCorrector.ts — Dev-time diagnostic for stale pin coordinates.
3
3
  *
4
4
  * Dynamically imported only on mismatch — zero cost in production or when coordinates are correct.
5
5
  * Computes and logs the correct child index path for a given selector.
@@ -26,7 +26,7 @@ function computeChildPath(root: Element, target: Element): number[] | null {
26
26
  }
27
27
 
28
28
  /**
29
- * Log a correction suggestion for a mismatched withIds config.
29
+ * Log a correction suggestion for a mismatched pin config.
30
30
  */
31
31
  export function logConfigCorrection(
32
32
  target: any,
@@ -38,7 +38,7 @@ export function logConfigCorrection(
38
38
  const correctEl = target.querySelector?.(config.expect);
39
39
  if (!correctEl) {
40
40
  console.warn(
41
- `withIds["${varName}"]: path [${config.path}] did not match "${config.expect}" ` +
41
+ `pin["${varName}"]: path [${config.path}] did not match "${config.expect}" ` +
42
42
  `and querySelector also found no match. Check that the selector is correct.`
43
43
  );
44
44
  return;
@@ -47,12 +47,12 @@ export function logConfigCorrection(
47
47
  const correctPath = computeChildPath(target, correctEl);
48
48
  if (correctPath) {
49
49
  console.warn(
50
- `withIds["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
50
+ `pin["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
51
51
  `Suggested correction: [${correctPath.join(', ')}]`
52
52
  );
53
53
  } else {
54
54
  console.warn(
55
- `withIds["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
55
+ `pin["${varName}"]: path [${config.path}] did not match "${config.expect}". ` +
56
56
  `Could not compute a child index path (element may not be a descendant of target).`
57
57
  );
58
58
  }
@@ -194,7 +194,8 @@ export async function processHandlerCommands(target, handlerKeys, pattern, optio
194
194
  resolvedParams = getValues(config.get, options.from, {
195
195
  withMethods: options.withMethods,
196
196
  aka: options.aka,
197
- protocols: options.protocols
197
+ protocols: options.protocols,
198
+ root: target
198
199
  });
199
200
  }
200
201
  // Resolve 'resolve' map asynchronously (yields to microtask queue)
@@ -202,7 +203,8 @@ export async function processHandlerCommands(target, handlerKeys, pattern, optio
202
203
  const asyncResolved = await resolveValues(config.resolve, options.from, {
203
204
  withMethods: options.withMethods,
204
205
  aka: options.aka,
205
- protocols: options.protocols
206
+ protocols: options.protocols,
207
+ root: target
206
208
  });
207
209
  Object.assign(resolvedParams, asyncResolved);
208
210
  }
@@ -220,7 +220,8 @@ export async function processHandlerCommands(
220
220
  resolvedParams = getValues(config.get, options.from, {
221
221
  withMethods: options.withMethods,
222
222
  aka: options.aka,
223
- protocols: options.protocols
223
+ protocols: options.protocols,
224
+ root: target
224
225
  });
225
226
  }
226
227
  // Resolve 'resolve' map asynchronously (yields to microtask queue)
@@ -228,7 +229,8 @@ export async function processHandlerCommands(
228
229
  const asyncResolved = await resolveValues(config.resolve, options.from, {
229
230
  withMethods: options.withMethods,
230
231
  aka: options.aka,
231
- protocols: options.protocols
232
+ protocols: options.protocols,
233
+ root: target
232
234
  });
233
235
  Object.assign(resolvedParams, asyncResolved);
234
236
  }
package/resolveIdRef.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * resolveIdRef.ts — Cached element resolution via #[x] syntax.
3
3
  *
4
- * Dynamically imported by assignFrom when `withIds` is provided or `#[x]` patterns are detected.
4
+ * Dynamically imported by assignFrom when `pin` is provided or `#[x]` patterns are detected.
5
5
  * Provides lazy, WeakRef-cached element lookups keyed by variable name.
6
6
  *
7
7
  * First access: runs the query against the target, auto-assigns an ID if needed, caches via WeakRef.
@@ -37,11 +37,11 @@ function generateUniqueId(rootNode) {
37
37
  *
38
38
  * @param varName - The variable name (e.g., 'x' from '#[x]')
39
39
  * @param target - The target element to query against
40
- * @param withIds - The withIds configuration map
40
+ * @param pin - The pin configuration map
41
41
  * @returns The resolved element, or undefined if not found
42
42
  */
43
- export function resolveIdVariable(varName, target, withIds) {
44
- const config = withIds[varName];
43
+ export function resolveIdVariable(varName, target, pin) {
44
+ const config = pin[varName];
45
45
  if (config === undefined)
46
46
  return undefined;
47
47
  // For 'at' option path-based configs (array or { path }), resolve directly from target — no ID, no caching
@@ -56,10 +56,10 @@ export function resolveIdVariable(varName, target, withIds) {
56
56
  return current instanceof Element ? current : undefined;
57
57
  }
58
58
  if (typeof config === 'object' && 'path' in config && !('qry' in config)) {
59
- // Determine if this is from 'at' (no ID assignment) or 'withIds' with path (assigns ID + caches)
60
- // When called from 'at', we skip ID/caching. When from 'withIds', we assign ID and cache.
59
+ // Determine if this is from 'at' (no ID assignment) or 'pin' with path (assigns ID + caches)
60
+ // When called from 'at', we skip ID/caching. When from 'pin', we assign ID and cache.
61
61
  // Distinguish by presence in the options — caller passes the merged map.
62
- // For now: { path } without 'noId' → assign ID + cache (withIds behavior)
62
+ // For now: { path } without 'noId' → assign ID + cache (pin behavior)
63
63
  const rootNode = target.getRootNode?.() ?? target;
64
64
  let current = target;
65
65
  for (const idx of config.path) {
@@ -78,7 +78,7 @@ export function resolveIdVariable(varName, target, withIds) {
78
78
  // Fire-and-forget: log correction suggestion
79
79
  const capturedConfig = config;
80
80
  const capturedVarName = varName;
81
- import('./withIdsCorrector.js').then(module => {
81
+ import('./pinCorrector.js').then(module => {
82
82
  module.logConfigCorrection(target, capturedVarName, capturedConfig);
83
83
  }).catch(() => { });
84
84
  }
package/resolveIdRef.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * resolveIdRef.ts — Cached element resolution via #[x] syntax.
3
3
  *
4
- * Dynamically imported by assignFrom when `withIds` is provided or `#[x]` patterns are detected.
4
+ * Dynamically imported by assignFrom when `pin` is provided or `#[x]` patterns are detected.
5
5
  * Provides lazy, WeakRef-cached element lookups keyed by variable name.
6
6
  *
7
7
  * First access: runs the query against the target, auto-assigns an ID if needed, caches via WeakRef.
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  /**
12
- * Configuration for a withIds entry.
12
+ * Configuration for a pin entry.
13
13
  */
14
14
  export type WithIdConfig = string | { qry: string } | number[] | { path: number[]; expect?: string; fallback?: boolean };
15
15
 
@@ -46,15 +46,15 @@ function generateUniqueId(rootNode: any): string {
46
46
  *
47
47
  * @param varName - The variable name (e.g., 'x' from '#[x]')
48
48
  * @param target - The target element to query against
49
- * @param withIds - The withIds configuration map
49
+ * @param pin - The pin configuration map
50
50
  * @returns The resolved element, or undefined if not found
51
51
  */
52
52
  export function resolveIdVariable(
53
53
  varName: string,
54
54
  target: any,
55
- withIds: Record<string, WithIdConfig>
55
+ pin: Record<string, WithIdConfig>
56
56
  ): Element | undefined {
57
- const config = withIds[varName];
57
+ const config = pin[varName];
58
58
  if (config === undefined) return undefined;
59
59
 
60
60
  // For 'at' option path-based configs (array or { path }), resolve directly from target — no ID, no caching
@@ -69,10 +69,10 @@ export function resolveIdVariable(
69
69
  }
70
70
 
71
71
  if (typeof config === 'object' && 'path' in config && !('qry' in config)) {
72
- // Determine if this is from 'at' (no ID assignment) or 'withIds' with path (assigns ID + caches)
73
- // When called from 'at', we skip ID/caching. When from 'withIds', we assign ID and cache.
72
+ // Determine if this is from 'at' (no ID assignment) or 'pin' with path (assigns ID + caches)
73
+ // When called from 'at', we skip ID/caching. When from 'pin', we assign ID and cache.
74
74
  // Distinguish by presence in the options — caller passes the merged map.
75
- // For now: { path } without 'noId' → assign ID + cache (withIds behavior)
75
+ // For now: { path } without 'noId' → assign ID + cache (pin behavior)
76
76
  const rootNode = target.getRootNode?.() ?? target;
77
77
  let current: any = target;
78
78
  for (const idx of config.path) {
@@ -91,7 +91,7 @@ export function resolveIdVariable(
91
91
  // Fire-and-forget: log correction suggestion
92
92
  const capturedConfig = config;
93
93
  const capturedVarName = varName;
94
- import('./withIdsCorrector.js').then(module => {
94
+ import('./pinCorrector.js').then(module => {
95
95
  module.logConfigCorrection(target, capturedVarName, capturedConfig);
96
96
  }).catch(() => {});
97
97
  }