snice 1.14.3 → 2.1.0
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/bin/templates/base/tsconfig.json +5 -4
- package/components/accordion/demo.html +403 -0
- package/components/accordion/snice-accordion-item.css +85 -0
- package/components/accordion/snice-accordion-item.ts +226 -0
- package/components/accordion/snice-accordion.css +31 -0
- package/components/accordion/snice-accordion.ts +182 -0
- package/components/accordion/snice-accordion.types.ts +32 -0
- package/components/alert/demo.html +445 -0
- package/components/alert/snice-alert.css +195 -0
- package/components/alert/snice-alert.ts +141 -0
- package/components/alert/snice-alert.types.ts +12 -0
- package/components/avatar/demo.html +598 -0
- package/components/avatar/snice-avatar.css +131 -0
- package/components/avatar/snice-avatar.ts +136 -0
- package/components/avatar/snice-avatar.types.ts +13 -0
- package/components/badge/demo.html +523 -0
- package/components/badge/snice-badge.css +161 -0
- package/components/badge/snice-badge.ts +117 -0
- package/components/badge/snice-badge.types.ts +16 -0
- package/components/breadcrumbs/demo.html +404 -0
- package/components/breadcrumbs/snice-breadcrumbs.css +133 -0
- package/components/breadcrumbs/snice-breadcrumbs.ts +191 -0
- package/components/breadcrumbs/snice-breadcrumbs.types.ts +26 -0
- package/components/breadcrumbs/snice-crumb.ts +26 -0
- package/components/button/demo.html +42 -0
- package/components/button/snice-button.css +230 -0
- package/components/button/snice-button.ts +169 -0
- package/components/button/snice-button.types.ts +25 -0
- package/components/card/demo.html +525 -0
- package/components/card/snice-card.css +140 -0
- package/components/card/snice-card.ts +102 -0
- package/components/card/snice-card.types.ts +10 -0
- package/components/checkbox/demo.html +253 -0
- package/components/checkbox/snice-checkbox.css +164 -0
- package/components/checkbox/snice-checkbox.ts +223 -0
- package/components/checkbox/snice-checkbox.types.ts +22 -0
- package/components/chip/demo.html +383 -0
- package/components/chip/snice-chip.css +195 -0
- package/components/chip/snice-chip.ts +139 -0
- package/components/chip/snice-chip.types.ts +15 -0
- package/components/date-picker/README.md +233 -0
- package/components/date-picker/demo.html +191 -0
- package/components/date-picker/snice-date-picker.css +330 -0
- package/components/date-picker/snice-date-picker.ts +777 -0
- package/components/date-picker/snice-date-picker.types.ts +83 -0
- package/components/divider/demo.html +233 -0
- package/components/divider/snice-divider.css +155 -0
- package/components/divider/snice-divider.ts +69 -0
- package/components/divider/snice-divider.types.ts +15 -0
- package/components/drawer/demo.html +328 -0
- package/components/drawer/snice-drawer.css +476 -0
- package/components/drawer/snice-drawer.ts +287 -0
- package/components/drawer/snice-drawer.types.ts +17 -0
- package/components/global.d.ts +14 -0
- package/components/input/demo.html +303 -0
- package/components/input/snice-input.css +257 -0
- package/components/input/snice-input.ts +442 -0
- package/components/input/snice-input.types.ts +59 -0
- package/components/input/test.html +77 -0
- package/components/layout/README.md +260 -0
- package/components/layout/demo.html +538 -0
- package/components/layout/snice-layout-blog.css +129 -0
- package/components/layout/snice-layout-blog.ts +48 -0
- package/components/layout/snice-layout-card.css +104 -0
- package/components/layout/snice-layout-card.ts +35 -0
- package/components/layout/snice-layout-centered.css +51 -0
- package/components/layout/snice-layout-centered.ts +22 -0
- package/components/layout/snice-layout-dashboard.css +98 -0
- package/components/layout/snice-layout-dashboard.ts +45 -0
- package/components/layout/snice-layout-fullscreen.css +72 -0
- package/components/layout/snice-layout-fullscreen.ts +34 -0
- package/components/layout/snice-layout-landing.css +92 -0
- package/components/layout/snice-layout-landing.ts +47 -0
- package/components/layout/snice-layout-minimal.css +16 -0
- package/components/layout/snice-layout-minimal.ts +19 -0
- package/components/layout/snice-layout-sidebar.css +117 -0
- package/components/layout/snice-layout-sidebar.ts +48 -0
- package/components/layout/snice-layout-split.css +103 -0
- package/components/layout/snice-layout-split.ts +29 -0
- package/components/layout/snice-layout.css +72 -0
- package/components/layout/snice-layout.ts +35 -0
- package/components/layout/snice-layout.types.ts +5 -0
- package/components/login/demo-auth-controller.ts +185 -0
- package/components/login/demo.html +470 -0
- package/components/login/snice-login.css +204 -0
- package/components/login/snice-login.ts +337 -0
- package/components/login/snice-login.types.ts +34 -0
- package/components/modal/demo.html +291 -0
- package/components/modal/snice-modal.css +203 -0
- package/components/modal/snice-modal.ts +233 -0
- package/components/modal/snice-modal.types.ts +21 -0
- package/components/pagination/demo.html +395 -0
- package/components/pagination/snice-pagination.ts +333 -0
- package/components/pagination/snice-pagination.types.ts +21 -0
- package/components/progress/demo.html +510 -0
- package/components/progress/snice-progress.css +267 -0
- package/components/progress/snice-progress.ts +247 -0
- package/components/progress/snice-progress.types.ts +19 -0
- package/components/radio/demo.html +287 -0
- package/components/radio/snice-radio.css +171 -0
- package/components/radio/snice-radio.ts +218 -0
- package/components/radio/snice-radio.types.ts +21 -0
- package/components/select/demo.html +511 -0
- package/components/select/snice-option.ts +52 -0
- package/components/select/snice-option.types.ts +14 -0
- package/components/select/snice-select.css +392 -0
- package/components/select/snice-select.ts +796 -0
- package/components/select/snice-select.types.ts +55 -0
- package/components/skeleton/demo.html +514 -0
- package/components/skeleton/snice-skeleton.css +109 -0
- package/components/skeleton/snice-skeleton.ts +126 -0
- package/components/skeleton/snice-skeleton.types.ts +11 -0
- package/components/switch/demo.html +284 -0
- package/components/switch/snice-switch.css +221 -0
- package/components/switch/snice-switch.ts +229 -0
- package/components/switch/snice-switch.types.ts +23 -0
- package/components/symbols.ts +23 -0
- package/components/table/demo-table-controller.ts +100 -0
- package/components/table/demo.html +480 -0
- package/components/table/snice-cell-boolean.ts +112 -0
- package/components/table/snice-cell-date.ts +210 -0
- package/components/table/snice-cell-duration.ts +91 -0
- package/components/table/snice-cell-filesize.ts +90 -0
- package/components/table/snice-cell-number.ts +165 -0
- package/components/table/snice-cell-progress.ts +83 -0
- package/components/table/snice-cell-rating.ts +82 -0
- package/components/table/snice-cell-sparkline.ts +253 -0
- package/components/table/snice-cell-text.ts +125 -0
- package/components/table/snice-cell.css +296 -0
- package/components/table/snice-cell.ts +473 -0
- package/components/table/snice-column.ts +353 -0
- package/components/table/snice-header.css +243 -0
- package/components/table/snice-header.ts +261 -0
- package/components/table/snice-progress.ts +66 -0
- package/components/table/snice-rating.ts +45 -0
- package/components/table/snice-row.css +255 -0
- package/components/table/snice-row.ts +331 -0
- package/components/table/snice-table.css +241 -0
- package/components/table/snice-table.ts +737 -0
- package/components/table/snice-table.types.ts +158 -0
- package/components/tabs/demo.html +487 -0
- package/components/tabs/snice-tab-panel.css +264 -0
- package/components/tabs/snice-tab-panel.ts +47 -0
- package/components/tabs/snice-tab.css +96 -0
- package/components/tabs/snice-tab.ts +65 -0
- package/components/tabs/snice-tabs.css +189 -0
- package/components/tabs/snice-tabs.ts +332 -0
- package/components/tabs/snice-tabs.types.ts +28 -0
- package/components/theme/theme.css +234 -0
- package/components/toast/demo.html +329 -0
- package/components/toast/snice-toast-container.ts +256 -0
- package/components/toast/snice-toast.css +213 -0
- package/components/toast/snice-toast.ts +276 -0
- package/components/toast/snice-toast.types.ts +35 -0
- package/components/tooltip/demo.html +350 -0
- package/components/tooltip/snice-tooltip-portal.css +79 -0
- package/components/tooltip/snice-tooltip.css +117 -0
- package/components/tooltip/snice-tooltip.ts +612 -0
- package/components/tooltip/snice-tooltip.types.ts +32 -0
- package/components/transitions.ts +94 -0
- package/components/tsconfig.json +18 -0
- package/dist/index.cjs +441 -329
- package/dist/index.cjs.map +1 -1
- package/dist/index.cjs.min.map +1 -1
- package/dist/index.esm.js +441 -329
- 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 +441 -329
- 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.esm.js +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/controller.d.ts +1 -1
- package/dist/types/element.d.ts +10 -10
- package/dist/types/events.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/observe.d.ts +1 -1
- package/dist/types/request-response.d.ts +2 -3
- package/dist/types/router.d.ts +1 -1
- package/package.json +9 -3
- package/dist/index.cjs.min +0 -15
- package/dist/symbols.cjs +0 -103
- package/dist/transitions.cjs +0 -219
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v1.14.
|
|
2
|
+
* snice v1.14.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.
|
|
@@ -80,24 +80,27 @@ function on(eventName, selectorOrOptions, options) {
|
|
|
80
80
|
selector = undefined;
|
|
81
81
|
opts = selectorOrOptions;
|
|
82
82
|
}
|
|
83
|
-
return function (target,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
83
|
+
return function (target, context) {
|
|
84
|
+
const propertyKey = context.name;
|
|
85
|
+
context.addInitializer(function () {
|
|
86
|
+
const constructor = this.constructor;
|
|
87
|
+
// Store event handler metadata
|
|
88
|
+
if (!constructor.prototype[ON_HANDLERS]) {
|
|
89
|
+
constructor.prototype[ON_HANDLERS] = [];
|
|
90
|
+
}
|
|
91
|
+
// Normalize to array and expand at decoration time
|
|
92
|
+
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
93
|
+
// Create a handler entry for each event
|
|
94
|
+
for (const event of eventNames) {
|
|
95
|
+
constructor.prototype[ON_HANDLERS].push({
|
|
96
|
+
eventName: event,
|
|
97
|
+
selector,
|
|
98
|
+
methodName: propertyKey,
|
|
99
|
+
method: target,
|
|
100
|
+
options: opts
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
101
104
|
};
|
|
102
105
|
}
|
|
103
106
|
// Helper to setup event handlers for elements
|
|
@@ -291,13 +294,12 @@ function cleanupEventHandlers(instance) {
|
|
|
291
294
|
* @param options Optional configuration extending EventInit
|
|
292
295
|
*/
|
|
293
296
|
function dispatch(eventName, options) {
|
|
294
|
-
return function (
|
|
295
|
-
const originalMethod = descriptor.value;
|
|
297
|
+
return function (originalMethod, _context) {
|
|
296
298
|
// Create timing wrappers for dispatch
|
|
297
299
|
let debounceTimeout;
|
|
298
300
|
let throttleLastCall = 0;
|
|
299
301
|
let throttleTimeout;
|
|
300
|
-
|
|
302
|
+
return function (...args) {
|
|
301
303
|
// Call the original method
|
|
302
304
|
const result = originalMethod.apply(this, args);
|
|
303
305
|
// Helper to dispatch the event
|
|
@@ -352,7 +354,6 @@ function dispatch(eventName, options) {
|
|
|
352
354
|
timedDispatch(result);
|
|
353
355
|
return result;
|
|
354
356
|
};
|
|
355
|
-
return descriptor;
|
|
356
357
|
};
|
|
357
358
|
}
|
|
358
359
|
|
|
@@ -379,27 +380,30 @@ function observe(observeTarget, selectorOrOptions, options) {
|
|
|
379
380
|
selector = undefined;
|
|
380
381
|
opts = selectorOrOptions;
|
|
381
382
|
}
|
|
382
|
-
return function (target,
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
type
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
383
|
+
return function (target, context) {
|
|
384
|
+
const propertyKey = context.name;
|
|
385
|
+
context.addInitializer(function () {
|
|
386
|
+
const constructor = this.constructor;
|
|
387
|
+
// Store observer metadata
|
|
388
|
+
if (!constructor.prototype[OBSERVERS]) {
|
|
389
|
+
constructor.prototype[OBSERVERS] = [];
|
|
390
|
+
}
|
|
391
|
+
// Normalize to array
|
|
392
|
+
const observeTargets = Array.isArray(observeTarget) ? observeTarget : [observeTarget];
|
|
393
|
+
// Create an observer entry for each target
|
|
394
|
+
for (const targetString of observeTargets) {
|
|
395
|
+
// Parse the observation type from the observeTarget string
|
|
396
|
+
const [type, ...modifiers] = targetString.split(':');
|
|
397
|
+
constructor.prototype[OBSERVERS].push({
|
|
398
|
+
type,
|
|
399
|
+
target: modifiers.join(':'), // Rejoin for media queries or mutation types
|
|
400
|
+
selector,
|
|
401
|
+
methodName: propertyKey,
|
|
402
|
+
method: target,
|
|
403
|
+
options: opts
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
});
|
|
403
407
|
};
|
|
404
408
|
}
|
|
405
409
|
// Helper to setup observers for elements
|
|
@@ -692,13 +696,12 @@ function cleanupObservers(instance) {
|
|
|
692
696
|
* @param options Optional configuration
|
|
693
697
|
*/
|
|
694
698
|
function request(requestName, options) {
|
|
695
|
-
return function (
|
|
696
|
-
const originalMethod = descriptor.value;
|
|
699
|
+
return function (originalMethod, _context) {
|
|
697
700
|
// Create timing variables for debounce/throttle
|
|
698
701
|
let debounceTimeout;
|
|
699
702
|
let throttleLastCall = 0;
|
|
700
703
|
let throttleTimeout;
|
|
701
|
-
|
|
704
|
+
return async function (...args) {
|
|
702
705
|
const actualRequest = async () => {
|
|
703
706
|
// @request always acts as requester (client side)
|
|
704
707
|
const responseTimeout = options?.timeout ?? 120000; // Default 2 minute timeout
|
|
@@ -822,7 +825,6 @@ function request(requestName, options) {
|
|
|
822
825
|
// No timing applied, execute immediately
|
|
823
826
|
return actualRequest();
|
|
824
827
|
};
|
|
825
|
-
return descriptor;
|
|
826
828
|
};
|
|
827
829
|
}
|
|
828
830
|
/**
|
|
@@ -832,20 +834,22 @@ function request(requestName, options) {
|
|
|
832
834
|
* @param options Optional configuration
|
|
833
835
|
*/
|
|
834
836
|
function respond(requestName, options) {
|
|
835
|
-
return function (target,
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
837
|
+
return function (target, context) {
|
|
838
|
+
const propertyKey = context.name;
|
|
839
|
+
context.addInitializer(function () {
|
|
840
|
+
const constructor = this.constructor;
|
|
841
|
+
// Store response metadata on the prototype
|
|
842
|
+
// This will be picked up by setupResponseHandlers
|
|
843
|
+
if (!constructor.prototype[CHANNEL_HANDLERS]) {
|
|
844
|
+
constructor.prototype[CHANNEL_HANDLERS] = [];
|
|
845
|
+
}
|
|
846
|
+
constructor.prototype[CHANNEL_HANDLERS].push({
|
|
847
|
+
channelName: requestName,
|
|
848
|
+
methodName: propertyKey,
|
|
849
|
+
method: target,
|
|
850
|
+
options: options
|
|
851
|
+
});
|
|
847
852
|
});
|
|
848
|
-
return descriptor;
|
|
849
853
|
};
|
|
850
854
|
}
|
|
851
855
|
// Helper to setup response handlers for elements and controllers
|
|
@@ -996,7 +1000,7 @@ class ControllerScope {
|
|
|
996
1000
|
* @param name The name to register the controller under
|
|
997
1001
|
*/
|
|
998
1002
|
function controller(name) {
|
|
999
|
-
return function (constructor) {
|
|
1003
|
+
return function (constructor, _context) {
|
|
1000
1004
|
snice.controllerRegistry.set(name, constructor);
|
|
1001
1005
|
// Mark as controller class for channel decorator detection
|
|
1002
1006
|
constructor.prototype[IS_CONTROLLER_CLASS] = true;
|
|
@@ -1343,10 +1347,12 @@ function applyElementFunctionality(constructor) {
|
|
|
1343
1347
|
// Mark that properties have been initialized
|
|
1344
1348
|
this[PROPERTIES_INITIALIZED] = true;
|
|
1345
1349
|
// Reflect properties that were explicitly set before connection
|
|
1346
|
-
//
|
|
1347
|
-
if (properties
|
|
1350
|
+
// AND also reflect initial values that have reflect: true
|
|
1351
|
+
if (properties) {
|
|
1348
1352
|
for (const [propName, propOptions] of properties) {
|
|
1349
|
-
|
|
1353
|
+
const wasExplicitlySet = this[EXPLICITLY_SET_PROPERTIES] && this[EXPLICITLY_SET_PROPERTIES].has(propName);
|
|
1354
|
+
const hasInitialValue = propName in this[PROPERTY_VALUES];
|
|
1355
|
+
if (propOptions.reflect && hasInitialValue && (wasExplicitlySet || this[PROPERTY_VALUES][propName] !== undefined)) {
|
|
1350
1356
|
const value = this[PROPERTY_VALUES][propName];
|
|
1351
1357
|
const attributeName = typeof propOptions.attribute === 'string' ? propOptions.attribute : propName.toLowerCase();
|
|
1352
1358
|
if (value !== null && value !== undefined && value !== false &&
|
|
@@ -1595,176 +1601,224 @@ function applyElementFunctionality(constructor) {
|
|
|
1595
1601
|
};
|
|
1596
1602
|
}
|
|
1597
1603
|
function element(tagName) {
|
|
1598
|
-
return function (constructor) {
|
|
1604
|
+
return function (constructor, context) {
|
|
1605
|
+
// Transfer metadata from context to constructor
|
|
1606
|
+
if (context.metadata && context.metadata[PROPERTIES]) {
|
|
1607
|
+
if (!constructor[PROPERTIES]) {
|
|
1608
|
+
constructor[PROPERTIES] = new Map();
|
|
1609
|
+
}
|
|
1610
|
+
for (const [key, value] of context.metadata[PROPERTIES]) {
|
|
1611
|
+
constructor[PROPERTIES].set(key, value);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1599
1614
|
applyElementFunctionality(constructor);
|
|
1600
1615
|
customElements.define(tagName, constructor);
|
|
1616
|
+
return constructor;
|
|
1601
1617
|
};
|
|
1602
1618
|
}
|
|
1603
1619
|
function layout(tagName) {
|
|
1604
|
-
return function (constructor) {
|
|
1620
|
+
return function (constructor, context) {
|
|
1621
|
+
// Transfer metadata from context to constructor
|
|
1622
|
+
if (context.metadata && context.metadata[PROPERTIES]) {
|
|
1623
|
+
if (!constructor[PROPERTIES]) {
|
|
1624
|
+
constructor[PROPERTIES] = new Map();
|
|
1625
|
+
}
|
|
1626
|
+
for (const [key, value] of context.metadata[PROPERTIES]) {
|
|
1627
|
+
constructor[PROPERTIES].set(key, value);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1605
1630
|
applyElementFunctionality(constructor);
|
|
1606
1631
|
customElements.define(tagName, constructor);
|
|
1632
|
+
return constructor;
|
|
1607
1633
|
};
|
|
1608
1634
|
}
|
|
1609
1635
|
function property(options) {
|
|
1610
|
-
return function (
|
|
1611
|
-
const
|
|
1612
|
-
//
|
|
1636
|
+
return function (_value, context) {
|
|
1637
|
+
const propertyKey = context.name;
|
|
1638
|
+
// Use metadata to store property information at decoration time
|
|
1639
|
+
if (!context.metadata) {
|
|
1640
|
+
context.metadata = {};
|
|
1641
|
+
}
|
|
1642
|
+
if (!context.metadata[PROPERTIES]) {
|
|
1643
|
+
context.metadata[PROPERTIES] = new Map();
|
|
1644
|
+
}
|
|
1645
|
+
context.metadata[PROPERTIES].set(propertyKey, options || {});
|
|
1646
|
+
// Warn about problematic reflection usage at decoration time
|
|
1613
1647
|
if (options?.reflect && options?.type === Array) {
|
|
1614
1648
|
console.warn(`⚠️ Property '${propertyKey}' uses reflect:true with Array type.`);
|
|
1615
1649
|
}
|
|
1616
1650
|
if (options?.reflect && options?.type === Object) {
|
|
1617
1651
|
console.warn(`⚠️ Property '${propertyKey}' uses reflect:true with Object type.`);
|
|
1618
1652
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
set(value) {
|
|
1631
|
-
if (!this[PROPERTY_VALUES]) {
|
|
1632
|
-
this[PROPERTY_VALUES] = {};
|
|
1633
|
-
}
|
|
1634
|
-
if (!this[EXPLICITLY_SET_PROPERTIES]) {
|
|
1635
|
-
this[EXPLICITLY_SET_PROPERTIES] = new Set();
|
|
1636
|
-
}
|
|
1637
|
-
const oldValue = this[PROPERTY_VALUES][propertyKey];
|
|
1638
|
-
// Don't update if value hasn't changed
|
|
1639
|
-
if (oldValue === value)
|
|
1640
|
-
return;
|
|
1641
|
-
// Mark as explicitly set in these cases:
|
|
1642
|
-
// 1. There was a previous value (normal property update)
|
|
1643
|
-
// 2. This is during element construction and we have a non-null/non-undefined value
|
|
1644
|
-
// (this handles default values declared in class properties)
|
|
1645
|
-
const isInitialDefaultValue = oldValue === undefined && !this[PROPERTIES_INITIALIZED];
|
|
1646
|
-
if (oldValue !== undefined || (isInitialDefaultValue && value !== null && value !== undefined)) {
|
|
1647
|
-
this[EXPLICITLY_SET_PROPERTIES].add(propertyKey);
|
|
1648
|
-
}
|
|
1649
|
-
this[PROPERTY_VALUES][propertyKey] = value;
|
|
1650
|
-
// Only reflect to attributes if:
|
|
1651
|
-
// 1. Properties have been initialized from attributes
|
|
1652
|
-
// 2. The property was explicitly set (not just default value)
|
|
1653
|
-
// This prevents default values from creating attributes
|
|
1654
|
-
if (options?.reflect && this.setAttribute && this[PROPERTIES_INITIALIZED] && this[EXPLICITLY_SET_PROPERTIES].has(propertyKey)) {
|
|
1655
|
-
const attributeName = typeof options.attribute === 'string' ? options.attribute : propertyKey.toLowerCase();
|
|
1656
|
-
if (value === null || value === undefined || value === false ||
|
|
1657
|
-
(options?.type === SimpleArray && Array.isArray(value) && value.length === 0)) {
|
|
1658
|
-
this.removeAttribute(attributeName);
|
|
1659
|
-
}
|
|
1660
|
-
else {
|
|
1661
|
-
// Handle special types for reflection
|
|
1662
|
-
let attributeValue;
|
|
1663
|
-
if (value instanceof Date) {
|
|
1664
|
-
attributeValue = value.toISOString();
|
|
1653
|
+
context.addInitializer(function () {
|
|
1654
|
+
// No longer need warnings here since they're at decoration time
|
|
1655
|
+
});
|
|
1656
|
+
// Return a field initializer function for new decorators
|
|
1657
|
+
return function (initialValue) {
|
|
1658
|
+
// Set up the property descriptor on first access
|
|
1659
|
+
if (!Object.hasOwnProperty.call(this.constructor.prototype, propertyKey)) {
|
|
1660
|
+
const descriptor = {
|
|
1661
|
+
get() {
|
|
1662
|
+
if (!this[PROPERTY_VALUES]) {
|
|
1663
|
+
this[PROPERTY_VALUES] = {};
|
|
1665
1664
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1665
|
+
return this[PROPERTY_VALUES][propertyKey];
|
|
1666
|
+
},
|
|
1667
|
+
set(newValue) {
|
|
1668
|
+
if (!this[PROPERTY_VALUES]) {
|
|
1669
|
+
this[PROPERTY_VALUES] = {};
|
|
1668
1670
|
}
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
+
if (!this[EXPLICITLY_SET_PROPERTIES]) {
|
|
1672
|
+
this[EXPLICITLY_SET_PROPERTIES] = new Set();
|
|
1671
1673
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
+
const oldValue = this[PROPERTY_VALUES][propertyKey];
|
|
1675
|
+
if (oldValue === newValue)
|
|
1676
|
+
return;
|
|
1677
|
+
const isInitialDefaultValue = oldValue === undefined && !this[PROPERTIES_INITIALIZED];
|
|
1678
|
+
if (oldValue !== undefined || (isInitialDefaultValue && newValue !== null && newValue !== undefined)) {
|
|
1679
|
+
this[EXPLICITLY_SET_PROPERTIES].add(propertyKey);
|
|
1674
1680
|
}
|
|
1675
|
-
this
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
// Call specific property watchers
|
|
1682
|
-
if (watchers.has(propertyKey)) {
|
|
1683
|
-
const propertyWatchers = watchers.get(propertyKey);
|
|
1684
|
-
for (const watcher of propertyWatchers) {
|
|
1685
|
-
try {
|
|
1686
|
-
// Always pass oldValue, newValue, and propertyName
|
|
1687
|
-
watcher.method.call(this, oldValue, value, propertyKey);
|
|
1681
|
+
this[PROPERTY_VALUES][propertyKey] = newValue;
|
|
1682
|
+
if (options?.reflect && this.setAttribute && this[PROPERTIES_INITIALIZED] && this[EXPLICITLY_SET_PROPERTIES].has(propertyKey)) {
|
|
1683
|
+
const attributeName = typeof options.attribute === 'string' ? options.attribute : propertyKey.toLowerCase();
|
|
1684
|
+
if (newValue === null || newValue === undefined || newValue === false ||
|
|
1685
|
+
(options?.type === SimpleArray && Array.isArray(newValue) && newValue.length === 0)) {
|
|
1686
|
+
this.removeAttribute(attributeName);
|
|
1688
1687
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1688
|
+
else {
|
|
1689
|
+
let attributeValue;
|
|
1690
|
+
if (newValue instanceof Date) {
|
|
1691
|
+
attributeValue = newValue.toISOString();
|
|
1692
|
+
}
|
|
1693
|
+
else if (typeof newValue === 'bigint') {
|
|
1694
|
+
attributeValue = newValue.toString() + 'n';
|
|
1695
|
+
}
|
|
1696
|
+
else if (options?.type === SimpleArray && Array.isArray(newValue)) {
|
|
1697
|
+
attributeValue = SimpleArray.serialize(newValue);
|
|
1698
|
+
}
|
|
1699
|
+
else {
|
|
1700
|
+
attributeValue = String(newValue);
|
|
1701
|
+
}
|
|
1702
|
+
this.setAttribute(attributeName, attributeValue);
|
|
1691
1703
|
}
|
|
1692
1704
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1705
|
+
const constructor = this.constructor;
|
|
1706
|
+
const watchers = constructor[PROPERTY_WATCHERS];
|
|
1707
|
+
if (watchers) {
|
|
1708
|
+
if (watchers.has(propertyKey)) {
|
|
1709
|
+
const propertyWatchers = watchers.get(propertyKey);
|
|
1710
|
+
for (const watcher of propertyWatchers) {
|
|
1711
|
+
try {
|
|
1712
|
+
watcher.method.call(this, oldValue, newValue, propertyKey);
|
|
1713
|
+
}
|
|
1714
|
+
catch (error) {
|
|
1715
|
+
console.error(`Error in @watch('${propertyKey}') method ${watcher.methodName}:`, error);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1701
1718
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1719
|
+
if (watchers.has('*')) {
|
|
1720
|
+
const wildcardWatchers = watchers.get('*');
|
|
1721
|
+
for (const watcher of wildcardWatchers) {
|
|
1722
|
+
try {
|
|
1723
|
+
watcher.method.call(this, oldValue, newValue, propertyKey);
|
|
1724
|
+
}
|
|
1725
|
+
catch (error) {
|
|
1726
|
+
console.error(`Error in @watch('*') method ${watcher.methodName}:`, error);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1704
1729
|
}
|
|
1705
1730
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1731
|
+
if (this.requestUpdate) {
|
|
1732
|
+
this.requestUpdate(propertyKey, oldValue);
|
|
1733
|
+
}
|
|
1734
|
+
},
|
|
1735
|
+
configurable: true,
|
|
1736
|
+
enumerable: true
|
|
1737
|
+
};
|
|
1738
|
+
Object.defineProperty(this.constructor.prototype, propertyKey, descriptor);
|
|
1739
|
+
}
|
|
1740
|
+
// Initialize the property value
|
|
1741
|
+
if (!this[PROPERTY_VALUES]) {
|
|
1742
|
+
this[PROPERTY_VALUES] = {};
|
|
1743
|
+
}
|
|
1744
|
+
this[PROPERTY_VALUES][propertyKey] = initialValue;
|
|
1745
|
+
return initialValue;
|
|
1715
1746
|
};
|
|
1716
|
-
Object.defineProperty(target, propertyKey, descriptor);
|
|
1717
1747
|
};
|
|
1718
1748
|
}
|
|
1719
1749
|
function query(selector, options = {}) {
|
|
1720
|
-
return function (
|
|
1750
|
+
return function (_value, context) {
|
|
1721
1751
|
// Default to shadow DOM only
|
|
1722
1752
|
const { light = false, shadow = true } = options;
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1753
|
+
const propertyKey = context.name;
|
|
1754
|
+
// Return a field initializer function for new decorators
|
|
1755
|
+
return function (initialValue) {
|
|
1756
|
+
// Set up the property descriptor on first access
|
|
1757
|
+
if (!Object.hasOwnProperty.call(this.constructor.prototype, propertyKey)) {
|
|
1758
|
+
const descriptor = {
|
|
1759
|
+
get() {
|
|
1760
|
+
// Check if this is a controller using the symbol
|
|
1761
|
+
const isController = this[IS_CONTROLLER_INSTANCE] === true;
|
|
1762
|
+
const root = isController && this.element ? this.element : this;
|
|
1763
|
+
// Query in specified contexts
|
|
1764
|
+
let result = null;
|
|
1765
|
+
if (shadow && root.shadowRoot) {
|
|
1766
|
+
result = root.shadowRoot.querySelector(selector);
|
|
1767
|
+
}
|
|
1768
|
+
if (!result && light) {
|
|
1769
|
+
result = root.querySelector(selector);
|
|
1770
|
+
}
|
|
1771
|
+
return result || null;
|
|
1772
|
+
},
|
|
1773
|
+
set() {
|
|
1774
|
+
// Query results are read-only
|
|
1775
|
+
},
|
|
1776
|
+
configurable: true,
|
|
1777
|
+
enumerable: true
|
|
1778
|
+
};
|
|
1779
|
+
Object.defineProperty(this.constructor.prototype, propertyKey, descriptor);
|
|
1780
|
+
}
|
|
1781
|
+
return initialValue;
|
|
1782
|
+
};
|
|
1741
1783
|
};
|
|
1742
1784
|
}
|
|
1743
1785
|
function queryAll(selector, options = {}) {
|
|
1744
|
-
return function (
|
|
1786
|
+
return function (_value, context) {
|
|
1745
1787
|
// Default to shadow DOM only
|
|
1746
1788
|
const { light = false, shadow = true } = options;
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1789
|
+
const propertyKey = context.name;
|
|
1790
|
+
// Return a field initializer function for new decorators
|
|
1791
|
+
return function (initialValue) {
|
|
1792
|
+
// Set up the property descriptor on first access
|
|
1793
|
+
if (!Object.hasOwnProperty.call(this.constructor.prototype, propertyKey)) {
|
|
1794
|
+
const descriptor = {
|
|
1795
|
+
get() {
|
|
1796
|
+
// Check if this is a controller using the symbol
|
|
1797
|
+
const isController = this[IS_CONTROLLER_INSTANCE] === true;
|
|
1798
|
+
const root = isController && this.element ? this.element : this;
|
|
1799
|
+
// Query in specified contexts and combine results
|
|
1800
|
+
const results = [];
|
|
1801
|
+
if (shadow && root.shadowRoot) {
|
|
1802
|
+
const shadowResults = root.shadowRoot.querySelectorAll(selector);
|
|
1803
|
+
results.push(...shadowResults);
|
|
1804
|
+
}
|
|
1805
|
+
if (light) {
|
|
1806
|
+
const lightResults = root.querySelectorAll(selector);
|
|
1807
|
+
results.push(...lightResults);
|
|
1808
|
+
}
|
|
1809
|
+
// Return a static NodeList-like object
|
|
1810
|
+
return results;
|
|
1811
|
+
},
|
|
1812
|
+
set() {
|
|
1813
|
+
// Query results are read-only
|
|
1814
|
+
},
|
|
1815
|
+
configurable: true,
|
|
1816
|
+
enumerable: true
|
|
1817
|
+
};
|
|
1818
|
+
Object.defineProperty(this.constructor.prototype, propertyKey, descriptor);
|
|
1819
|
+
}
|
|
1820
|
+
return initialValue;
|
|
1821
|
+
};
|
|
1768
1822
|
};
|
|
1769
1823
|
}
|
|
1770
1824
|
/**
|
|
@@ -1774,6 +1828,7 @@ function queryAll(selector, options = {}) {
|
|
|
1774
1828
|
* Strings cannot contain the full-width comma character
|
|
1775
1829
|
*/
|
|
1776
1830
|
class SimpleArray {
|
|
1831
|
+
static { this.SEPARATOR = ','; } // U+FF0C Full-width comma
|
|
1777
1832
|
/**
|
|
1778
1833
|
* Serialize array to string for attribute storage
|
|
1779
1834
|
*/
|
|
@@ -1823,24 +1878,25 @@ class SimpleArray {
|
|
|
1823
1878
|
});
|
|
1824
1879
|
}
|
|
1825
1880
|
}
|
|
1826
|
-
SimpleArray.SEPARATOR = ','; // U+FF0C Full-width comma
|
|
1827
1881
|
function watch(...propertyNames) {
|
|
1828
|
-
return function (target,
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1831
|
-
constructor
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1882
|
+
return function (target, context) {
|
|
1883
|
+
const methodName = context.name;
|
|
1884
|
+
context.addInitializer(function () {
|
|
1885
|
+
const constructor = this.constructor;
|
|
1886
|
+
if (!constructor[PROPERTY_WATCHERS]) {
|
|
1887
|
+
constructor[PROPERTY_WATCHERS] = new Map();
|
|
1888
|
+
}
|
|
1889
|
+
// Store the watcher method for each property
|
|
1890
|
+
for (const propertyName of propertyNames) {
|
|
1891
|
+
if (!constructor[PROPERTY_WATCHERS].has(propertyName)) {
|
|
1892
|
+
constructor[PROPERTY_WATCHERS].set(propertyName, []);
|
|
1893
|
+
}
|
|
1894
|
+
constructor[PROPERTY_WATCHERS].get(propertyName).push({
|
|
1895
|
+
methodName,
|
|
1896
|
+
method: target
|
|
1897
|
+
});
|
|
1837
1898
|
}
|
|
1838
|
-
|
|
1839
|
-
methodName,
|
|
1840
|
-
method: descriptor.value
|
|
1841
|
-
});
|
|
1842
|
-
}
|
|
1843
|
-
return descriptor;
|
|
1899
|
+
});
|
|
1844
1900
|
};
|
|
1845
1901
|
}
|
|
1846
1902
|
/**
|
|
@@ -1848,46 +1904,57 @@ function watch(...propertyNames) {
|
|
|
1848
1904
|
* The context is automatically provided to page components by the router
|
|
1849
1905
|
*/
|
|
1850
1906
|
function context() {
|
|
1851
|
-
return function (
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1907
|
+
return function (_value, context) {
|
|
1908
|
+
const propertyKey = context.name;
|
|
1909
|
+
// Return a field initializer function for new decorators
|
|
1910
|
+
return function (initialValue) {
|
|
1911
|
+
// Set up the property descriptor on first access
|
|
1912
|
+
if (!Object.hasOwnProperty.call(this.constructor.prototype, propertyKey)) {
|
|
1913
|
+
const descriptor = {
|
|
1914
|
+
get() {
|
|
1915
|
+
// First check if context is stored directly on this element
|
|
1916
|
+
if (this[ROUTER_CONTEXT] !== undefined) {
|
|
1917
|
+
return this[ROUTER_CONTEXT];
|
|
1918
|
+
}
|
|
1919
|
+
// Otherwise, request context from parent page via event
|
|
1920
|
+
const detail = { target: this };
|
|
1921
|
+
const event = new CustomEvent('@context/request', {
|
|
1922
|
+
bubbles: true,
|
|
1923
|
+
cancelable: true,
|
|
1924
|
+
detail
|
|
1925
|
+
});
|
|
1926
|
+
// Dispatch event and wait for response
|
|
1927
|
+
// Check if this is a controller using the symbol
|
|
1928
|
+
const isController = this[IS_CONTROLLER_INSTANCE] === true;
|
|
1929
|
+
let targetElement = isController && this.element ? this.element : this;
|
|
1930
|
+
// If element is null (e.g., controller was detached), can't get context
|
|
1931
|
+
if (!targetElement || !targetElement.dispatchEvent) {
|
|
1932
|
+
return undefined;
|
|
1933
|
+
}
|
|
1934
|
+
// If we're in shadow DOM, dispatch on the host element to ensure proper bubbling
|
|
1935
|
+
if (targetElement.getRootNode && targetElement.getRootNode() instanceof ShadowRoot) {
|
|
1936
|
+
const shadowRoot = targetElement.getRootNode();
|
|
1937
|
+
targetElement = shadowRoot.host;
|
|
1938
|
+
}
|
|
1939
|
+
targetElement.dispatchEvent(event);
|
|
1940
|
+
// Check if context was provided via the event
|
|
1941
|
+
if (detail.context !== undefined) {
|
|
1942
|
+
// Cache it for future use
|
|
1943
|
+
this[ROUTER_CONTEXT] = detail.context;
|
|
1944
|
+
return detail.context;
|
|
1945
|
+
}
|
|
1946
|
+
return undefined;
|
|
1947
|
+
},
|
|
1948
|
+
set() {
|
|
1949
|
+
// Context is read-only
|
|
1950
|
+
},
|
|
1951
|
+
configurable: true,
|
|
1952
|
+
enumerable: true
|
|
1953
|
+
};
|
|
1954
|
+
Object.defineProperty(this.constructor.prototype, propertyKey, descriptor);
|
|
1955
|
+
}
|
|
1956
|
+
return initialValue;
|
|
1957
|
+
};
|
|
1891
1958
|
};
|
|
1892
1959
|
}
|
|
1893
1960
|
/**
|
|
@@ -1896,16 +1963,18 @@ function context() {
|
|
|
1896
1963
|
* Supports async methods
|
|
1897
1964
|
*/
|
|
1898
1965
|
function ready() {
|
|
1899
|
-
return function (target,
|
|
1900
|
-
const
|
|
1901
|
-
|
|
1902
|
-
constructor
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1966
|
+
return function (target, context) {
|
|
1967
|
+
const methodName = context.name;
|
|
1968
|
+
context.addInitializer(function () {
|
|
1969
|
+
const constructor = this.constructor;
|
|
1970
|
+
if (!constructor[READY_HANDLERS]) {
|
|
1971
|
+
constructor[READY_HANDLERS] = [];
|
|
1972
|
+
}
|
|
1973
|
+
constructor[READY_HANDLERS].push({
|
|
1974
|
+
methodName,
|
|
1975
|
+
method: target
|
|
1976
|
+
});
|
|
1907
1977
|
});
|
|
1908
|
-
return descriptor;
|
|
1909
1978
|
};
|
|
1910
1979
|
}
|
|
1911
1980
|
/**
|
|
@@ -1913,16 +1982,18 @@ function ready() {
|
|
|
1913
1982
|
* Used for cleanup tasks when element is removed from DOM
|
|
1914
1983
|
*/
|
|
1915
1984
|
function dispose() {
|
|
1916
|
-
return function (target,
|
|
1917
|
-
const
|
|
1918
|
-
|
|
1919
|
-
constructor
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1985
|
+
return function (target, context) {
|
|
1986
|
+
const methodName = context.name;
|
|
1987
|
+
context.addInitializer(function () {
|
|
1988
|
+
const constructor = this.constructor;
|
|
1989
|
+
if (!constructor[DISPOSE_HANDLERS]) {
|
|
1990
|
+
constructor[DISPOSE_HANDLERS] = [];
|
|
1991
|
+
}
|
|
1992
|
+
constructor[DISPOSE_HANDLERS].push({
|
|
1993
|
+
methodName,
|
|
1994
|
+
method: target
|
|
1995
|
+
});
|
|
1924
1996
|
});
|
|
1925
|
-
return descriptor;
|
|
1926
1997
|
};
|
|
1927
1998
|
}
|
|
1928
1999
|
/**
|
|
@@ -1931,27 +2002,20 @@ function dispose() {
|
|
|
1931
2002
|
* When the decorated method is called, it automatically re-renders its part
|
|
1932
2003
|
*/
|
|
1933
2004
|
function part(partName, options = {}) {
|
|
1934
|
-
return function (
|
|
1935
|
-
const
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
const originalMethod = descriptor.value;
|
|
1946
|
-
if (!constructor[PARTS]) {
|
|
1947
|
-
constructor[PARTS] = new Map();
|
|
1948
|
-
}
|
|
1949
|
-
constructor[PARTS].set(partName, {
|
|
1950
|
-
methodName,
|
|
1951
|
-
method: originalMethod
|
|
2005
|
+
return function (originalMethod, context) {
|
|
2006
|
+
const methodName = context.name;
|
|
2007
|
+
context.addInitializer(function () {
|
|
2008
|
+
const constructor = this.constructor;
|
|
2009
|
+
if (!constructor[PARTS]) {
|
|
2010
|
+
constructor[PARTS] = new Map();
|
|
2011
|
+
}
|
|
2012
|
+
constructor[PARTS].set(partName, {
|
|
2013
|
+
methodName,
|
|
2014
|
+
method: originalMethod
|
|
2015
|
+
});
|
|
1952
2016
|
});
|
|
1953
|
-
//
|
|
1954
|
-
|
|
2017
|
+
// Return wrapped method that automatically re-renders the part when called
|
|
2018
|
+
return function (...args) {
|
|
1955
2019
|
// Initialize timers storage if not present
|
|
1956
2020
|
if (!this[PART_TIMERS]) {
|
|
1957
2021
|
this[PART_TIMERS] = new Map();
|
|
@@ -1965,58 +2029,96 @@ function part(partName, options = {}) {
|
|
|
1965
2029
|
});
|
|
1966
2030
|
}
|
|
1967
2031
|
const timers = this[PART_TIMERS].get(partName);
|
|
1968
|
-
//
|
|
1969
|
-
const
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
const content = result instanceof Promise ? await result : result;
|
|
1973
|
-
// Re-render the part if shadow DOM exists and content is defined
|
|
2032
|
+
// Call the original method first to get its result
|
|
2033
|
+
const result = originalMethod.apply(this, args);
|
|
2034
|
+
// Helper function to update DOM
|
|
2035
|
+
const updateDOM = (content) => {
|
|
1974
2036
|
if (this.shadowRoot && content !== undefined) {
|
|
1975
2037
|
const partElement = this.shadowRoot.querySelector(`[part="${partName}"]`);
|
|
1976
2038
|
if (partElement) {
|
|
1977
2039
|
partElement.innerHTML = content;
|
|
1978
2040
|
}
|
|
1979
2041
|
}
|
|
1980
|
-
return content;
|
|
1981
2042
|
};
|
|
1982
|
-
//
|
|
1983
|
-
if (
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2043
|
+
// Check if result is a Promise (async method)
|
|
2044
|
+
if (result instanceof Promise) {
|
|
2045
|
+
// Handle async method
|
|
2046
|
+
if (options.debounce !== undefined && options.debounce > 0) {
|
|
2047
|
+
// Debounce: defer DOM update, return original Promise
|
|
2048
|
+
if (timers.debounceTimer) {
|
|
2049
|
+
clearTimeout(timers.debounceTimer);
|
|
2050
|
+
}
|
|
1988
2051
|
timers.debounceTimer = setTimeout(async () => {
|
|
1989
|
-
const
|
|
1990
|
-
|
|
2052
|
+
const content = await result;
|
|
2053
|
+
updateDOM(content);
|
|
1991
2054
|
}, options.debounce);
|
|
2055
|
+
return result;
|
|
2056
|
+
}
|
|
2057
|
+
if (options.throttle !== undefined && options.throttle > 0) {
|
|
2058
|
+
// Throttle: handle timing but return original Promise
|
|
2059
|
+
const now = Date.now();
|
|
2060
|
+
if (timers.lastThrottleCall === 0 || now - timers.lastThrottleCall >= options.throttle) {
|
|
2061
|
+
timers.lastThrottleCall = now;
|
|
2062
|
+
return result.then(content => {
|
|
2063
|
+
updateDOM(content);
|
|
2064
|
+
return content;
|
|
2065
|
+
});
|
|
2066
|
+
}
|
|
2067
|
+
else {
|
|
2068
|
+
if (!timers.throttleTimer) {
|
|
2069
|
+
const remainingTime = options.throttle - (now - timers.lastThrottleCall);
|
|
2070
|
+
timers.throttleTimer = setTimeout(async () => {
|
|
2071
|
+
timers.throttleTimer = null;
|
|
2072
|
+
timers.lastThrottleCall = Date.now();
|
|
2073
|
+
const content = await result;
|
|
2074
|
+
updateDOM(content);
|
|
2075
|
+
}, remainingTime);
|
|
2076
|
+
}
|
|
2077
|
+
return result;
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
// No timing: update DOM after Promise resolves
|
|
2081
|
+
return result.then(content => {
|
|
2082
|
+
updateDOM(content);
|
|
2083
|
+
return content;
|
|
1992
2084
|
});
|
|
1993
2085
|
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
timers.
|
|
1999
|
-
|
|
2086
|
+
else {
|
|
2087
|
+
// Handle sync method
|
|
2088
|
+
if (options.debounce !== undefined && options.debounce > 0) {
|
|
2089
|
+
// Debounce: defer DOM update, return result immediately
|
|
2090
|
+
if (timers.debounceTimer) {
|
|
2091
|
+
clearTimeout(timers.debounceTimer);
|
|
2092
|
+
}
|
|
2093
|
+
timers.debounceTimer = setTimeout(() => {
|
|
2094
|
+
updateDOM(result);
|
|
2095
|
+
}, options.debounce);
|
|
2096
|
+
return result;
|
|
2000
2097
|
}
|
|
2001
|
-
|
|
2002
|
-
//
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
timers.
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2098
|
+
if (options.throttle !== undefined && options.throttle > 0) {
|
|
2099
|
+
// Throttle: handle timing for DOM updates
|
|
2100
|
+
const now = Date.now();
|
|
2101
|
+
if (timers.lastThrottleCall === 0 || now - timers.lastThrottleCall >= options.throttle) {
|
|
2102
|
+
timers.lastThrottleCall = now;
|
|
2103
|
+
updateDOM(result);
|
|
2104
|
+
}
|
|
2105
|
+
else {
|
|
2106
|
+
if (!timers.throttleTimer) {
|
|
2107
|
+
const remainingTime = options.throttle - (now - timers.lastThrottleCall);
|
|
2108
|
+
timers.throttleTimer = setTimeout(() => {
|
|
2109
|
+
timers.throttleTimer = null;
|
|
2110
|
+
timers.lastThrottleCall = Date.now();
|
|
2111
|
+
updateDOM(result);
|
|
2112
|
+
}, remainingTime);
|
|
2113
|
+
}
|
|
2010
2114
|
}
|
|
2011
|
-
|
|
2012
|
-
// The actual render will happen in the scheduled timeout
|
|
2013
|
-
return undefined;
|
|
2115
|
+
return result;
|
|
2014
2116
|
}
|
|
2117
|
+
// No timing: update DOM immediately
|
|
2118
|
+
updateDOM(result);
|
|
2119
|
+
return result;
|
|
2015
2120
|
}
|
|
2016
|
-
// No throttle/debounce - render immediately
|
|
2017
|
-
return await renderPart();
|
|
2018
2121
|
};
|
|
2019
|
-
return descriptor;
|
|
2020
2122
|
};
|
|
2021
2123
|
}
|
|
2022
2124
|
|
|
@@ -2788,7 +2890,16 @@ function Router(options) {
|
|
|
2788
2890
|
* @returns A decorator function to apply to a custom element class.
|
|
2789
2891
|
*/
|
|
2790
2892
|
function page(pageOptions) {
|
|
2791
|
-
return function (constructor) {
|
|
2893
|
+
return function (constructor, context) {
|
|
2894
|
+
// Transfer metadata from context to constructor (for new decorators)
|
|
2895
|
+
if (context.metadata && context.metadata[PROPERTIES]) {
|
|
2896
|
+
if (!constructor[PROPERTIES]) {
|
|
2897
|
+
constructor[PROPERTIES] = new Map();
|
|
2898
|
+
}
|
|
2899
|
+
for (const [key, value] of context.metadata[PROPERTIES]) {
|
|
2900
|
+
constructor[PROPERTIES].set(key, value);
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2792
2903
|
// Apply all element functionality (properties, queries, watchers, controllers, etc.)
|
|
2793
2904
|
applyElementFunctionality(constructor);
|
|
2794
2905
|
// Store transition config on constructor for later use
|
|
@@ -2828,6 +2939,7 @@ function Router(options) {
|
|
|
2828
2939
|
customElements.define(pageOptions.tag, constructor);
|
|
2829
2940
|
// Register the routes with guards and layout
|
|
2830
2941
|
pageOptions.routes.forEach(route => register(route, pageOptions.tag, pageOptions.transition, pageOptions.guards, pageOptions.layout));
|
|
2942
|
+
return constructor;
|
|
2831
2943
|
};
|
|
2832
2944
|
}
|
|
2833
2945
|
/**
|