snice 2.1.2 → 2.1.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.
- package/components/table/snice-table.ts +2 -2
- package/dist/index.cjs +67 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.cjs.min.map +1 -1
- package/dist/index.esm.js +67 -96
- 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 +67 -96
- 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.3
|
|
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
|
|
@@ -115,7 +117,9 @@ function setupEventHandlers(instance, element) {
|
|
|
115
117
|
instance[CLEANUP] = { events: [], channels: [] };
|
|
116
118
|
}
|
|
117
119
|
for (const handler of handlers) {
|
|
118
|
-
|
|
120
|
+
// Get the current method from the instance (preserves decorator stacking)
|
|
121
|
+
const currentMethod = instance[handler.method.name];
|
|
122
|
+
const originalMethod = currentMethod ? currentMethod.bind(instance) : handler.method.bind(instance);
|
|
119
123
|
const handlerOptions = handler.options || {};
|
|
120
124
|
// Parse event name for key modifiers
|
|
121
125
|
const [baseEventName, keyModifier] = handler.eventName.split(':');
|
|
@@ -297,12 +301,21 @@ function cleanupEventHandlers(instance) {
|
|
|
297
301
|
*/
|
|
298
302
|
function dispatch(eventName, options) {
|
|
299
303
|
return function (originalMethod, _context) {
|
|
300
|
-
// Create timing wrappers for dispatch
|
|
301
|
-
let debounceTimeout;
|
|
302
|
-
let throttleLastCall = 0;
|
|
303
|
-
let throttleTimeout;
|
|
304
304
|
return function (...args) {
|
|
305
|
-
//
|
|
305
|
+
// Create timing wrappers for dispatch (per-instance)
|
|
306
|
+
if (!this[DISPATCH_TIMERS]) {
|
|
307
|
+
this[DISPATCH_TIMERS] = new Map();
|
|
308
|
+
}
|
|
309
|
+
const timerKey = `${eventName}_${_context.name}`;
|
|
310
|
+
if (!this[DISPATCH_TIMERS].has(timerKey)) {
|
|
311
|
+
this[DISPATCH_TIMERS].set(timerKey, {
|
|
312
|
+
debounceTimeout: null,
|
|
313
|
+
throttleLastCall: 0,
|
|
314
|
+
throttleTimeout: null
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
const timers = this[DISPATCH_TIMERS].get(timerKey);
|
|
318
|
+
// Call the original method with preserved this context
|
|
306
319
|
const result = originalMethod.apply(this, args);
|
|
307
320
|
// Helper to dispatch the event
|
|
308
321
|
const doDispatch = (detail) => {
|
|
@@ -322,21 +335,21 @@ function dispatch(eventName, options) {
|
|
|
322
335
|
// Helper to handle timed dispatch
|
|
323
336
|
const timedDispatch = (detail) => {
|
|
324
337
|
if (options?.debounce) {
|
|
325
|
-
clearTimeout(debounceTimeout);
|
|
326
|
-
debounceTimeout = setTimeout(() => doDispatch(detail), options.debounce);
|
|
338
|
+
clearTimeout(timers.debounceTimeout);
|
|
339
|
+
timers.debounceTimeout = setTimeout(() => doDispatch(detail), options.debounce);
|
|
327
340
|
}
|
|
328
341
|
else if (options?.throttle) {
|
|
329
342
|
const now = Date.now();
|
|
330
|
-
const remaining = options.throttle - (now - throttleLastCall);
|
|
343
|
+
const remaining = options.throttle - (now - timers.throttleLastCall);
|
|
331
344
|
if (remaining <= 0) {
|
|
332
|
-
clearTimeout(throttleTimeout);
|
|
333
|
-
throttleLastCall = now;
|
|
345
|
+
clearTimeout(timers.throttleTimeout);
|
|
346
|
+
timers.throttleLastCall = now;
|
|
334
347
|
doDispatch(detail);
|
|
335
348
|
}
|
|
336
|
-
else if (!throttleTimeout) {
|
|
337
|
-
throttleTimeout = setTimeout(() => {
|
|
338
|
-
throttleLastCall = Date.now();
|
|
339
|
-
throttleTimeout = null;
|
|
349
|
+
else if (!timers.throttleTimeout) {
|
|
350
|
+
timers.throttleTimeout = setTimeout(() => {
|
|
351
|
+
timers.throttleLastCall = Date.now();
|
|
352
|
+
timers.throttleTimeout = null;
|
|
340
353
|
doDispatch(detail);
|
|
341
354
|
}, remaining);
|
|
342
355
|
}
|
|
@@ -1428,6 +1441,7 @@ function applyElementFunctionality(constructor) {
|
|
|
1428
1441
|
try {
|
|
1429
1442
|
const partElement = this.shadowRoot.querySelector(`[part="${partName}"]`);
|
|
1430
1443
|
if (partElement) {
|
|
1444
|
+
// For initial render, call original method directly to avoid timing restrictions
|
|
1431
1445
|
const partResult = partHandler.method.call(this);
|
|
1432
1446
|
const partContent = partResult instanceof Promise ? await partResult : partResult;
|
|
1433
1447
|
if (partContent !== undefined) {
|
|
@@ -2031,94 +2045,51 @@ function part(partName, options = {}) {
|
|
|
2031
2045
|
});
|
|
2032
2046
|
}
|
|
2033
2047
|
const timers = this[PART_TIMERS].get(partName);
|
|
2034
|
-
//
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
const
|
|
2040
|
-
if (
|
|
2041
|
-
|
|
2048
|
+
// Helper function to execute method and update DOM
|
|
2049
|
+
const executeAndUpdate = (...methodArgs) => {
|
|
2050
|
+
const result = originalMethod.apply(this, methodArgs);
|
|
2051
|
+
const updateDOM = (content) => {
|
|
2052
|
+
const hasContent = content !== undefined;
|
|
2053
|
+
const hasElement = this.shadowRoot?.querySelector(`[part="${partName}"]`);
|
|
2054
|
+
if (hasContent && hasElement) {
|
|
2055
|
+
hasElement.innerHTML = content;
|
|
2042
2056
|
}
|
|
2043
|
-
}
|
|
2057
|
+
};
|
|
2058
|
+
const isPromise = result instanceof Promise;
|
|
2059
|
+
return isPromise
|
|
2060
|
+
? result.then(content => { updateDOM(content); return content; })
|
|
2061
|
+
: (updateDOM(result), result);
|
|
2044
2062
|
};
|
|
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;
|
|
2063
|
+
const hasDebounce = options.debounce !== undefined && options.debounce > 0;
|
|
2064
|
+
const hasThrottle = options.throttle !== undefined && options.throttle > 0;
|
|
2065
|
+
// Handle timing based on priority: debounce > throttle > immediate
|
|
2066
|
+
switch (true) {
|
|
2067
|
+
case hasDebounce: {
|
|
2068
|
+
clearTimeout(timers.debounceTimer);
|
|
2069
|
+
timers.debounceTimer = setTimeout(() => executeAndUpdate(...args), options.debounce);
|
|
2070
|
+
return undefined;
|
|
2058
2071
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2072
|
+
case hasThrottle: {
|
|
2073
|
+
const throttleMs = options.throttle;
|
|
2061
2074
|
const now = Date.now();
|
|
2062
|
-
|
|
2075
|
+
const canExecuteImmediately = timers.lastThrottleCall === 0 || now - timers.lastThrottleCall >= throttleMs;
|
|
2076
|
+
if (canExecuteImmediately) {
|
|
2063
2077
|
timers.lastThrottleCall = now;
|
|
2064
|
-
return
|
|
2065
|
-
updateDOM(content);
|
|
2066
|
-
return content;
|
|
2067
|
-
});
|
|
2078
|
+
return executeAndUpdate(...args);
|
|
2068
2079
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
}, remainingTime);
|
|
2078
|
-
}
|
|
2079
|
-
return result;
|
|
2080
|
+
const hasScheduledTimer = !!timers.throttleTimer;
|
|
2081
|
+
if (!hasScheduledTimer) {
|
|
2082
|
+
const remainingTime = throttleMs - (now - timers.lastThrottleCall);
|
|
2083
|
+
timers.throttleTimer = setTimeout(() => {
|
|
2084
|
+
timers.throttleTimer = null;
|
|
2085
|
+
timers.lastThrottleCall = Date.now();
|
|
2086
|
+
executeAndUpdate(...args);
|
|
2087
|
+
}, remainingTime);
|
|
2080
2088
|
}
|
|
2089
|
+
return undefined;
|
|
2081
2090
|
}
|
|
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;
|
|
2091
|
+
default:
|
|
2092
|
+
return executeAndUpdate(...args);
|
|
2122
2093
|
}
|
|
2123
2094
|
};
|
|
2124
2095
|
};
|