snice 2.1.2 → 2.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.
- package/components/table/snice-table.ts +2 -2
- package/dist/index.cjs +64 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.cjs.min.map +1 -1
- package/dist/index.esm.js +64 -95
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +3 -3
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.iife.js +64 -95
- package/dist/index.iife.js.map +1 -1
- package/dist/index.iife.min.js +3 -3
- package/dist/index.iife.min.js.map +1 -1
- package/dist/symbols.cjs.map +1 -1
- package/dist/symbols.esm.js +4 -2
- package/dist/symbols.esm.js.map +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/symbols.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { element, on, property, query, request, dispatch, watch } from 'snice';
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
2
|
+
import '../input/snice-input';
|
|
3
|
+
import '../select/snice-select';
|
|
4
4
|
import './snice-cell.ts';
|
|
5
5
|
import './snice-cell-text.ts';
|
|
6
6
|
import './snice-cell-number.ts';
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v2.1.
|
|
2
|
+
* snice v2.1.2
|
|
3
3
|
* Imperative TypeScript framework for building vanilla web components with decorators, routing, and controllers. No virtual DOM, no build complexity.
|
|
4
4
|
* (c) 2024
|
|
5
5
|
* Released under the MIT License.
|
|
@@ -69,6 +69,8 @@ const OBSERVERS = getSymbol('observers');
|
|
|
69
69
|
// Part symbols
|
|
70
70
|
const PARTS = getSymbol('parts');
|
|
71
71
|
const PART_TIMERS = getSymbol('part-timers');
|
|
72
|
+
// Dispatch timing symbols
|
|
73
|
+
const DISPATCH_TIMERS = getSymbol('dispatch-timers');
|
|
72
74
|
|
|
73
75
|
function on(eventName, selectorOrOptions, options) {
|
|
74
76
|
// Handle overloaded parameters
|
|
@@ -297,12 +299,21 @@ function cleanupEventHandlers(instance) {
|
|
|
297
299
|
*/
|
|
298
300
|
function dispatch(eventName, options) {
|
|
299
301
|
return function (originalMethod, _context) {
|
|
300
|
-
// Create timing wrappers for dispatch
|
|
301
|
-
let debounceTimeout;
|
|
302
|
-
let throttleLastCall = 0;
|
|
303
|
-
let throttleTimeout;
|
|
304
302
|
return function (...args) {
|
|
305
|
-
//
|
|
303
|
+
// Create timing wrappers for dispatch (per-instance)
|
|
304
|
+
if (!this[DISPATCH_TIMERS]) {
|
|
305
|
+
this[DISPATCH_TIMERS] = new Map();
|
|
306
|
+
}
|
|
307
|
+
const timerKey = `${eventName}_${_context.name}`;
|
|
308
|
+
if (!this[DISPATCH_TIMERS].has(timerKey)) {
|
|
309
|
+
this[DISPATCH_TIMERS].set(timerKey, {
|
|
310
|
+
debounceTimeout: null,
|
|
311
|
+
throttleLastCall: 0,
|
|
312
|
+
throttleTimeout: null
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
const timers = this[DISPATCH_TIMERS].get(timerKey);
|
|
316
|
+
// Call the original method with preserved this context
|
|
306
317
|
const result = originalMethod.apply(this, args);
|
|
307
318
|
// Helper to dispatch the event
|
|
308
319
|
const doDispatch = (detail) => {
|
|
@@ -322,21 +333,21 @@ function dispatch(eventName, options) {
|
|
|
322
333
|
// Helper to handle timed dispatch
|
|
323
334
|
const timedDispatch = (detail) => {
|
|
324
335
|
if (options?.debounce) {
|
|
325
|
-
clearTimeout(debounceTimeout);
|
|
326
|
-
debounceTimeout = setTimeout(() => doDispatch(detail), options.debounce);
|
|
336
|
+
clearTimeout(timers.debounceTimeout);
|
|
337
|
+
timers.debounceTimeout = setTimeout(() => doDispatch(detail), options.debounce);
|
|
327
338
|
}
|
|
328
339
|
else if (options?.throttle) {
|
|
329
340
|
const now = Date.now();
|
|
330
|
-
const remaining = options.throttle - (now - throttleLastCall);
|
|
341
|
+
const remaining = options.throttle - (now - timers.throttleLastCall);
|
|
331
342
|
if (remaining <= 0) {
|
|
332
|
-
clearTimeout(throttleTimeout);
|
|
333
|
-
throttleLastCall = now;
|
|
343
|
+
clearTimeout(timers.throttleTimeout);
|
|
344
|
+
timers.throttleLastCall = now;
|
|
334
345
|
doDispatch(detail);
|
|
335
346
|
}
|
|
336
|
-
else if (!throttleTimeout) {
|
|
337
|
-
throttleTimeout = setTimeout(() => {
|
|
338
|
-
throttleLastCall = Date.now();
|
|
339
|
-
throttleTimeout = null;
|
|
347
|
+
else if (!timers.throttleTimeout) {
|
|
348
|
+
timers.throttleTimeout = setTimeout(() => {
|
|
349
|
+
timers.throttleLastCall = Date.now();
|
|
350
|
+
timers.throttleTimeout = null;
|
|
340
351
|
doDispatch(detail);
|
|
341
352
|
}, remaining);
|
|
342
353
|
}
|
|
@@ -1428,6 +1439,7 @@ function applyElementFunctionality(constructor) {
|
|
|
1428
1439
|
try {
|
|
1429
1440
|
const partElement = this.shadowRoot.querySelector(`[part="${partName}"]`);
|
|
1430
1441
|
if (partElement) {
|
|
1442
|
+
// For initial render, call original method directly to avoid timing restrictions
|
|
1431
1443
|
const partResult = partHandler.method.call(this);
|
|
1432
1444
|
const partContent = partResult instanceof Promise ? await partResult : partResult;
|
|
1433
1445
|
if (partContent !== undefined) {
|
|
@@ -2031,94 +2043,51 @@ function part(partName, options = {}) {
|
|
|
2031
2043
|
});
|
|
2032
2044
|
}
|
|
2033
2045
|
const timers = this[PART_TIMERS].get(partName);
|
|
2034
|
-
//
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
const
|
|
2040
|
-
if (
|
|
2041
|
-
|
|
2046
|
+
// Helper function to execute method and update DOM
|
|
2047
|
+
const executeAndUpdate = (...methodArgs) => {
|
|
2048
|
+
const result = originalMethod.apply(this, methodArgs);
|
|
2049
|
+
const updateDOM = (content) => {
|
|
2050
|
+
const hasContent = content !== undefined;
|
|
2051
|
+
const hasElement = this.shadowRoot?.querySelector(`[part="${partName}"]`);
|
|
2052
|
+
if (hasContent && hasElement) {
|
|
2053
|
+
hasElement.innerHTML = content;
|
|
2042
2054
|
}
|
|
2043
|
-
}
|
|
2055
|
+
};
|
|
2056
|
+
const isPromise = result instanceof Promise;
|
|
2057
|
+
return isPromise
|
|
2058
|
+
? result.then(content => { updateDOM(content); return content; })
|
|
2059
|
+
: (updateDOM(result), result);
|
|
2044
2060
|
};
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
timers.debounceTimer = setTimeout(async () => {
|
|
2054
|
-
const content = await result;
|
|
2055
|
-
updateDOM(content);
|
|
2056
|
-
}, options.debounce);
|
|
2057
|
-
return result;
|
|
2061
|
+
const hasDebounce = options.debounce !== undefined && options.debounce > 0;
|
|
2062
|
+
const hasThrottle = options.throttle !== undefined && options.throttle > 0;
|
|
2063
|
+
// Handle timing based on priority: debounce > throttle > immediate
|
|
2064
|
+
switch (true) {
|
|
2065
|
+
case hasDebounce: {
|
|
2066
|
+
clearTimeout(timers.debounceTimer);
|
|
2067
|
+
timers.debounceTimer = setTimeout(() => executeAndUpdate(...args), options.debounce);
|
|
2068
|
+
return undefined;
|
|
2058
2069
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2070
|
+
case hasThrottle: {
|
|
2071
|
+
const throttleMs = options.throttle;
|
|
2061
2072
|
const now = Date.now();
|
|
2062
|
-
|
|
2073
|
+
const canExecuteImmediately = timers.lastThrottleCall === 0 || now - timers.lastThrottleCall >= throttleMs;
|
|
2074
|
+
if (canExecuteImmediately) {
|
|
2063
2075
|
timers.lastThrottleCall = now;
|
|
2064
|
-
return
|
|
2065
|
-
updateDOM(content);
|
|
2066
|
-
return content;
|
|
2067
|
-
});
|
|
2076
|
+
return executeAndUpdate(...args);
|
|
2068
2077
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
}, remainingTime);
|
|
2078
|
-
}
|
|
2079
|
-
return result;
|
|
2078
|
+
const hasScheduledTimer = !!timers.throttleTimer;
|
|
2079
|
+
if (!hasScheduledTimer) {
|
|
2080
|
+
const remainingTime = throttleMs - (now - timers.lastThrottleCall);
|
|
2081
|
+
timers.throttleTimer = setTimeout(() => {
|
|
2082
|
+
timers.throttleTimer = null;
|
|
2083
|
+
timers.lastThrottleCall = Date.now();
|
|
2084
|
+
executeAndUpdate(...args);
|
|
2085
|
+
}, remainingTime);
|
|
2080
2086
|
}
|
|
2087
|
+
return undefined;
|
|
2081
2088
|
}
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
updateDOM(content);
|
|
2085
|
-
return content;
|
|
2086
|
-
});
|
|
2087
|
-
}
|
|
2088
|
-
else {
|
|
2089
|
-
// Handle sync method
|
|
2090
|
-
if (options.debounce !== undefined && options.debounce > 0) {
|
|
2091
|
-
// Debounce: defer DOM update, return result immediately
|
|
2092
|
-
if (timers.debounceTimer) {
|
|
2093
|
-
clearTimeout(timers.debounceTimer);
|
|
2094
|
-
}
|
|
2095
|
-
timers.debounceTimer = setTimeout(() => {
|
|
2096
|
-
updateDOM(result);
|
|
2097
|
-
}, options.debounce);
|
|
2098
|
-
return result;
|
|
2099
|
-
}
|
|
2100
|
-
if (options.throttle !== undefined && options.throttle > 0) {
|
|
2101
|
-
// Throttle: handle timing for DOM updates
|
|
2102
|
-
const now = Date.now();
|
|
2103
|
-
if (timers.lastThrottleCall === 0 || now - timers.lastThrottleCall >= options.throttle) {
|
|
2104
|
-
timers.lastThrottleCall = now;
|
|
2105
|
-
updateDOM(result);
|
|
2106
|
-
}
|
|
2107
|
-
else {
|
|
2108
|
-
if (!timers.throttleTimer) {
|
|
2109
|
-
const remainingTime = options.throttle - (now - timers.lastThrottleCall);
|
|
2110
|
-
timers.throttleTimer = setTimeout(() => {
|
|
2111
|
-
timers.throttleTimer = null;
|
|
2112
|
-
timers.lastThrottleCall = Date.now();
|
|
2113
|
-
updateDOM(result);
|
|
2114
|
-
}, remainingTime);
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
return result;
|
|
2118
|
-
}
|
|
2119
|
-
// No timing: update DOM immediately
|
|
2120
|
-
updateDOM(result);
|
|
2121
|
-
return result;
|
|
2089
|
+
default:
|
|
2090
|
+
return executeAndUpdate(...args);
|
|
2122
2091
|
}
|
|
2123
2092
|
};
|
|
2124
2093
|
};
|