selective-ui 1.1.2 → 1.1.3

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.
@@ -1,4 +1,4 @@
1
- /*! Selective UI v1.1.2 | MIT License */
1
+ /*! Selective UI v1.1.3 | MIT License */
2
2
  /**
3
3
  * @class
4
4
  */
@@ -5151,6 +5151,9 @@ class ElementAdditionObserver {
5151
5151
  }
5152
5152
 
5153
5153
  class Selective {
5154
+ constructor() {
5155
+ this.bindedQueries = new Map();
5156
+ }
5154
5157
  /**
5155
5158
  * Binds Selective UI to all <select> elements matching the query.
5156
5159
  * Merges provided options with defaults, schedules `on.load` callbacks,
@@ -5159,7 +5162,7 @@ class Selective {
5159
5162
  * @param {string} query - CSS selector for target <select> elements.
5160
5163
  * @param {object} options - Configuration overrides merged with defaults.
5161
5164
  */
5162
- static bind(query, options) {
5165
+ bind(query, options) {
5163
5166
  const merged = Libs.mergeConfig(Libs.getDefaultConfig(), options);
5164
5167
  // Ensure hooks exist
5165
5168
  merged.on = merged.on ?? {};
@@ -5193,7 +5196,7 @@ class Selective {
5193
5196
  * @param {string} [query="*"] - CSS selector or "*" to search all bound instances.
5194
5197
  * @returns {SelectiveActionApi} - Aggregated actions; {isEmpty:true} if none found.
5195
5198
  */
5196
- static find(query = "*") {
5199
+ find(query = "*") {
5197
5200
  const empty = { isEmpty: true };
5198
5201
  if (query === "*") {
5199
5202
  query = Libs.getBindedCommand().join(", ");
@@ -5228,7 +5231,7 @@ class Selective {
5228
5231
  * Starts observing the document for newly added <select> elements and applies
5229
5232
  * Selective bindings automatically when they match previously bound queries.
5230
5233
  */
5231
- static Observer() {
5234
+ Observer() {
5232
5235
  this.EAObserver = new ElementAdditionObserver();
5233
5236
  this.EAObserver.onDetect((selectElement) => {
5234
5237
  this.bindedQueries.forEach((options, query) => {
@@ -5252,7 +5255,7 @@ class Selective {
5252
5255
  *
5253
5256
  * @param {null|string|HTMLSelectElement} target - Target to destroy.
5254
5257
  */
5255
- static destroy(target = null) {
5258
+ destroy(target = null) {
5256
5259
  if (target === null) {
5257
5260
  this.destroyAll();
5258
5261
  }
@@ -5267,7 +5270,7 @@ class Selective {
5267
5270
  * Destroys all bound Selective instances and clears bindings/state.
5268
5271
  * Stops the ElementAdditionObserver.
5269
5272
  */
5270
- static destroyAll() {
5273
+ destroyAll() {
5271
5274
  const bindedCommands = Libs.getBindedCommand();
5272
5275
  bindedCommands.forEach((query) => this.destroyByQuery(query));
5273
5276
  this.bindedQueries.clear();
@@ -5280,7 +5283,7 @@ class Selective {
5280
5283
  *
5281
5284
  * @param {string} query - CSS selector whose Selective instances should be destroyed.
5282
5285
  */
5283
- static destroyByQuery(query) {
5286
+ destroyByQuery(query) {
5284
5287
  const selectElements = Libs.getElements(query);
5285
5288
  selectElements.forEach((element) => {
5286
5289
  if (element.tagName === "SELECT")
@@ -5298,7 +5301,7 @@ class Selective {
5298
5301
  *
5299
5302
  * @param {HTMLSelectElement} selectElement - The target <select> element to clean up.
5300
5303
  */
5301
- static destroyElement(selectElement) {
5304
+ destroyElement(selectElement) {
5302
5305
  const bindMap = Libs.getBinderMap(selectElement);
5303
5306
  if (!bindMap)
5304
5307
  return;
@@ -5335,7 +5338,7 @@ class Selective {
5335
5338
  * @param {string} query - CSS selector to rebind.
5336
5339
  * @param {object} options - Configuration for the new binding.
5337
5340
  */
5338
- static rebind(query, options) {
5341
+ rebind(query, options) {
5339
5342
  this.destroyByQuery(query);
5340
5343
  this.bind(query, options);
5341
5344
  }
@@ -5348,7 +5351,7 @@ class Selective {
5348
5351
  * @param {object} options - Configuration used for this instance.
5349
5352
  * @returns {boolean} - False if already bound; true if successfully applied.
5350
5353
  */
5351
- static applySelectBox(selectElement, options) {
5354
+ applySelectBox(selectElement, options) {
5352
5355
  if (Libs.getBinderMap(selectElement) || Libs.getUnbinderMap(selectElement)) {
5353
5356
  return false;
5354
5357
  }
@@ -5379,7 +5382,7 @@ class Selective {
5379
5382
  * @param {*} action - The object containing the property.
5380
5383
  * @returns {PropertiesType} - The derived property type and name.
5381
5384
  */
5382
- static getProperties(actionName, action) {
5385
+ getProperties(actionName, action) {
5383
5386
  const descriptor = Object.getOwnPropertyDescriptor(action, actionName);
5384
5387
  let type = "variable";
5385
5388
  if (descriptor?.get || (descriptor?.set && typeof action[actionName] !== "function")) {
@@ -5398,7 +5401,7 @@ class Selective {
5398
5401
  * @param {string} name - The property name to expose.
5399
5402
  * @param {HTMLElement[]} els - The list of bound elements to proxy.
5400
5403
  */
5401
- static buildGetSetAction(object, name, els) {
5404
+ buildGetSetAction(object, name, els) {
5402
5405
  Object.defineProperty(object, name, {
5403
5406
  get() {
5404
5407
  const binded = Libs.getBinderMap(els[0]);
@@ -5424,7 +5427,7 @@ class Selective {
5424
5427
  * @param {string} name - The function name to expose.
5425
5428
  * @param {HTMLElement[]} els - The list of bound elements to invoke against.
5426
5429
  */
5427
- static buildFuntionAction(object, name, els) {
5430
+ buildFuntionAction(object, name, els) {
5428
5431
  object[name] = (...params) => {
5429
5432
  for (let index = 0; index < els.length; index++) {
5430
5433
  const el = els[index];
@@ -5440,131 +5443,145 @@ class Selective {
5440
5443
  };
5441
5444
  }
5442
5445
  }
5443
- Selective.bindedQueries = new Map();
5444
5446
 
5445
5447
  /**
5446
- * Checks for a previously loaded global library instance by name.
5447
- * initializes a loading placeholder on `window[name]` and returns false.
5448
+ * Entry module for SelectiveUI.
5448
5449
  *
5449
- * @param {string} LIB_NAME - The global namespace key to check on `window`.
5450
- * @returns {boolean} - True if a loaded instance already exists; false otherwise.
5450
+ * This file exposes the public API surface of the library:
5451
+ * - version/name metadata
5452
+ * - DOM binding helpers (bind/find/rebind/destroy)
5453
+ * - effector factory for imperative effects
5454
+ *
5455
+ * Notes:
5456
+ * - CSS imports below are *side-effect imports* used by bundlers (Vite/Webpack/Rollup)
5457
+ * to include component styles in the final bundle.
5451
5458
  */
5452
- function checkDuplicate(LIB_NAME) {
5453
- if (typeof window === "undefined")
5454
- return false;
5455
- const existing = window[LIB_NAME];
5456
- if (existing) {
5457
- console.warn(`[${LIB_NAME}] Already loaded (v${existing.version}). ` +
5458
- `Using existing instance. Please remove duplicate <script> tags.`);
5459
- return true;
5459
+ /** Base/global styles for SelectiveUI. */
5460
+ const iVersion = "1.1.3";
5461
+ const iName = "SelectiveUI";
5462
+ if (typeof globalThis.GLOBAL_SEUI == "undefined") {
5463
+ const SECLASS = new Selective();
5464
+ globalThis.GLOBAL_SEUI = {
5465
+ version: iVersion,
5466
+ name: iName,
5467
+ bind: SECLASS.bind.bind(SECLASS),
5468
+ find: SECLASS.find.bind(SECLASS),
5469
+ destroy: SECLASS.destroy.bind(SECLASS),
5470
+ effector: Effector.bind(Effector),
5471
+ rebind: SECLASS.rebind.bind(SECLASS)
5472
+ };
5473
+ let domInitialized = false;
5474
+ function init() {
5475
+ if (domInitialized)
5476
+ return;
5477
+ domInitialized = true;
5478
+ document.addEventListener("mousedown", () => {
5479
+ const sels = Libs.getBindedCommand();
5480
+ if (sels.length > 0) {
5481
+ const actionApi = SECLASS.find(sels.join(", "));
5482
+ if (!actionApi.isEmpty)
5483
+ actionApi.close();
5484
+ }
5485
+ });
5486
+ SECLASS.Observer();
5460
5487
  }
5461
- const base = existing ?? {};
5462
- window[LIB_NAME] = base;
5463
- return false;
5488
+ if (typeof document !== "undefined") {
5489
+ if (document.readyState === "loading") {
5490
+ document.addEventListener("DOMContentLoaded", init);
5491
+ }
5492
+ else {
5493
+ init();
5494
+ }
5495
+ }
5496
+ console.log(`[${iName}] v${iVersion} loaded successfully`);
5497
+ }
5498
+ else {
5499
+ console.warn(`[${globalThis.GLOBAL_SEUI.name}] Already loaded (v${globalThis.GLOBAL_SEUI.version}). ` +
5500
+ `Using existing instance. Please remove duplicate <script> tags.`);
5464
5501
  }
5465
5502
  /**
5466
- * Marks a global library namespace as fully loaded, sets version metadata,
5467
- * merges its public API into `window[name]`, freezes the object to prevent
5468
- * further mutation, and logs a success message.
5503
+ * Current library version.
5469
5504
  *
5470
- * @param {string} name - The global namespace key on `window`.
5471
- * @param {string} version - Semantic version string of the library.
5472
- * @param {SelectiveUIGlobal} api - Public API surface to expose under `window[name]`.
5473
- * @returns {void}
5505
+ * Declared as `const` literal type to enable strict typing and easy tree-shaking.
5474
5506
  */
5475
- function markLoaded(name, version, api) {
5476
- if (typeof window === "undefined")
5477
- return;
5478
- const ns = (window[name] ?? {});
5479
- ns.version = version;
5480
- Object.assign(ns, api);
5481
- Object.freeze(ns);
5482
- window[name] = ns;
5483
- console.log(`[${name}] v${version} loaded successfully`);
5484
- }
5485
-
5486
- const version = "1.1.2";
5487
- const name = "SelectiveUI";
5488
- const alreadyLoaded = checkDuplicate(name);
5489
- function getGlobal() {
5490
- if (typeof window === "undefined")
5491
- return undefined;
5492
- return window[name];
5493
- }
5507
+ const version = globalThis.GLOBAL_SEUI.version;
5494
5508
  /**
5495
- * Enhances all <select> elements matching the query with Selective UI.
5496
- * If a prior global instance is already loaded, proxies the call to it; otherwise uses local Selective.bind.
5509
+ * Library name identifier.
5510
+ *
5511
+ * Can be used for debugging, logging, telemetry, or exposing global namespace metadata.
5512
+ */
5513
+ const name = globalThis.GLOBAL_SEUI.name;
5514
+ /**
5515
+ * Bind SelectiveUI behaviors to elements matched by a CSS selector.
5516
+ *
5517
+ * Typically used to initialize/select-enhance native `<select>` elements or custom containers.
5518
+ *
5519
+ * @param query - A CSS selector string used to find target elements in the DOM.
5520
+ * @param options - Optional configuration used during initialization.
5521
+ *
5522
+ * @example
5523
+ * bind(".my-select", { searchable: true });
5497
5524
  */
5498
5525
  function bind(query, options = {}) {
5499
- const global = getGlobal();
5500
- if (alreadyLoaded && global)
5501
- return global.bind(query, options);
5502
- Selective.bind(query, options);
5526
+ globalThis.GLOBAL_SEUI.bind(query, options);
5503
5527
  }
5504
5528
  /**
5505
- * Retrieves the dynamic action API for bound instances matching the query.
5506
- * Proxies to an already-loaded global instance if present; otherwise uses local Selective.find.
5529
+ * Find an existing SelectiveUI instance/actions API by selector.
5530
+ *
5531
+ * @param query - A CSS selector string previously used with `bind()` (or matching the same element).
5532
+ * @returns An action API that allows controlling the instance (open/close/setValue/etc).
5533
+ *
5534
+ * @remarks
5535
+ * The return type is casted to `SelectiveActionApi` for a stable public contract.
5507
5536
  */
5508
5537
  function find(query) {
5509
- const global = getGlobal();
5510
- if (alreadyLoaded && global)
5511
- return global.find(query);
5512
- return Selective.find(query);
5538
+ return globalThis.GLOBAL_SEUI.find(query);
5513
5539
  }
5514
5540
  /**
5515
- * Destroys Selective instances associated with the given query.
5516
- * Proxies to a global loaded instance if available; otherwise uses local Selective.destroy.
5541
+ * Destroy SelectiveUI instance(s) and release related resources.
5542
+ *
5543
+ * @param query - A CSS selector string identifying which instance(s) to destroy.
5544
+ * If `null`, destroys all instances managed by SelectiveUI.
5545
+ *
5546
+ * @example
5547
+ * destroy(".my-select");
5548
+ *
5549
+ * @example
5550
+ * // Destroy all instances
5551
+ * destroy();
5517
5552
  */
5518
5553
  function destroy(query = null) {
5519
- const global = getGlobal();
5520
- if (alreadyLoaded && global)
5521
- return global.destroy(query);
5522
- Selective.destroy(query);
5554
+ globalThis.GLOBAL_SEUI.destroy(query);
5523
5555
  }
5524
5556
  /**
5525
- * Rebinds Selective for the given query by destroying existing instances and binding anew.
5526
- * Proxies to a global loaded instance if available; otherwise uses local Selective.rebind.
5557
+ * Rebind (reinitialize) SelectiveUI on the given selector.
5558
+ *
5559
+ * Useful when:
5560
+ * - The DOM has changed dynamically
5561
+ * - Options need to be reapplied
5562
+ * - You want a clean re-init without manual destroy + bind
5563
+ *
5564
+ * @param query - A CSS selector string used to locate target elements.
5565
+ * @param options - Optional configuration applied during re-initialization.
5527
5566
  */
5528
5567
  function rebind(query, options = {}) {
5529
- const global = getGlobal();
5530
- if (alreadyLoaded && global)
5531
- return global.rebind(query, options);
5532
- Selective.rebind(query, options);
5568
+ globalThis.GLOBAL_SEUI.rebind(query, options);
5533
5569
  }
5534
5570
  /**
5535
- * Returns an effector instance for a given element, enabling expand/collapse/resize animations.
5536
- * Proxies to a global loaded instance if available; otherwise constructs a local Effector.
5571
+ * Create an Effector instance for a given element.
5572
+ *
5573
+ * An effector provides imperative effect utilities bound to an element, such as animations,
5574
+ * positioning, UI transitions, or event-driven effects (depending on implementation).
5575
+ *
5576
+ * @param element - A CSS selector string or a direct HTMLElement reference.
5577
+ * @returns An `EffectorInterface` implementation bound to the given element.
5578
+ *
5579
+ * @example
5580
+ * const fx = effector("#popup");
5581
+ * fx.show();
5537
5582
  */
5538
5583
  function effector(element) {
5539
- const global = getGlobal();
5540
- if (alreadyLoaded && global)
5541
- return global.effector(element);
5542
- return Effector(element);
5543
- }
5544
- if (!alreadyLoaded) {
5545
- const api = { bind, find, destroy, rebind, effector, version };
5546
- markLoaded(name, version, api);
5547
- let domInitialized = false;
5548
- function init() {
5549
- if (domInitialized)
5550
- return;
5551
- domInitialized = true;
5552
- document.addEventListener("mousedown", () => {
5553
- const sels = Libs.getBindedCommand();
5554
- if (sels.length > 0) {
5555
- const actionApi = Selective.find(sels.join(", "));
5556
- if (!actionApi.isEmpty)
5557
- actionApi.close();
5558
- }
5559
- });
5560
- Selective.Observer();
5561
- }
5562
- if (document.readyState === "loading") {
5563
- document.addEventListener("DOMContentLoaded", init);
5564
- }
5565
- else {
5566
- init();
5567
- }
5584
+ return globalThis.GLOBAL_SEUI.effector(element);
5568
5585
  }
5569
5586
 
5570
5587
  export { bind, destroy, effector, find, name, rebind, version };