@domql/utils 3.7.0 → 3.7.4

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.
@@ -31,7 +31,9 @@ function addEventFromProps(key, obj) {
31
31
  if ((0, import_types.isFunction)(origEvent)) {
32
32
  on[eventName] = (...args) => {
33
33
  const originalEventRetunrs = origEvent(...args);
34
- if (originalEventRetunrs !== false) funcFromProps(...args);
34
+ if (originalEventRetunrs !== false) {
35
+ if ((0, import_types.isFunction)(funcFromProps)) return funcFromProps(...args);
36
+ }
35
37
  };
36
38
  } else on[eventName] = funcFromProps;
37
39
  }
@@ -228,14 +228,17 @@ const deepMergeExtends = (element, extend, sourcemap, sourceName, preBuiltSource
228
228
  }
229
229
  return element;
230
230
  };
231
- const trackSourcemapDeep = (sourcemap, obj, sourceName) => {
231
+ const trackSourcemapDeep = (sourcemap, obj, sourceName, seen) => {
232
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
233
+ if (seen.has(obj)) return;
234
+ seen.add(obj);
232
235
  for (const key in obj) {
233
236
  if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
234
237
  if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
235
238
  const val = obj[key];
236
239
  if ((0, import_types.isObject)(val) && !(0, import_types.isArray)(val)) {
237
240
  sourcemap[key] = sourcemap[key] || {};
238
- trackSourcemapDeep(sourcemap[key], val, sourceName);
241
+ trackSourcemapDeep(sourcemap[key], val, sourceName, seen);
239
242
  } else {
240
243
  sourcemap[key] = sourceName;
241
244
  }
@@ -21,8 +21,11 @@ __export(function_exports, {
21
21
  cloneFunction: () => cloneFunction,
22
22
  debounce: () => debounce,
23
23
  debounceOnContext: () => debounceOnContext,
24
+ hasHandlerPlugin: () => hasHandlerPlugin,
24
25
  isStringFunction: () => isStringFunction,
25
- memoize: () => memoize
26
+ memoize: () => memoize,
27
+ resolveHandler: () => resolveHandler,
28
+ runPluginHook: () => runPluginHook
26
29
  });
27
30
  module.exports = __toCommonJS(function_exports);
28
31
  function debounce(func, wait, immediate) {
@@ -66,6 +69,35 @@ const RE_STRING_FUNCTION = /^((function\s*\([^)]*\)\s*\{[^}]*\})|(\([^)]*\)\s*=>
66
69
  const isStringFunction = (inputString) => {
67
70
  return RE_STRING_FUNCTION.test(inputString);
68
71
  };
72
+ const hasHandlerPlugin = (ctx) => {
73
+ const plugins = ctx?.plugins;
74
+ if (!plugins || !plugins.length) return false;
75
+ for (const plugin of plugins) {
76
+ if (plugin.resolveHandler) return true;
77
+ }
78
+ return false;
79
+ };
80
+ const resolveHandler = (handler, element) => {
81
+ if (typeof handler === "function") return handler;
82
+ const plugins = element?.context?.plugins;
83
+ if (!plugins) return handler;
84
+ for (const plugin of plugins) {
85
+ if (plugin.resolveHandler) {
86
+ const resolved = plugin.resolveHandler(handler, element);
87
+ if (typeof resolved === "function") return resolved;
88
+ }
89
+ }
90
+ return handler;
91
+ };
92
+ const runPluginHook = (hookName, element, ...args) => {
93
+ const plugins = element?.context?.plugins;
94
+ if (!plugins) return;
95
+ for (const plugin of plugins) {
96
+ if (typeof plugin[hookName] === "function") {
97
+ plugin[hookName](element, ...args);
98
+ }
99
+ }
100
+ };
69
101
  function cloneFunction(fn, win = window) {
70
102
  const temp = function() {
71
103
  return fn.apply(win, arguments);
@@ -372,18 +372,18 @@ function call(fnKey, ...args) {
372
372
  const result = fn.call(this, ...args);
373
373
  if (result && typeof result.then === "function") {
374
374
  result.catch((err) => {
375
- this.error = err;
375
+ error.call(this, err);
376
376
  });
377
377
  }
378
378
  return result;
379
379
  } catch (err) {
380
- this.error = err;
380
+ error.call(this, err);
381
381
  if (context?.strictMode) throw err;
382
382
  }
383
383
  }
384
384
  async function getDB() {
385
385
  const element = this;
386
- const db = element.context?.db;
386
+ const db = element.context?.fetch;
387
387
  if (!db) return null;
388
388
  if (typeof db.select === "function") {
389
389
  if (!db.__authInitialized && db.getSession) {
@@ -404,7 +404,7 @@ async function getDB() {
404
404
  db.__resolving = resolvePromise;
405
405
  const resolved = await resolvePromise;
406
406
  db.__resolved = resolved;
407
- element.context.db = resolved;
407
+ element.context.fetch = resolved;
408
408
  delete db.__resolving;
409
409
  if (resolved.getSession) {
410
410
  const { initAdapterAuth } = await import("@symbo.ls/fetch");
package/dist/cjs/props.js CHANGED
@@ -41,6 +41,7 @@ var import_events = require("./events.js");
41
41
  var import_object = require("./object.js");
42
42
  var import_types = require("./types.js");
43
43
  var import_string = require("./string.js");
44
+ var import_function = require("./function.js");
44
45
  const RE_UPPER = /^[A-Z]/;
45
46
  const RE_DIGITS = /^\d+$/;
46
47
  const CSS_SELECTOR_PREFIXES = /* @__PURE__ */ new Set([":", "@", "[", "*", "+", "~", "&", ">", "$", "-", ".", "!"]);
@@ -83,7 +84,8 @@ function pickupPropsFromElement(obj, opts = {}) {
83
84
  const cachedKeys = opts.cachedKeys || [];
84
85
  for (const key in obj) {
85
86
  const value = obj[key];
86
- const isEventHandler = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase() && (0, import_types.isFunction)(value);
87
+ const isOnKey = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase();
88
+ const isEventHandler = isOnKey && ((0, import_types.isFunction)(value) || value != null && (0, import_function.hasHandlerPlugin)(this.context));
87
89
  if (isEventHandler) {
88
90
  const eventName = (0, import_string.lowercaseFirstLetter)(key.slice(2));
89
91
  if (obj.on) obj.on[eventName] = value;
@@ -123,8 +125,8 @@ function pickupElementFromProps(obj = this, opts) {
123
125
  for (const key in obj.props) {
124
126
  const value = obj.props[key];
125
127
  const isEvent = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110;
126
- const isFn = (0, import_types.isFunction)(value);
127
- if (isEvent && isFn) {
128
+ const isHandler = (0, import_types.isFunction)(value) || value != null && (0, import_function.hasHandlerPlugin)(this.context);
129
+ if (isEvent && isHandler) {
128
130
  (0, import_events.addEventFromProps)(key, obj);
129
131
  delete obj.props[key];
130
132
  continue;
@@ -43,8 +43,8 @@ const trimStringFromSymbols = (str, characters) => {
43
43
  return str.replace(pattern, "");
44
44
  };
45
45
  const brackRegex = {
46
- 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*}}/g,
47
- 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*}}}/g
46
+ 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,
47
+ 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g
48
48
  };
49
49
  const getNestedValue = (obj, path) => {
50
50
  return path.split(".").reduce((acc, part) => {
@@ -57,7 +57,17 @@ function replaceLiteralsWithObjectFields(str, state, options = {}) {
57
57
  if (!str.includes(bracketPattern)) return str;
58
58
  const reg = brackRegex[bracketsLength];
59
59
  const obj = state || this.state || {};
60
- return str.replace(reg, (_, parentPath, variable) => {
60
+ const element = this;
61
+ return str.replace(reg, (_, parentPath, variable, filter) => {
62
+ const key = variable.trim();
63
+ if (filter) {
64
+ const filterFn = element?.context?.functions?.[filter];
65
+ if (filterFn) {
66
+ const stateValue = getNestedValue(obj, key);
67
+ return String(filterFn.call(element, stateValue !== void 0 ? stateValue : key) ?? "");
68
+ }
69
+ return "";
70
+ }
61
71
  if (parentPath) {
62
72
  const parentLevels = (parentPath.match(/\.\.\//g) || []).length;
63
73
  let parentState = obj;
@@ -65,14 +75,13 @@ function replaceLiteralsWithObjectFields(str, state, options = {}) {
65
75
  if (!parentState || !parentState.parent) return "";
66
76
  parentState = parentState.parent;
67
77
  }
68
- const key = variable.trim();
69
78
  if (key === "parent") {
70
79
  return String(parentState.value ?? "");
71
80
  }
72
81
  const value = getNestedValue(parentState, key);
73
82
  return String(value ?? "");
74
83
  } else {
75
- const value = getNestedValue(obj, variable.trim());
84
+ const value = getNestedValue(obj, key);
76
85
  return String(value ?? "");
77
86
  }
78
87
  });
@@ -25,6 +25,7 @@ __export(triggerEvent_exports, {
25
25
  });
26
26
  module.exports = __toCommonJS(triggerEvent_exports);
27
27
  var import_types = require("./types.js");
28
+ var import_function = require("./function.js");
28
29
  const getOnOrPropsEvent = (param, element) => {
29
30
  const onEvent = element.on?.[param];
30
31
  if (onEvent) return onEvent;
@@ -34,6 +35,7 @@ const getOnOrPropsEvent = (param, element) => {
34
35
  return props[propKey];
35
36
  };
36
37
  const applyEvent = (param, element, state, context, options) => {
38
+ param = (0, import_function.resolveHandler)(param, element);
37
39
  if (!(0, import_types.isFunction)(param)) return;
38
40
  try {
39
41
  const result = param.call(
@@ -60,6 +62,7 @@ const triggerEventOn = (param, element, options) => {
60
62
  if (!element) {
61
63
  throw new Error("Element is required");
62
64
  }
65
+ (0, import_function.runPluginHook)(param, element, options);
63
66
  const appliedFunction = getOnOrPropsEvent(param, element);
64
67
  if (appliedFunction) {
65
68
  const { state, context } = element;
@@ -67,6 +70,7 @@ const triggerEventOn = (param, element, options) => {
67
70
  }
68
71
  };
69
72
  const applyEventUpdate = (param, updatedObj, element, state, context, options) => {
73
+ param = (0, import_function.resolveHandler)(param, element);
70
74
  if (!(0, import_types.isFunction)(param)) return;
71
75
  try {
72
76
  const result = param.call(
@@ -91,6 +95,7 @@ const applyEventUpdate = (param, updatedObj, element, state, context, options) =
91
95
  }
92
96
  };
93
97
  const triggerEventOnUpdate = (param, updatedObj, element, options) => {
98
+ (0, import_function.runPluginHook)(param, element, updatedObj, options);
94
99
  const appliedFunction = getOnOrPropsEvent(param, element);
95
100
  if (appliedFunction) {
96
101
  const { state, context } = element;
@@ -8,7 +8,9 @@ function addEventFromProps(key, obj) {
8
8
  if (isFunction(origEvent)) {
9
9
  on[eventName] = (...args) => {
10
10
  const originalEventRetunrs = origEvent(...args);
11
- if (originalEventRetunrs !== false) funcFromProps(...args);
11
+ if (originalEventRetunrs !== false) {
12
+ if (isFunction(funcFromProps)) return funcFromProps(...args);
13
+ }
12
14
  };
13
15
  } else on[eventName] = funcFromProps;
14
16
  }
@@ -179,14 +179,17 @@ const deepMergeExtends = (element, extend, sourcemap, sourceName, preBuiltSource
179
179
  }
180
180
  return element;
181
181
  };
182
- const trackSourcemapDeep = (sourcemap, obj, sourceName) => {
182
+ const trackSourcemapDeep = (sourcemap, obj, sourceName, seen) => {
183
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
184
+ if (seen.has(obj)) return;
185
+ seen.add(obj);
183
186
  for (const key in obj) {
184
187
  if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
185
188
  if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
186
189
  const val = obj[key];
187
190
  if (isObject(val) && !isArray(val)) {
188
191
  sourcemap[key] = sourcemap[key] || {};
189
- trackSourcemapDeep(sourcemap[key], val, sourceName);
192
+ trackSourcemapDeep(sourcemap[key], val, sourceName, seen);
190
193
  } else {
191
194
  sourcemap[key] = sourceName;
192
195
  }
@@ -39,6 +39,35 @@ const RE_STRING_FUNCTION = /^((function\s*\([^)]*\)\s*\{[^}]*\})|(\([^)]*\)\s*=>
39
39
  const isStringFunction = (inputString) => {
40
40
  return RE_STRING_FUNCTION.test(inputString);
41
41
  };
42
+ const hasHandlerPlugin = (ctx) => {
43
+ const plugins = ctx?.plugins;
44
+ if (!plugins || !plugins.length) return false;
45
+ for (const plugin of plugins) {
46
+ if (plugin.resolveHandler) return true;
47
+ }
48
+ return false;
49
+ };
50
+ const resolveHandler = (handler, element) => {
51
+ if (typeof handler === "function") return handler;
52
+ const plugins = element?.context?.plugins;
53
+ if (!plugins) return handler;
54
+ for (const plugin of plugins) {
55
+ if (plugin.resolveHandler) {
56
+ const resolved = plugin.resolveHandler(handler, element);
57
+ if (typeof resolved === "function") return resolved;
58
+ }
59
+ }
60
+ return handler;
61
+ };
62
+ const runPluginHook = (hookName, element, ...args) => {
63
+ const plugins = element?.context?.plugins;
64
+ if (!plugins) return;
65
+ for (const plugin of plugins) {
66
+ if (typeof plugin[hookName] === "function") {
67
+ plugin[hookName](element, ...args);
68
+ }
69
+ }
70
+ };
42
71
  function cloneFunction(fn, win = window) {
43
72
  const temp = function() {
44
73
  return fn.apply(win, arguments);
@@ -54,6 +83,9 @@ export {
54
83
  cloneFunction,
55
84
  debounce,
56
85
  debounceOnContext,
86
+ hasHandlerPlugin,
57
87
  isStringFunction,
58
- memoize
88
+ memoize,
89
+ resolveHandler,
90
+ runPluginHook
59
91
  };
@@ -309,18 +309,18 @@ function call(fnKey, ...args) {
309
309
  const result = fn.call(this, ...args);
310
310
  if (result && typeof result.then === "function") {
311
311
  result.catch((err) => {
312
- this.error = err;
312
+ error.call(this, err);
313
313
  });
314
314
  }
315
315
  return result;
316
316
  } catch (err) {
317
- this.error = err;
317
+ error.call(this, err);
318
318
  if (context?.strictMode) throw err;
319
319
  }
320
320
  }
321
321
  async function getDB() {
322
322
  const element = this;
323
- const db = element.context?.db;
323
+ const db = element.context?.fetch;
324
324
  if (!db) return null;
325
325
  if (typeof db.select === "function") {
326
326
  if (!db.__authInitialized && db.getSession) {
@@ -341,7 +341,7 @@ async function getDB() {
341
341
  db.__resolving = resolvePromise;
342
342
  const resolved = await resolvePromise;
343
343
  db.__resolved = resolved;
344
- element.context.db = resolved;
344
+ element.context.fetch = resolved;
345
345
  delete db.__resolving;
346
346
  if (resolved.getSession) {
347
347
  const { initAdapterAuth } = await import("@symbo.ls/fetch");
package/dist/esm/props.js CHANGED
@@ -3,6 +3,7 @@ import { addEventFromProps } from "./events.js";
3
3
  import { deepClone, deepMerge, exec } from "./object.js";
4
4
  import { is, isArray, isFunction, isObject, isObjectLike } from "./types.js";
5
5
  import { lowercaseFirstLetter } from "./string.js";
6
+ import { hasHandlerPlugin } from "./function.js";
6
7
  const RE_UPPER = /^[A-Z]/;
7
8
  const RE_DIGITS = /^\d+$/;
8
9
  const CSS_SELECTOR_PREFIXES = /* @__PURE__ */ new Set([":", "@", "[", "*", "+", "~", "&", ">", "$", "-", ".", "!"]);
@@ -45,7 +46,8 @@ function pickupPropsFromElement(obj, opts = {}) {
45
46
  const cachedKeys = opts.cachedKeys || [];
46
47
  for (const key in obj) {
47
48
  const value = obj[key];
48
- const isEventHandler = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase() && isFunction(value);
49
+ const isOnKey = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase();
50
+ const isEventHandler = isOnKey && (isFunction(value) || value != null && hasHandlerPlugin(this.context));
49
51
  if (isEventHandler) {
50
52
  const eventName = lowercaseFirstLetter(key.slice(2));
51
53
  if (obj.on) obj.on[eventName] = value;
@@ -85,8 +87,8 @@ function pickupElementFromProps(obj = this, opts) {
85
87
  for (const key in obj.props) {
86
88
  const value = obj.props[key];
87
89
  const isEvent = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110;
88
- const isFn = isFunction(value);
89
- if (isEvent && isFn) {
90
+ const isHandler = isFunction(value) || value != null && hasHandlerPlugin(this.context);
91
+ if (isEvent && isHandler) {
90
92
  addEventFromProps(key, obj);
91
93
  delete obj.props[key];
92
94
  continue;
@@ -11,8 +11,8 @@ const trimStringFromSymbols = (str, characters) => {
11
11
  return str.replace(pattern, "");
12
12
  };
13
13
  const brackRegex = {
14
- 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*}}/g,
15
- 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*}}}/g
14
+ 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,
15
+ 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g
16
16
  };
17
17
  const getNestedValue = (obj, path) => {
18
18
  return path.split(".").reduce((acc, part) => {
@@ -25,7 +25,17 @@ function replaceLiteralsWithObjectFields(str, state, options = {}) {
25
25
  if (!str.includes(bracketPattern)) return str;
26
26
  const reg = brackRegex[bracketsLength];
27
27
  const obj = state || this.state || {};
28
- return str.replace(reg, (_, parentPath, variable) => {
28
+ const element = this;
29
+ return str.replace(reg, (_, parentPath, variable, filter) => {
30
+ const key = variable.trim();
31
+ if (filter) {
32
+ const filterFn = element?.context?.functions?.[filter];
33
+ if (filterFn) {
34
+ const stateValue = getNestedValue(obj, key);
35
+ return String(filterFn.call(element, stateValue !== void 0 ? stateValue : key) ?? "");
36
+ }
37
+ return "";
38
+ }
29
39
  if (parentPath) {
30
40
  const parentLevels = (parentPath.match(/\.\.\//g) || []).length;
31
41
  let parentState = obj;
@@ -33,14 +43,13 @@ function replaceLiteralsWithObjectFields(str, state, options = {}) {
33
43
  if (!parentState || !parentState.parent) return "";
34
44
  parentState = parentState.parent;
35
45
  }
36
- const key = variable.trim();
37
46
  if (key === "parent") {
38
47
  return String(parentState.value ?? "");
39
48
  }
40
49
  const value = getNestedValue(parentState, key);
41
50
  return String(value ?? "");
42
51
  } else {
43
- const value = getNestedValue(obj, variable.trim());
52
+ const value = getNestedValue(obj, key);
44
53
  return String(value ?? "");
45
54
  }
46
55
  });
@@ -1,4 +1,5 @@
1
1
  import { isFunction } from "./types.js";
2
+ import { resolveHandler, runPluginHook } from "./function.js";
2
3
  const getOnOrPropsEvent = (param, element) => {
3
4
  const onEvent = element.on?.[param];
4
5
  if (onEvent) return onEvent;
@@ -8,6 +9,7 @@ const getOnOrPropsEvent = (param, element) => {
8
9
  return props[propKey];
9
10
  };
10
11
  const applyEvent = (param, element, state, context, options) => {
12
+ param = resolveHandler(param, element);
11
13
  if (!isFunction(param)) return;
12
14
  try {
13
15
  const result = param.call(
@@ -34,6 +36,7 @@ const triggerEventOn = (param, element, options) => {
34
36
  if (!element) {
35
37
  throw new Error("Element is required");
36
38
  }
39
+ runPluginHook(param, element, options);
37
40
  const appliedFunction = getOnOrPropsEvent(param, element);
38
41
  if (appliedFunction) {
39
42
  const { state, context } = element;
@@ -41,6 +44,7 @@ const triggerEventOn = (param, element, options) => {
41
44
  }
42
45
  };
43
46
  const applyEventUpdate = (param, updatedObj, element, state, context, options) => {
47
+ param = resolveHandler(param, element);
44
48
  if (!isFunction(param)) return;
45
49
  try {
46
50
  const result = param.call(
@@ -65,6 +69,7 @@ const applyEventUpdate = (param, updatedObj, element, state, context, options) =
65
69
  }
66
70
  };
67
71
  const triggerEventOnUpdate = (param, updatedObj, element, options) => {
72
+ runPluginHook(param, element, updatedObj, options);
68
73
  const appliedFunction = getOnOrPropsEvent(param, element);
69
74
  if (appliedFunction) {
70
75
  const { state, context } = element;
@@ -743,13 +743,14 @@ var DomqlUtils = (() => {
743
743
  createAdapter: () => createAdapter,
744
744
  default: () => fetch_default,
745
745
  executeFetch: () => executeFetch,
746
+ fetchPlugin: () => fetchPlugin,
746
747
  initAdapterAuth: () => initAdapterAuth,
747
748
  parseDuration: () => parseDuration,
748
749
  queryClient: () => queryClient,
749
750
  registerAdapter: () => registerAdapter,
750
751
  resolveDb: () => resolveDb
751
752
  });
752
- var ADAPTER_METHODS, BUILTIN_ADAPTERS, registerAdapter, createAdapter, resolveDb, parseDuration, cacheStore, querySubscribers, activeQueries, buildCacheKey, getCacheEntry, setCacheEntry, invalidateCache, removeCache, parseCacheConfig, gcTimer, startGC, DEFAULT_RETRY, DEFAULT_RETRY_DELAY, resolveRetryConfig, withRetry, globalListeners, globalListenersAttached, attachGlobalListeners, resolveFetchConfig, resolveParamsSync, resolveParams, initAdapterAuth, resolveAdapter, triggerCallback, collectFormData, updateElementState, setFetchStatus, runFetch, bindEvent, bindAutoRefetch, applyOptimisticUpdate, rollbackOptimistic, runMutation, executeFetch, queryClient, fetch_default;
753
+ var ADAPTER_METHODS, BUILTIN_ADAPTERS, registerAdapter, createAdapter, resolveDb, parseDuration, cacheStore, querySubscribers, activeQueries, buildCacheKey, getCacheEntry, setCacheEntry, invalidateCache, removeCache, parseCacheConfig, gcTimer, startGC, DEFAULT_RETRY, DEFAULT_RETRY_DELAY, resolveRetryConfig, withRetry, globalListeners, globalListenersAttached, attachGlobalListeners, resolveFetchConfig, resolveParamsSync, resolveLanguage, resolveParams, initAdapterAuth, resolveAdapter, triggerCallback, collectFormData, updateElementState, setFetchStatus, runFetch, bindEvent, bindAutoRefetch, applyOptimisticUpdate, rollbackOptimistic, runMutation, executeFetch, queryClient, fetchPlugin, fetch_default;
753
754
  var init_fetch = __esm({
754
755
  "../../plugins/fetch/index.js"() {
755
756
  "use strict";
@@ -945,13 +946,23 @@ var DomqlUtils = (() => {
945
946
  if (!params || isFunction2(params)) return params;
946
947
  return params;
947
948
  };
948
- resolveParams = (params, element) => {
949
- if (!params) return void 0;
950
- if (isFunction2(params)) return params(element, element.state);
951
- const resolved = {};
952
- for (const key in params) {
953
- const val = params[key];
954
- resolved[key] = isFunction2(val) ? val(element, element.state) : val;
949
+ resolveLanguage = (element, context) => {
950
+ const root = element?.state?.root || context?.state?.root;
951
+ if (root?.lang) return root.lang;
952
+ return void 0;
953
+ };
954
+ resolveParams = (params, element, context) => {
955
+ let resolved;
956
+ if (!params) {
957
+ resolved = void 0;
958
+ } else if (isFunction2(params)) {
959
+ resolved = params(element, element.state);
960
+ } else {
961
+ resolved = {};
962
+ for (const key in params) {
963
+ const val = params[key];
964
+ resolved[key] = isFunction2(val) ? val(element, element.state) : val;
965
+ }
955
966
  }
956
967
  return resolved;
957
968
  };
@@ -989,7 +1000,7 @@ var DomqlUtils = (() => {
989
1000
  db.__resolving = resolveDb(db);
990
1001
  const resolved = await db.__resolving;
991
1002
  db.__resolved = resolved;
992
- context.db = resolved;
1003
+ context.fetch = resolved;
993
1004
  delete db.__resolving;
994
1005
  if (db.auth !== false) await initAdapterAuth(resolved, context);
995
1006
  return resolved;
@@ -1037,7 +1048,7 @@ var DomqlUtils = (() => {
1037
1048
  ref.__fetchError = status.error;
1038
1049
  };
1039
1050
  runFetch = async (config, element, context, opts = {}) => {
1040
- const db = context?.db;
1051
+ const db = context?.fetch;
1041
1052
  if (!db) return;
1042
1053
  if (config.enabled === false) return;
1043
1054
  if (isFunction2(config.enabled) && !config.enabled(element, element.state)) return;
@@ -1077,7 +1088,7 @@ var DomqlUtils = (() => {
1077
1088
  const q = element.getQuery(adapter.name || "paths");
1078
1089
  if (q) select = q.select || q.length && q.join(",") || void 0;
1079
1090
  }
1080
- const params = resolveParams(rawParams, element);
1091
+ const params = resolveParams(rawParams, element, context);
1081
1092
  const cacheConfig = parseCacheConfig(cacheRaw);
1082
1093
  const retryConfig = resolveRetryConfig(config);
1083
1094
  const cacheKey = cacheConfig ? cacheRaw?.key || `${from}:${method}:${JSON.stringify(params || "")}${infinite ? ":infinite" : ""}${page ? ":p" + JSON.stringify(page) : ""}` : null;
@@ -1147,6 +1158,10 @@ var DomqlUtils = (() => {
1147
1158
  const fn = adapter[method];
1148
1159
  if (!isFunction2(fn)) return { data: null, error: { message: `Method "${method}" not found on adapter` } };
1149
1160
  const request2 = { from, select, params, single, limit, offset, order, headers, baseUrl };
1161
+ const lang = resolveLanguage(element, context);
1162
+ if (lang) {
1163
+ request2.headers = { ...request2.headers, "Accept-Language": lang };
1164
+ }
1150
1165
  if (page !== void 0) {
1151
1166
  if (isObject2(page)) {
1152
1167
  if (page.offset !== void 0) request2.offset = page.offset;
@@ -1329,7 +1344,7 @@ var DomqlUtils = (() => {
1329
1344
  }
1330
1345
  };
1331
1346
  runMutation = async (config, element, context) => {
1332
- const db = context?.db;
1347
+ const db = context?.fetch;
1333
1348
  if (!db) return;
1334
1349
  const adapter = await resolveAdapter(db, context);
1335
1350
  if (!adapter) return;
@@ -1366,7 +1381,11 @@ var DomqlUtils = (() => {
1366
1381
  const fn = adapter[method];
1367
1382
  if (!isFunction2(fn)) return;
1368
1383
  const request2 = { from, data: mutationData, headers, baseUrl };
1369
- if (config.params) request2.params = resolveParams(config.params, element);
1384
+ if (config.params) request2.params = resolveParams(config.params, element, context);
1385
+ const lang = resolveLanguage(element, context);
1386
+ if (lang) {
1387
+ request2.headers = { ...request2.headers, "Accept-Language": lang };
1388
+ }
1370
1389
  const retryConfig = resolveRetryConfig(config);
1371
1390
  const result = await withRetry(() => fn(request2), retryConfig);
1372
1391
  const { data, error: error2 } = result || {};
@@ -1411,7 +1430,7 @@ var DomqlUtils = (() => {
1411
1430
  };
1412
1431
  executeFetch = (param, element, state, context) => {
1413
1432
  if (!param) return;
1414
- const db = context?.db;
1433
+ const db = context?.fetch;
1415
1434
  if (!db) return;
1416
1435
  const fetchProp = exec2(param, element);
1417
1436
  if (!fetchProp) return;
@@ -1497,7 +1516,7 @@ var DomqlUtils = (() => {
1497
1516
  setCacheEntry(key, data, null);
1498
1517
  },
1499
1518
  prefetchQuery: async (config, context) => {
1500
- const db = context?.db;
1519
+ const db = context?.fetch;
1501
1520
  if (!db) return;
1502
1521
  const adapter = await resolveAdapter(db, context);
1503
1522
  if (!adapter) return;
@@ -1521,6 +1540,15 @@ var DomqlUtils = (() => {
1521
1540
  getCache: () => cacheStore,
1522
1541
  clear: () => removeCache()
1523
1542
  };
1543
+ fetchPlugin = {
1544
+ name: "fetch",
1545
+ // Hook into element creation to auto-execute fetch configs
1546
+ create(element) {
1547
+ const fetchProp = element.fetch || element.props?.fetch;
1548
+ if (!fetchProp) return;
1549
+ executeFetch(fetchProp, element, element.state, element.context);
1550
+ }
1551
+ };
1524
1552
  fetch_default = executeFetch;
1525
1553
  }
1526
1554
  });
@@ -1644,6 +1672,7 @@ var DomqlUtils = (() => {
1644
1672
  getSpreadChildren: () => getSpreadChildren,
1645
1673
  global: () => global,
1646
1674
  hasFunction: () => hasFunction,
1675
+ hasHandlerPlugin: () => hasHandlerPlugin,
1647
1676
  hasOwnProperty: () => hasOwnProperty,
1648
1677
  inheritChildExtends: () => inheritChildExtends,
1649
1678
  inheritChildPropsExtends: () => inheritChildPropsExtends,
@@ -1726,7 +1755,9 @@ var DomqlUtils = (() => {
1726
1755
  reorderArrayByValues: () => reorderArrayByValues,
1727
1756
  replaceLiteralsWithObjectFields: () => replaceLiteralsWithObjectFields,
1728
1757
  replaceOctalEscapeSequences: () => replaceOctalEscapeSequences,
1758
+ resolveHandler: () => resolveHandler,
1729
1759
  returnValueAsText: () => returnValueAsText,
1760
+ runPluginHook: () => runPluginHook,
1730
1761
  self: () => self,
1731
1762
  setCookie: () => setCookie,
1732
1763
  setHashedExtend: () => setHashedExtend,
@@ -1950,8 +1981,8 @@ var DomqlUtils = (() => {
1950
1981
  return str.replace(pattern, "");
1951
1982
  };
1952
1983
  var brackRegex = {
1953
- 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*}}/g,
1954
- 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*}}}/g
1984
+ 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,
1985
+ 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g
1955
1986
  };
1956
1987
  var getNestedValue = (obj, path) => {
1957
1988
  return path.split(".").reduce((acc, part) => {
@@ -1964,7 +1995,17 @@ var DomqlUtils = (() => {
1964
1995
  if (!str.includes(bracketPattern)) return str;
1965
1996
  const reg = brackRegex[bracketsLength];
1966
1997
  const obj = state || this.state || {};
1967
- return str.replace(reg, (_, parentPath, variable) => {
1998
+ const element = this;
1999
+ return str.replace(reg, (_, parentPath, variable, filter) => {
2000
+ const key = variable.trim();
2001
+ if (filter) {
2002
+ const filterFn = element?.context?.functions?.[filter];
2003
+ if (filterFn) {
2004
+ const stateValue = getNestedValue(obj, key);
2005
+ return String(filterFn.call(element, stateValue !== void 0 ? stateValue : key) ?? "");
2006
+ }
2007
+ return "";
2008
+ }
1968
2009
  if (parentPath) {
1969
2010
  const parentLevels = (parentPath.match(/\.\.\//g) || []).length;
1970
2011
  let parentState = obj;
@@ -1972,14 +2013,13 @@ var DomqlUtils = (() => {
1972
2013
  if (!parentState || !parentState.parent) return "";
1973
2014
  parentState = parentState.parent;
1974
2015
  }
1975
- const key = variable.trim();
1976
2016
  if (key === "parent") {
1977
2017
  return String(parentState.value ?? "");
1978
2018
  }
1979
2019
  const value = getNestedValue(parentState, key);
1980
2020
  return String(value ?? "");
1981
2021
  } else {
1982
- const value = getNestedValue(obj, variable.trim());
2022
+ const value = getNestedValue(obj, key);
1983
2023
  return String(value ?? "");
1984
2024
  }
1985
2025
  });
@@ -2822,6 +2862,35 @@ var DomqlUtils = (() => {
2822
2862
  var isStringFunction = (inputString) => {
2823
2863
  return RE_STRING_FUNCTION.test(inputString);
2824
2864
  };
2865
+ var hasHandlerPlugin = (ctx) => {
2866
+ const plugins = ctx?.plugins;
2867
+ if (!plugins || !plugins.length) return false;
2868
+ for (const plugin of plugins) {
2869
+ if (plugin.resolveHandler) return true;
2870
+ }
2871
+ return false;
2872
+ };
2873
+ var resolveHandler = (handler, element) => {
2874
+ if (typeof handler === "function") return handler;
2875
+ const plugins = element?.context?.plugins;
2876
+ if (!plugins) return handler;
2877
+ for (const plugin of plugins) {
2878
+ if (plugin.resolveHandler) {
2879
+ const resolved = plugin.resolveHandler(handler, element);
2880
+ if (typeof resolved === "function") return resolved;
2881
+ }
2882
+ }
2883
+ return handler;
2884
+ };
2885
+ var runPluginHook = (hookName, element, ...args) => {
2886
+ const plugins = element?.context?.plugins;
2887
+ if (!plugins) return;
2888
+ for (const plugin of plugins) {
2889
+ if (typeof plugin[hookName] === "function") {
2890
+ plugin[hookName](element, ...args);
2891
+ }
2892
+ }
2893
+ };
2825
2894
  function cloneFunction(fn, win = window) {
2826
2895
  const temp = function() {
2827
2896
  return fn.apply(win, arguments);
@@ -3276,14 +3345,17 @@ var DomqlUtils = (() => {
3276
3345
  }
3277
3346
  return element;
3278
3347
  };
3279
- var trackSourcemapDeep = (sourcemap, obj, sourceName) => {
3348
+ var trackSourcemapDeep = (sourcemap, obj, sourceName, seen) => {
3349
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
3350
+ if (seen.has(obj)) return;
3351
+ seen.add(obj);
3280
3352
  for (const key in obj) {
3281
3353
  if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
3282
3354
  if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
3283
3355
  const val = obj[key];
3284
3356
  if (isObject(val) && !isArray(val)) {
3285
3357
  sourcemap[key] = sourcemap[key] || {};
3286
- trackSourcemapDeep(sourcemap[key], val, sourceName);
3358
+ trackSourcemapDeep(sourcemap[key], val, sourceName, seen);
3287
3359
  } else {
3288
3360
  sourcemap[key] = sourceName;
3289
3361
  }
@@ -3510,7 +3582,9 @@ var DomqlUtils = (() => {
3510
3582
  if (isFunction(origEvent)) {
3511
3583
  on[eventName] = (...args) => {
3512
3584
  const originalEventRetunrs = origEvent(...args);
3513
- if (originalEventRetunrs !== false) funcFromProps(...args);
3585
+ if (originalEventRetunrs !== false) {
3586
+ if (isFunction(funcFromProps)) return funcFromProps(...args);
3587
+ }
3514
3588
  };
3515
3589
  } else on[eventName] = funcFromProps;
3516
3590
  }
@@ -3558,7 +3632,8 @@ var DomqlUtils = (() => {
3558
3632
  const cachedKeys = opts.cachedKeys || [];
3559
3633
  for (const key in obj) {
3560
3634
  const value = obj[key];
3561
- const isEventHandler = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase() && isFunction(value);
3635
+ const isOnKey = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase();
3636
+ const isEventHandler = isOnKey && (isFunction(value) || value != null && hasHandlerPlugin(this.context));
3562
3637
  if (isEventHandler) {
3563
3638
  const eventName = lowercaseFirstLetter(key.slice(2));
3564
3639
  if (obj.on) obj.on[eventName] = value;
@@ -3598,8 +3673,8 @@ var DomqlUtils = (() => {
3598
3673
  for (const key in obj.props) {
3599
3674
  const value = obj.props[key];
3600
3675
  const isEvent = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110;
3601
- const isFn = isFunction(value);
3602
- if (isEvent && isFn) {
3676
+ const isHandler = isFunction(value) || value != null && hasHandlerPlugin(this.context);
3677
+ if (isEvent && isHandler) {
3603
3678
  addEventFromProps(key, obj);
3604
3679
  delete obj.props[key];
3605
3680
  continue;
@@ -4009,6 +4084,7 @@ var DomqlUtils = (() => {
4009
4084
  return props[propKey];
4010
4085
  };
4011
4086
  var applyEvent = (param, element, state, context, options) => {
4087
+ param = resolveHandler(param, element);
4012
4088
  if (!isFunction(param)) return;
4013
4089
  try {
4014
4090
  const result = param.call(
@@ -4035,6 +4111,7 @@ var DomqlUtils = (() => {
4035
4111
  if (!element) {
4036
4112
  throw new Error("Element is required");
4037
4113
  }
4114
+ runPluginHook(param, element, options);
4038
4115
  const appliedFunction = getOnOrPropsEvent(param, element);
4039
4116
  if (appliedFunction) {
4040
4117
  const { state, context } = element;
@@ -4042,6 +4119,7 @@ var DomqlUtils = (() => {
4042
4119
  }
4043
4120
  };
4044
4121
  var applyEventUpdate = (param, updatedObj, element, state, context, options) => {
4122
+ param = resolveHandler(param, element);
4045
4123
  if (!isFunction(param)) return;
4046
4124
  try {
4047
4125
  const result = param.call(
@@ -4066,6 +4144,7 @@ var DomqlUtils = (() => {
4066
4144
  }
4067
4145
  };
4068
4146
  var triggerEventOnUpdate = (param, updatedObj, element, options) => {
4147
+ runPluginHook(param, element, updatedObj, options);
4069
4148
  const appliedFunction = getOnOrPropsEvent(param, element);
4070
4149
  if (appliedFunction) {
4071
4150
  const { state, context } = element;
@@ -4389,18 +4468,18 @@ var DomqlUtils = (() => {
4389
4468
  const result = fn.call(this, ...args);
4390
4469
  if (result && typeof result.then === "function") {
4391
4470
  result.catch((err) => {
4392
- this.error = err;
4471
+ error.call(this, err);
4393
4472
  });
4394
4473
  }
4395
4474
  return result;
4396
4475
  } catch (err) {
4397
- this.error = err;
4476
+ error.call(this, err);
4398
4477
  if (context?.strictMode) throw err;
4399
4478
  }
4400
4479
  }
4401
4480
  async function getDB() {
4402
4481
  const element = this;
4403
- const db = element.context?.db;
4482
+ const db = element.context?.fetch;
4404
4483
  if (!db) return null;
4405
4484
  if (typeof db.select === "function") {
4406
4485
  if (!db.__authInitialized && db.getSession) {
@@ -4421,7 +4500,7 @@ var DomqlUtils = (() => {
4421
4500
  db.__resolving = resolvePromise;
4422
4501
  const resolved = await resolvePromise;
4423
4502
  db.__resolved = resolved;
4424
- element.context.db = resolved;
4503
+ element.context.fetch = resolved;
4425
4504
  delete db.__resolving;
4426
4505
  if (resolved.getSession) {
4427
4506
  const { initAdapterAuth: initAdapterAuth2 } = await Promise.resolve().then(() => (init_fetch(), fetch_exports));
package/events.js CHANGED
@@ -11,7 +11,9 @@ export function addEventFromProps (key, obj) {
11
11
  if (isFunction(origEvent)) {
12
12
  on[eventName] = (...args) => {
13
13
  const originalEventRetunrs = origEvent(...args)
14
- if (originalEventRetunrs !== false) funcFromProps(...args)
14
+ if (originalEventRetunrs !== false) {
15
+ if (isFunction(funcFromProps)) return funcFromProps(...args)
16
+ }
15
17
  }
16
18
  } else on[eventName] = funcFromProps
17
19
  }
package/extends.js CHANGED
@@ -252,14 +252,17 @@ export const deepMergeExtends = (element, extend, sourcemap, sourceName, preBuil
252
252
  return element
253
253
  }
254
254
 
255
- const trackSourcemapDeep = (sourcemap, obj, sourceName) => {
255
+ const trackSourcemapDeep = (sourcemap, obj, sourceName, seen) => {
256
+ if (!seen) seen = new WeakSet()
257
+ if (seen.has(obj)) return
258
+ seen.add(obj)
256
259
  for (const key in obj) {
257
260
  if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
258
261
  if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
259
262
  const val = obj[key]
260
263
  if (isObject(val) && !isArray(val)) {
261
264
  sourcemap[key] = sourcemap[key] || {}
262
- trackSourcemapDeep(sourcemap[key], val, sourceName)
265
+ trackSourcemapDeep(sourcemap[key], val, sourceName, seen)
263
266
  } else {
264
267
  sourcemap[key] = sourceName
265
268
  }
package/function.js CHANGED
@@ -73,6 +73,60 @@ export const isStringFunction = inputString => {
73
73
  return RE_STRING_FUNCTION.test(inputString)
74
74
  }
75
75
 
76
+ /**
77
+ * Resolve an event handler through context plugins.
78
+ *
79
+ * If `handler` is already a function it is returned as-is.
80
+ * Otherwise, iterates `context.plugins` looking for a plugin
81
+ * with a `resolveHandler` method that can compile the handler
82
+ * (e.g. a funcql schema) into a callable function.
83
+ *
84
+ * @param {*} handler - event handler (function, object, array, string)
85
+ * @param {object} element - domql element
86
+ * @returns {function|*} resolved handler
87
+ */
88
+ /**
89
+ * Check if context has any plugin that can resolve non-function handlers.
90
+ */
91
+ export const hasHandlerPlugin = (ctx) => {
92
+ const plugins = ctx?.plugins
93
+ if (!plugins || !plugins.length) return false
94
+ for (const plugin of plugins) {
95
+ if (plugin.resolveHandler) return true
96
+ }
97
+ return false
98
+ }
99
+
100
+ export const resolveHandler = (handler, element) => {
101
+ if (typeof handler === 'function') return handler
102
+ const plugins = element?.context?.plugins
103
+ if (!plugins) return handler
104
+ for (const plugin of plugins) {
105
+ if (plugin.resolveHandler) {
106
+ const resolved = plugin.resolveHandler(handler, element)
107
+ if (typeof resolved === 'function') return resolved
108
+ }
109
+ }
110
+ return handler
111
+ }
112
+
113
+ /**
114
+ * Run a named hook across all context plugins.
115
+ *
116
+ * @param {string} hookName - lifecycle hook name
117
+ * @param {object} element - domql element
118
+ * @param {*[]} args - additional arguments forwarded to each plugin hook
119
+ */
120
+ export const runPluginHook = (hookName, element, ...args) => {
121
+ const plugins = element?.context?.plugins
122
+ if (!plugins) return
123
+ for (const plugin of plugins) {
124
+ if (typeof plugin[hookName] === 'function') {
125
+ plugin[hookName](element, ...args)
126
+ }
127
+ }
128
+ }
129
+
76
130
  export function cloneFunction (fn, win = window) {
77
131
  const temp = function () {
78
132
  return fn.apply(win, arguments)
package/methods.js CHANGED
@@ -389,19 +389,19 @@ export function call (fnKey, ...args) {
389
389
  const result = fn.call(this, ...args)
390
390
  if (result && typeof result.then === 'function') {
391
391
  result.catch((err) => {
392
- this.error = err
392
+ error.call(this, err)
393
393
  })
394
394
  }
395
395
  return result
396
396
  } catch (err) {
397
- this.error = err
397
+ error.call(this, err)
398
398
  if (context?.strictMode) throw err
399
399
  }
400
400
  }
401
401
 
402
402
  export async function getDB () {
403
403
  const element = this
404
- const db = element.context?.db
404
+ const db = element.context?.fetch
405
405
  if (!db) return null
406
406
  if (typeof db.select === 'function') {
407
407
  if (!db.__authInitialized && db.getSession) {
@@ -424,7 +424,7 @@ export async function getDB () {
424
424
  db.__resolving = resolvePromise
425
425
  const resolved = await resolvePromise
426
426
  db.__resolved = resolved
427
- element.context.db = resolved
427
+ element.context.fetch = resolved
428
428
  delete db.__resolving
429
429
  if (resolved.getSession) {
430
430
  const { initAdapterAuth } = await import('@symbo.ls/fetch')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domql/utils",
3
- "version": "3.7.0",
3
+ "version": "3.7.4",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.js",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681",
40
40
  "peerDependencies": {
41
- "@symbo.ls/fetch": "^3.7.0"
41
+ "@symbo.ls/fetch": "^3.7.4"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "@symbo.ls/fetch": {
package/props.js CHANGED
@@ -5,6 +5,7 @@ import { addEventFromProps } from './events.js'
5
5
  import { deepClone, deepMerge, exec } from './object.js'
6
6
  import { is, isArray, isFunction, isObject, isObjectLike } from './types.js'
7
7
  import { lowercaseFirstLetter } from './string.js'
8
+ import { hasHandlerPlugin } from './function.js'
8
9
 
9
10
  const RE_UPPER = /^[A-Z]/
10
11
  const RE_DIGITS = /^\d+$/
@@ -46,7 +47,8 @@ export function pickupPropsFromElement (obj, opts = {}) {
46
47
  const value = obj[key]
47
48
 
48
49
  // Move top-level onXxx handlers directly into on.xxx (v3 style)
49
- const isEventHandler = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase() && isFunction(value)
50
+ const isOnKey = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase()
51
+ const isEventHandler = isOnKey && (isFunction(value) || (value != null && hasHandlerPlugin(this.context)))
50
52
  if (isEventHandler) {
51
53
  const eventName = lowercaseFirstLetter(key.slice(2))
52
54
  if (obj.on) obj.on[eventName] = value
@@ -101,11 +103,11 @@ export function pickupElementFromProps (obj = this, opts) {
101
103
  for (const key in obj.props) {
102
104
  const value = obj.props[key]
103
105
 
104
- // Handle event handlers
106
+ // Handle event handlers (functions, or plugin schemas when plugins are active)
105
107
  const isEvent = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110
106
- const isFn = isFunction(value)
108
+ const isHandler = isFunction(value) || (value != null && hasHandlerPlugin(this.context))
107
109
 
108
- if (isEvent && isFn) {
110
+ if (isEvent && isHandler) {
109
111
  addEventFromProps(key, obj)
110
112
  delete obj.props[key]
111
113
  continue
package/string.js CHANGED
@@ -25,8 +25,8 @@ export const trimStringFromSymbols = (str, characters) => {
25
25
  * @returns {string} The modified string with placeholders replaced by values from the object.
26
26
  */
27
27
  const brackRegex = {
28
- 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*}}/g,
29
- 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*}}}/g
28
+ 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,
29
+ 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g
30
30
  }
31
31
 
32
32
  const getNestedValue = (obj, path) => {
@@ -43,7 +43,22 @@ export function replaceLiteralsWithObjectFields (str, state, options = {}) {
43
43
  const reg = brackRegex[bracketsLength]
44
44
  const obj = state || this.state || {}
45
45
 
46
- return str.replace(reg, (_, parentPath, variable) => {
46
+ const element = this
47
+
48
+ return str.replace(reg, (_, parentPath, variable, filter) => {
49
+ const key = variable.trim()
50
+
51
+ // Pipe filter: {{ key | filterName }}
52
+ // Resolves key from state first, passes value (or raw key) to filter
53
+ if (filter) {
54
+ const filterFn = element?.context?.functions?.[filter]
55
+ if (filterFn) {
56
+ const stateValue = getNestedValue(obj, key)
57
+ return String(filterFn.call(element, stateValue !== undefined ? stateValue : key) ?? '')
58
+ }
59
+ return ''
60
+ }
61
+
47
62
  if (parentPath) {
48
63
  const parentLevels = (parentPath.match(/\.\.\//g) || []).length
49
64
  let parentState = obj
@@ -54,7 +69,6 @@ export function replaceLiteralsWithObjectFields (str, state, options = {}) {
54
69
  }
55
70
 
56
71
  // If the variable is 'parent', return the value property
57
- const key = variable.trim()
58
72
  if (key === 'parent') {
59
73
  return String(parentState.value ?? '')
60
74
  }
@@ -62,7 +76,7 @@ export function replaceLiteralsWithObjectFields (str, state, options = {}) {
62
76
  const value = getNestedValue(parentState, key)
63
77
  return String(value ?? '')
64
78
  } else {
65
- const value = getNestedValue(obj, variable.trim())
79
+ const value = getNestedValue(obj, key)
66
80
  return String(value ?? '')
67
81
  }
68
82
  })
package/triggerEvent.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  import { isFunction } from './types.js'
4
+ import { resolveHandler, runPluginHook } from './function.js'
4
5
 
5
6
  const getOnOrPropsEvent = (param, element) => {
6
7
  const onEvent = element.on?.[param]
@@ -12,6 +13,7 @@ const getOnOrPropsEvent = (param, element) => {
12
13
  }
13
14
 
14
15
  export const applyEvent = (param, element, state, context, options) => {
16
+ param = resolveHandler(param, element)
15
17
  if (!isFunction(param)) return
16
18
  try {
17
19
  const result = param.call(
@@ -39,6 +41,7 @@ export const triggerEventOn = (param, element, options) => {
39
41
  if (!element) {
40
42
  throw new Error('Element is required')
41
43
  }
44
+ runPluginHook(param, element, options)
42
45
  const appliedFunction = getOnOrPropsEvent(param, element)
43
46
  if (appliedFunction) {
44
47
  const { state, context } = element
@@ -54,6 +57,7 @@ export const applyEventUpdate = (
54
57
  context,
55
58
  options
56
59
  ) => {
60
+ param = resolveHandler(param, element)
57
61
  if (!isFunction(param)) return
58
62
  try {
59
63
  const result = param.call(
@@ -79,6 +83,7 @@ export const applyEventUpdate = (
79
83
  }
80
84
 
81
85
  export const triggerEventOnUpdate = (param, updatedObj, element, options) => {
86
+ runPluginHook(param, element, updatedObj, options)
82
87
  const appliedFunction = getOnOrPropsEvent(param, element)
83
88
  if (appliedFunction) {
84
89
  const { state, context } = element