snice 7.3.0 → 7.4.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/.agents/skills/snice/SKILL.md +12 -16
- package/README.md +5 -1
- package/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.js +1 -1
- package/adapters/react/matchRoute.js +1 -1
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +3 -1
- package/bin/project-analyzer.js +219 -6
- package/bin/snice.js +77 -13
- package/dist/app-context.d.ts +10 -10
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/action-bar/snice-action-bar.js +1 -1
- package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/availability/snice-availability.js +1 -1
- package/dist/cdn/avatar/snice-avatar.js +1 -1
- package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/binpack/snice-binpack.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/booking/snice-booking.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/button/snice-button.js +1 -1
- package/dist/cdn/calendar/snice-calendar.js +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/cart/snice-cart.js +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/code-block/snice-code-block.js +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/data-card/snice-data-card.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/estimate/snice-estimate.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/form-layout/snice-form-layout.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/grid/snice-grid.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/invoice/snice-invoice.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/key-value/snice-key-value.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/login/snice-login.js +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/markdown/snice-markdown.js +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/message-strip/snice-message-strip.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
- package/dist/cdn/popover/snice-popover.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/product-card/snice-product-card.js +1 -1
- package/dist/cdn/progress/snice-progress.js +1 -1
- package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
- package/dist/cdn/qr-code/snice-qr-code.js +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/range-slider/snice-range-slider.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/receipt/snice-receipt.js +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/runtime/README.md +2 -2
- package/dist/cdn/runtime/snice-runtime.esm.js +309 -188
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +309 -187
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
- package/dist/cdn/select/snice-select.js +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/split-button/snice-split-button.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/stat-group/snice-stat-group.js +1 -1
- package/dist/cdn/step-input/snice-step-input.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/switch/snice-switch.js +1 -1
- package/dist/cdn/table/snice-table.esm.js +1 -1
- package/dist/cdn/table/snice-table.js +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tag/snice-tag.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/time-picker/snice-time-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/user-card/snice-user-card.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/work-order/snice-work-order.js +1 -1
- package/dist/components/pagination/snice-pagination.types.d.ts +5 -0
- package/dist/context-provider.d.ts +11 -1
- package/dist/context.d.ts +5 -6
- package/dist/index.cjs +306 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +306 -185
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +306 -184
- package/dist/index.iife.js.map +1 -1
- package/dist/react/SniceProvider.js +1 -1
- package/dist/react/SniceRouter.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/matchRoute.js +1 -1
- package/dist/react/useRequestHandler.js +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/testing-dom.cjs +48 -0
- package/dist/testing-dom.cjs.map +1 -0
- package/dist/testing-dom.d.ts +23 -0
- package/dist/testing-dom.esm.js +45 -0
- package/dist/testing-dom.esm.js.map +1 -0
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/context.d.ts +8 -8
- package/dist/utils.d.ts +3 -1
- package/docs/ai/api.md +12 -1
- package/docs/ai/architecture.md +7 -3
- package/docs/ai/bindings.md +1 -1
- package/docs/ai/cli.md +22 -0
- package/docs/ai/components/badge.md +4 -0
- package/docs/ai/components/pagination.md +4 -2
- package/docs/ai/components/segmented-control.md +5 -1
- package/docs/ai/controllers.md +30 -11
- package/docs/ai/decorators.md +2 -2
- package/docs/ai/events.md +8 -2
- package/docs/ai/fetcher.md +32 -1
- package/docs/ai/lifecycle.md +4 -1
- package/docs/ai/patterns.md +9 -4
- package/docs/ai/request-response.md +20 -6
- package/docs/ai/routing.md +8 -1
- package/docs/ai/testing.md +71 -0
- package/docs/bindings.md +1 -1
- package/docs/cli.md +23 -0
- package/docs/components/badge.md +4 -0
- package/docs/components/pagination.md +8 -5
- package/docs/components/segmented-control.md +5 -1
- package/docs/controllers.md +30 -11
- package/docs/events.md +11 -2
- package/docs/fetcher.md +32 -1
- package/docs/lifecycle.md +5 -1
- package/docs/request-response.md +25 -7
- package/docs/routing.md +10 -1
- package/docs/testing.md +71 -0
- package/package.json +6 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v7.
|
|
2
|
+
* snice v7.3.0
|
|
3
3
|
* A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
|
|
4
4
|
* (c) 2024
|
|
5
5
|
* Released under the MIT License.
|
|
@@ -230,7 +230,7 @@ let contextIdCounter = 0;
|
|
|
230
230
|
*/
|
|
231
231
|
class Context {
|
|
232
232
|
constructor(context = {}, placards = [], currentRoute = '', routeParams = {}, fetcher) {
|
|
233
|
-
// Stores the SET of wrapped-method names per
|
|
233
|
+
// Stores the SET of wrapped-method names per subscriber so that classes with
|
|
234
234
|
// multiple @context() handlers register every method, not just the last one.
|
|
235
235
|
this[_a] = new WeakMap();
|
|
236
236
|
this[_b] = new Set();
|
|
@@ -254,7 +254,7 @@ class Context {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
/**
|
|
257
|
-
* Register an element to receive context updates
|
|
257
|
+
* Register an element or controller to receive context updates
|
|
258
258
|
* @internal Used by @context decorator
|
|
259
259
|
*/
|
|
260
260
|
[(_a = REGISTERED_ELEMENTS, _b = REGISTERED_ELEMENTS_SET, _c = IS_UPDATING, CONTEXT_REGISTER)](element, methodName) {
|
|
@@ -268,10 +268,10 @@ class Context {
|
|
|
268
268
|
this[REGISTERED_ELEMENTS_SET].add(element);
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
|
-
* Unregister
|
|
271
|
+
* Unregister a subscriber from context updates. With a methodName,
|
|
272
272
|
* removes only that one handler (so a `once` handler tearing itself down
|
|
273
273
|
* doesn't kill the element's other @context handlers); without one, removes
|
|
274
|
-
* the
|
|
274
|
+
* the subscriber entirely (used on disconnect/detach).
|
|
275
275
|
* @internal Used by @context decorator cleanup
|
|
276
276
|
*/
|
|
277
277
|
[CONTEXT_UNREGISTER](element, methodName) {
|
|
@@ -312,7 +312,7 @@ class Context {
|
|
|
312
312
|
return;
|
|
313
313
|
}
|
|
314
314
|
this[IS_UPDATING] = true;
|
|
315
|
-
// Notify all registered
|
|
315
|
+
// Notify all registered subscribers by calling EVERY registered method
|
|
316
316
|
// name on each. Classes with multiple @context() methods get all fired.
|
|
317
317
|
const elementsSet = this[REGISTERED_ELEMENTS_SET];
|
|
318
318
|
const elementsMap = this[REGISTERED_ELEMENTS];
|
|
@@ -334,7 +334,7 @@ class Context {
|
|
|
334
334
|
this[IS_UPDATING] = false;
|
|
335
335
|
}
|
|
336
336
|
/**
|
|
337
|
-
* Notify a specific
|
|
337
|
+
* Notify a specific subscriber of the current context state
|
|
338
338
|
* @internal Used by @context decorator
|
|
339
339
|
*/
|
|
340
340
|
[CONTEXT_NOTIFY_ELEMENT](element) {
|
|
@@ -343,7 +343,12 @@ class Context {
|
|
|
343
343
|
return;
|
|
344
344
|
for (const methodName of names) {
|
|
345
345
|
if (typeof element[methodName] === 'function') {
|
|
346
|
-
|
|
346
|
+
try {
|
|
347
|
+
element[methodName](this);
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
console.error(`Error calling @context method ${methodName}:`, error);
|
|
351
|
+
}
|
|
347
352
|
}
|
|
348
353
|
}
|
|
349
354
|
}
|
|
@@ -675,11 +680,17 @@ function invokeImmediateWatchers(instance, constructor) {
|
|
|
675
680
|
*/
|
|
676
681
|
function createDebounced(fn, delay) {
|
|
677
682
|
let timer = null;
|
|
678
|
-
|
|
683
|
+
const debounced = function (...args) {
|
|
679
684
|
if (timer !== null)
|
|
680
685
|
clearTimeout(timer);
|
|
681
686
|
timer = setTimeout(() => { fn.apply(this, args); timer = null; }, delay);
|
|
682
687
|
};
|
|
688
|
+
debounced.cancel = () => {
|
|
689
|
+
if (timer !== null)
|
|
690
|
+
clearTimeout(timer);
|
|
691
|
+
timer = null;
|
|
692
|
+
};
|
|
693
|
+
return debounced;
|
|
683
694
|
}
|
|
684
695
|
/**
|
|
685
696
|
* Create a throttled version of a function (leading + trailing edge)
|
|
@@ -1136,7 +1147,7 @@ function contextTarget(source) {
|
|
|
1136
1147
|
* boundary. Public callers use provideContext(), which also activates the
|
|
1137
1148
|
* daemon instances declared by the context.
|
|
1138
1149
|
*/
|
|
1139
|
-
function installContextProvider(root, context) {
|
|
1150
|
+
function installContextProvider(root, context, fetch, navigation) {
|
|
1140
1151
|
if (!root || typeof root.addEventListener !== 'function' || typeof root.removeEventListener !== 'function') {
|
|
1141
1152
|
throw new TypeError('provideContext() requires an EventTarget root.');
|
|
1142
1153
|
}
|
|
@@ -1148,9 +1159,26 @@ function installContextProvider(root, context) {
|
|
|
1148
1159
|
}
|
|
1149
1160
|
const listener = (event) => {
|
|
1150
1161
|
const request = event;
|
|
1151
|
-
if (!request.detail
|
|
1162
|
+
if (!request.detail)
|
|
1163
|
+
return;
|
|
1164
|
+
if (request.detail.kind === 'application') {
|
|
1165
|
+
if (request.detail.context !== undefined)
|
|
1166
|
+
return;
|
|
1167
|
+
request.detail.context = context;
|
|
1168
|
+
}
|
|
1169
|
+
else if (request.detail.kind === 'fetch') {
|
|
1170
|
+
if (!fetch || request.detail.fetch !== undefined)
|
|
1171
|
+
return;
|
|
1172
|
+
request.detail.fetch = fetch;
|
|
1173
|
+
}
|
|
1174
|
+
else if (request.detail.kind === 'navigation') {
|
|
1175
|
+
if (!navigation || request.detail.navigation !== undefined)
|
|
1176
|
+
return;
|
|
1177
|
+
request.detail.navigation = navigation;
|
|
1178
|
+
}
|
|
1179
|
+
else {
|
|
1152
1180
|
return;
|
|
1153
|
-
|
|
1181
|
+
}
|
|
1154
1182
|
request.preventDefault();
|
|
1155
1183
|
request.stopPropagation();
|
|
1156
1184
|
};
|
|
@@ -1180,7 +1208,7 @@ function getContext(source) {
|
|
|
1180
1208
|
}
|
|
1181
1209
|
const target = contextTarget(source);
|
|
1182
1210
|
if (target) {
|
|
1183
|
-
const detail = {};
|
|
1211
|
+
const detail = { kind: 'application' };
|
|
1184
1212
|
target.dispatchEvent(new CustomEvent(CONTEXT_REQUEST_EVENT, {
|
|
1185
1213
|
bubbles: true,
|
|
1186
1214
|
composed: true,
|
|
@@ -1199,6 +1227,39 @@ function getContext(source) {
|
|
|
1199
1227
|
}
|
|
1200
1228
|
return undefined;
|
|
1201
1229
|
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Resolve the fetch function supplied by the nearest context provider.
|
|
1232
|
+
* Router providers expose their ContextAwareFetcher-bound function here;
|
|
1233
|
+
* explicit providers may supply the same dependency for non-router apps and
|
|
1234
|
+
* tests without adding a reserved property to AppContext.
|
|
1235
|
+
*/
|
|
1236
|
+
function getContextFetch(source) {
|
|
1237
|
+
const target = contextTarget(source);
|
|
1238
|
+
if (!target)
|
|
1239
|
+
return undefined;
|
|
1240
|
+
const detail = { kind: 'fetch' };
|
|
1241
|
+
target.dispatchEvent(new CustomEvent(CONTEXT_REQUEST_EVENT, {
|
|
1242
|
+
bubbles: true,
|
|
1243
|
+
composed: true,
|
|
1244
|
+
cancelable: true,
|
|
1245
|
+
detail,
|
|
1246
|
+
}));
|
|
1247
|
+
return detail.fetch;
|
|
1248
|
+
}
|
|
1249
|
+
/** @internal Resolve the router Context visible to an element or controller. */
|
|
1250
|
+
function getNavigationContext(source) {
|
|
1251
|
+
const target = contextTarget(source);
|
|
1252
|
+
if (!target)
|
|
1253
|
+
return undefined;
|
|
1254
|
+
const detail = { kind: 'navigation' };
|
|
1255
|
+
target.dispatchEvent(new CustomEvent(CONTEXT_REQUEST_EVENT, {
|
|
1256
|
+
bubbles: true,
|
|
1257
|
+
composed: true,
|
|
1258
|
+
cancelable: true,
|
|
1259
|
+
detail,
|
|
1260
|
+
}));
|
|
1261
|
+
return detail.navigation;
|
|
1262
|
+
}
|
|
1202
1263
|
|
|
1203
1264
|
function isDaemonInstance(value) {
|
|
1204
1265
|
return !!value
|
|
@@ -1862,12 +1923,13 @@ function setupEventHandlers(instance, targetElement) {
|
|
|
1862
1923
|
}
|
|
1863
1924
|
// Initialize cleanup object if needed
|
|
1864
1925
|
if (!instance[CLEANUP]) {
|
|
1865
|
-
instance[CLEANUP] = { events: [], channels: [], observers: [] };
|
|
1926
|
+
instance[CLEANUP] = { events: [], eventCancels: [], channels: [], observers: [] };
|
|
1866
1927
|
}
|
|
1867
|
-
|
|
1928
|
+
if (!instance[CLEANUP].events)
|
|
1868
1929
|
instance[CLEANUP].events = [];
|
|
1869
|
-
|
|
1870
|
-
|
|
1930
|
+
if (!instance[CLEANUP].eventCancels)
|
|
1931
|
+
instance[CLEANUP].eventCancels = [];
|
|
1932
|
+
if (instance[CLEANUP].events.length > 0 || instance[CLEANUP].eventCancels.length > 0) {
|
|
1871
1933
|
// Events already set up - clean them up first to avoid duplicates
|
|
1872
1934
|
cleanupEventHandlers(instance);
|
|
1873
1935
|
}
|
|
@@ -1897,7 +1959,9 @@ function setupEventHandlers(instance, targetElement) {
|
|
|
1897
1959
|
warnIfModifierMisuse(handler.eventName);
|
|
1898
1960
|
// Apply debounce (takes precedence over throttle)
|
|
1899
1961
|
if (handlerOptions.debounce && handlerOptions.debounce > 0) {
|
|
1900
|
-
|
|
1962
|
+
const debounced = createDebounced(boundMethod, handlerOptions.debounce);
|
|
1963
|
+
instance[CLEANUP].eventCancels.push(() => debounced.cancel());
|
|
1964
|
+
boundMethod = debounced;
|
|
1901
1965
|
}
|
|
1902
1966
|
else if (handlerOptions.throttle && handlerOptions.throttle > 0) {
|
|
1903
1967
|
boundMethod = throttle$1(boundMethod, handlerOptions.throttle);
|
|
@@ -2070,12 +2134,190 @@ function setupEventHandlers(instance, targetElement) {
|
|
|
2070
2134
|
function cleanupEventHandlers(instance) {
|
|
2071
2135
|
if (!instance[CLEANUP]?.events)
|
|
2072
2136
|
return;
|
|
2137
|
+
for (const cancel of instance[CLEANUP].eventCancels ?? [])
|
|
2138
|
+
cancel();
|
|
2139
|
+
instance[CLEANUP].eventCancels = [];
|
|
2073
2140
|
for (const { target, eventName, handler, options } of instance[CLEANUP].events) {
|
|
2074
2141
|
target.removeEventListener(eventName, handler, options);
|
|
2075
2142
|
}
|
|
2076
2143
|
instance[CLEANUP].events = [];
|
|
2077
2144
|
}
|
|
2078
2145
|
|
|
2146
|
+
/**
|
|
2147
|
+
* @context decorator for receiving router context updates
|
|
2148
|
+
*/
|
|
2149
|
+
const CONTEXT_HANDLERS = getSymbol('context-handlers');
|
|
2150
|
+
/**
|
|
2151
|
+
* @context decorator for receiving router context updates
|
|
2152
|
+
*
|
|
2153
|
+
* @example
|
|
2154
|
+
* ```typescript
|
|
2155
|
+
* @element('my-layout')
|
|
2156
|
+
* class MyLayout extends HTMLElement {
|
|
2157
|
+
* @context
|
|
2158
|
+
* handleContext(ctx: Context) {
|
|
2159
|
+
* this.renderNav(ctx.placards, ctx.currentRoute);
|
|
2160
|
+
* }
|
|
2161
|
+
*
|
|
2162
|
+
* @context({ debounce: 300 })
|
|
2163
|
+
* handleContextDebounced(ctx: Context) {
|
|
2164
|
+
* // Called after 300ms of no updates
|
|
2165
|
+
* }
|
|
2166
|
+
* }
|
|
2167
|
+
* ```
|
|
2168
|
+
*/
|
|
2169
|
+
function context$1(options = {}) {
|
|
2170
|
+
return function (originalMethod, context) {
|
|
2171
|
+
const methodName = context.name;
|
|
2172
|
+
context.addInitializer(function () {
|
|
2173
|
+
const constructor = this.constructor;
|
|
2174
|
+
// hasOwnProperty guards so subclasses don't mutate parent state via
|
|
2175
|
+
// the prototype chain.
|
|
2176
|
+
if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_METHODS)) {
|
|
2177
|
+
constructor[CONTEXT_METHODS] = new Set();
|
|
2178
|
+
}
|
|
2179
|
+
if (constructor[CONTEXT_METHODS].has(originalMethod))
|
|
2180
|
+
return;
|
|
2181
|
+
constructor[CONTEXT_METHODS].add(originalMethod);
|
|
2182
|
+
if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_HANDLERS)) {
|
|
2183
|
+
const inherited = constructor[CONTEXT_HANDLERS];
|
|
2184
|
+
constructor[CONTEXT_HANDLERS] = inherited ? [...inherited] : [];
|
|
2185
|
+
}
|
|
2186
|
+
constructor[CONTEXT_HANDLERS].push({
|
|
2187
|
+
methodName,
|
|
2188
|
+
method: originalMethod,
|
|
2189
|
+
options,
|
|
2190
|
+
});
|
|
2191
|
+
});
|
|
2192
|
+
return originalMethod;
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Set up context handlers for an element or attached controller.
|
|
2197
|
+
* Called automatically by the corresponding managed lifecycle.
|
|
2198
|
+
*/
|
|
2199
|
+
function setupContextHandler(element, catchUp = false) {
|
|
2200
|
+
const handlers = element.constructor[CONTEXT_HANDLERS];
|
|
2201
|
+
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
// Get the Context instance from the router
|
|
2205
|
+
const ctx = element[CONTEXT_HANDLER] ?? getNavigationContext(element);
|
|
2206
|
+
if (!ctx) {
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
// Store the Context instance for cleanup
|
|
2210
|
+
element[NAVIGATION_CONTEXT_INSTANCE] = ctx;
|
|
2211
|
+
// A controller can finish attaching after the Router has already announced
|
|
2212
|
+
// the current navigation. Track whether an update arrives during this turn;
|
|
2213
|
+
// if none does, catch it up once from the Context's current state.
|
|
2214
|
+
let receivedContextUpdate = false;
|
|
2215
|
+
// Register each handler with the Context
|
|
2216
|
+
for (const handler of handlers) {
|
|
2217
|
+
const { methodName, method, options } = handler;
|
|
2218
|
+
const wrappedMethodName = `__wrapped_${methodName}`;
|
|
2219
|
+
// Create wrapped method with timing controls
|
|
2220
|
+
element[wrappedMethodName] = function (context) {
|
|
2221
|
+
receivedContextUpdate = true;
|
|
2222
|
+
// `once` is tracked PER method (not a single element-level flag) so
|
|
2223
|
+
// multiple once handlers on the same element each fire.
|
|
2224
|
+
const called = element[CONTEXT_CALLED] ||
|
|
2225
|
+
(element[CONTEXT_CALLED] = new Set());
|
|
2226
|
+
if (options.once && called.has(methodName)) {
|
|
2227
|
+
return;
|
|
2228
|
+
}
|
|
2229
|
+
const callMethod = () => {
|
|
2230
|
+
method.call(element, context);
|
|
2231
|
+
// Handle once option
|
|
2232
|
+
if (options.once) {
|
|
2233
|
+
called.add(methodName);
|
|
2234
|
+
// Unregister ONLY this handler, not the whole element — otherwise the
|
|
2235
|
+
// element's other @context handlers would stop receiving updates.
|
|
2236
|
+
const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2237
|
+
if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
|
|
2238
|
+
ctx[CONTEXT_UNREGISTER](element, wrappedMethodName);
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
};
|
|
2242
|
+
// Per-handler timer slot to avoid debounce/throttle handlers on the same
|
|
2243
|
+
// element overwriting each other's state.
|
|
2244
|
+
const timerSlot = element[CONTEXT_TIMER] ||
|
|
2245
|
+
(element[CONTEXT_TIMER] = {});
|
|
2246
|
+
const timerKey = methodName;
|
|
2247
|
+
if (options.debounce) {
|
|
2248
|
+
clearTimeout(timerSlot[timerKey]?.timeout);
|
|
2249
|
+
timerSlot[timerKey] = {
|
|
2250
|
+
timeout: setTimeout(callMethod, options.debounce),
|
|
2251
|
+
};
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
if (options.throttle) {
|
|
2255
|
+
const now = Date.now();
|
|
2256
|
+
const lastCall = timerSlot[timerKey]?.lastCall || 0;
|
|
2257
|
+
if (now - lastCall >= options.throttle) {
|
|
2258
|
+
timerSlot[timerKey] = { lastCall: now };
|
|
2259
|
+
callMethod();
|
|
2260
|
+
}
|
|
2261
|
+
return;
|
|
2262
|
+
}
|
|
2263
|
+
callMethod();
|
|
2264
|
+
};
|
|
2265
|
+
// Register with the Context using the wrapped method name
|
|
2266
|
+
if (typeof ctx[CONTEXT_REGISTER] === 'function') {
|
|
2267
|
+
ctx[CONTEXT_REGISTER](element, wrappedMethodName);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if (catchUp && typeof ctx[CONTEXT_NOTIFY_ELEMENT] === 'function') {
|
|
2271
|
+
return new Promise((resolve) => {
|
|
2272
|
+
const notifyIfNeeded = () => {
|
|
2273
|
+
try {
|
|
2274
|
+
if (!receivedContextUpdate
|
|
2275
|
+
&& element[NAVIGATION_CONTEXT_INSTANCE] === ctx) {
|
|
2276
|
+
ctx[CONTEXT_NOTIFY_ELEMENT](element);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
finally {
|
|
2280
|
+
resolve();
|
|
2281
|
+
}
|
|
2282
|
+
};
|
|
2283
|
+
if (catchUp === 'task')
|
|
2284
|
+
setTimeout(notifyIfNeeded, 0);
|
|
2285
|
+
else
|
|
2286
|
+
queueMicrotask(notifyIfNeeded);
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
/**
|
|
2291
|
+
* Clean up context handlers for an element or attached controller.
|
|
2292
|
+
*/
|
|
2293
|
+
function cleanupContextHandler(element) {
|
|
2294
|
+
const handlers = element.constructor[CONTEXT_HANDLERS];
|
|
2295
|
+
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
2298
|
+
// Clear any pending debounce timers (per-handler slots)
|
|
2299
|
+
const timerSlot = element[CONTEXT_TIMER];
|
|
2300
|
+
if (timerSlot && typeof timerSlot === 'object') {
|
|
2301
|
+
for (const key of Object.keys(timerSlot)) {
|
|
2302
|
+
if (timerSlot[key]?.timeout)
|
|
2303
|
+
clearTimeout(timerSlot[key].timeout);
|
|
2304
|
+
}
|
|
2305
|
+
delete element[CONTEXT_TIMER];
|
|
2306
|
+
}
|
|
2307
|
+
for (const handler of handlers) {
|
|
2308
|
+
// Clean up wrapped method
|
|
2309
|
+
const wrappedMethodName = `__wrapped_${handler.methodName}`;
|
|
2310
|
+
delete element[wrappedMethodName];
|
|
2311
|
+
}
|
|
2312
|
+
// Unregister from Context if available
|
|
2313
|
+
const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2314
|
+
if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
|
|
2315
|
+
ctx[CONTEXT_UNREGISTER](element);
|
|
2316
|
+
}
|
|
2317
|
+
delete element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2318
|
+
delete element[CONTEXT_CALLED];
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2079
2321
|
// Controller-scoped cleanup registry
|
|
2080
2322
|
class ControllerScope {
|
|
2081
2323
|
constructor() {
|
|
@@ -2409,6 +2651,10 @@ async function attachController(element, controller) {
|
|
|
2409
2651
|
await scope.runOperation(async () => {
|
|
2410
2652
|
await controllerInstance.attach(element);
|
|
2411
2653
|
});
|
|
2654
|
+
// @context has the same managed lifecycle on controllers as @on,
|
|
2655
|
+
// @observe and @respond. Catch up controllers whose async attach completed
|
|
2656
|
+
// after the Router announced the current navigation.
|
|
2657
|
+
await setupContextHandler(controllerInstance, 'microtask');
|
|
2412
2658
|
// Setup @observe observers for controller
|
|
2413
2659
|
setupObservers(controllerInstance, element);
|
|
2414
2660
|
// Setup @channel handlers for controller
|
|
@@ -2474,6 +2720,8 @@ async function detachController(element) {
|
|
|
2474
2720
|
cleanupResponseHandlers(controllerInstance);
|
|
2475
2721
|
// Cleanup @on event handlers for controller
|
|
2476
2722
|
cleanupEventHandlers(controllerInstance);
|
|
2723
|
+
// Cleanup @context handlers for controller
|
|
2724
|
+
cleanupContextHandler(controllerInstance);
|
|
2477
2725
|
// Cleanup the controller scope
|
|
2478
2726
|
if (scope) {
|
|
2479
2727
|
await scope.cleanup();
|
|
@@ -2607,158 +2855,6 @@ function useNativeElementControllers() {
|
|
|
2607
2855
|
globalThis.sniceNativeControllerObserver = observer;
|
|
2608
2856
|
}
|
|
2609
2857
|
|
|
2610
|
-
/**
|
|
2611
|
-
* @context decorator for receiving router context updates
|
|
2612
|
-
*/
|
|
2613
|
-
const CONTEXT_HANDLERS = getSymbol('context-handlers');
|
|
2614
|
-
/**
|
|
2615
|
-
* @context decorator for receiving router context updates
|
|
2616
|
-
*
|
|
2617
|
-
* @example
|
|
2618
|
-
* ```typescript
|
|
2619
|
-
* @element('my-layout')
|
|
2620
|
-
* class MyLayout extends HTMLElement {
|
|
2621
|
-
* @context
|
|
2622
|
-
* handleContext(ctx: Context) {
|
|
2623
|
-
* this.renderNav(ctx.placards, ctx.currentRoute);
|
|
2624
|
-
* }
|
|
2625
|
-
*
|
|
2626
|
-
* @context({ debounce: 300 })
|
|
2627
|
-
* handleContextDebounced(ctx: Context) {
|
|
2628
|
-
* // Called after 300ms of no updates
|
|
2629
|
-
* }
|
|
2630
|
-
* }
|
|
2631
|
-
* ```
|
|
2632
|
-
*/
|
|
2633
|
-
function context$1(options = {}) {
|
|
2634
|
-
return function (originalMethod, context) {
|
|
2635
|
-
const methodName = context.name;
|
|
2636
|
-
context.addInitializer(function () {
|
|
2637
|
-
const constructor = this.constructor;
|
|
2638
|
-
// hasOwnProperty guards so subclasses don't mutate parent state via
|
|
2639
|
-
// the prototype chain.
|
|
2640
|
-
if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_METHODS)) {
|
|
2641
|
-
constructor[CONTEXT_METHODS] = new Set();
|
|
2642
|
-
}
|
|
2643
|
-
if (constructor[CONTEXT_METHODS].has(originalMethod))
|
|
2644
|
-
return;
|
|
2645
|
-
constructor[CONTEXT_METHODS].add(originalMethod);
|
|
2646
|
-
if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_HANDLERS)) {
|
|
2647
|
-
const inherited = constructor[CONTEXT_HANDLERS];
|
|
2648
|
-
constructor[CONTEXT_HANDLERS] = inherited ? [...inherited] : [];
|
|
2649
|
-
}
|
|
2650
|
-
constructor[CONTEXT_HANDLERS].push({
|
|
2651
|
-
methodName,
|
|
2652
|
-
method: originalMethod,
|
|
2653
|
-
options,
|
|
2654
|
-
});
|
|
2655
|
-
});
|
|
2656
|
-
return originalMethod;
|
|
2657
|
-
};
|
|
2658
|
-
}
|
|
2659
|
-
/**
|
|
2660
|
-
* Setup context handler for an element instance
|
|
2661
|
-
* Called automatically during element connection
|
|
2662
|
-
*/
|
|
2663
|
-
function setupContextHandler(element) {
|
|
2664
|
-
const handlers = element.constructor[CONTEXT_HANDLERS];
|
|
2665
|
-
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
2666
|
-
return;
|
|
2667
|
-
}
|
|
2668
|
-
// Get the Context instance from the router
|
|
2669
|
-
const ctx = element[CONTEXT_HANDLER];
|
|
2670
|
-
if (!ctx) {
|
|
2671
|
-
return;
|
|
2672
|
-
}
|
|
2673
|
-
// Store the Context instance for cleanup
|
|
2674
|
-
element[NAVIGATION_CONTEXT_INSTANCE] = ctx;
|
|
2675
|
-
// Register each handler with the Context
|
|
2676
|
-
for (const handler of handlers) {
|
|
2677
|
-
const { methodName, method, options } = handler;
|
|
2678
|
-
const wrappedMethodName = `__wrapped_${methodName}`;
|
|
2679
|
-
// Create wrapped method with timing controls
|
|
2680
|
-
element[wrappedMethodName] = function (context) {
|
|
2681
|
-
// `once` is tracked PER method (not a single element-level flag) so
|
|
2682
|
-
// multiple once handlers on the same element each fire.
|
|
2683
|
-
const called = element[CONTEXT_CALLED] ||
|
|
2684
|
-
(element[CONTEXT_CALLED] = new Set());
|
|
2685
|
-
if (options.once && called.has(methodName)) {
|
|
2686
|
-
return;
|
|
2687
|
-
}
|
|
2688
|
-
const callMethod = () => {
|
|
2689
|
-
method.call(element, context);
|
|
2690
|
-
// Handle once option
|
|
2691
|
-
if (options.once) {
|
|
2692
|
-
called.add(methodName);
|
|
2693
|
-
// Unregister ONLY this handler, not the whole element — otherwise the
|
|
2694
|
-
// element's other @context handlers would stop receiving updates.
|
|
2695
|
-
const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2696
|
-
if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
|
|
2697
|
-
ctx[CONTEXT_UNREGISTER](element, wrappedMethodName);
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
};
|
|
2701
|
-
// Per-handler timer slot to avoid debounce/throttle handlers on the same
|
|
2702
|
-
// element overwriting each other's state.
|
|
2703
|
-
const timerSlot = element[CONTEXT_TIMER] ||
|
|
2704
|
-
(element[CONTEXT_TIMER] = {});
|
|
2705
|
-
const timerKey = methodName;
|
|
2706
|
-
if (options.debounce) {
|
|
2707
|
-
clearTimeout(timerSlot[timerKey]?.timeout);
|
|
2708
|
-
timerSlot[timerKey] = {
|
|
2709
|
-
timeout: setTimeout(callMethod, options.debounce),
|
|
2710
|
-
};
|
|
2711
|
-
return;
|
|
2712
|
-
}
|
|
2713
|
-
if (options.throttle) {
|
|
2714
|
-
const now = Date.now();
|
|
2715
|
-
const lastCall = timerSlot[timerKey]?.lastCall || 0;
|
|
2716
|
-
if (now - lastCall >= options.throttle) {
|
|
2717
|
-
timerSlot[timerKey] = { lastCall: now };
|
|
2718
|
-
callMethod();
|
|
2719
|
-
}
|
|
2720
|
-
return;
|
|
2721
|
-
}
|
|
2722
|
-
callMethod();
|
|
2723
|
-
};
|
|
2724
|
-
// Register with the Context using the wrapped method name
|
|
2725
|
-
if (typeof ctx[CONTEXT_REGISTER] === 'function') {
|
|
2726
|
-
ctx[CONTEXT_REGISTER](element, wrappedMethodName);
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
/**
|
|
2731
|
-
* Cleanup context handler for an element instance
|
|
2732
|
-
* Called automatically during element disconnection
|
|
2733
|
-
*/
|
|
2734
|
-
function cleanupContextHandler(element) {
|
|
2735
|
-
const handlers = element.constructor[CONTEXT_HANDLERS];
|
|
2736
|
-
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
2737
|
-
return;
|
|
2738
|
-
}
|
|
2739
|
-
// Clear any pending debounce timers (per-handler slots)
|
|
2740
|
-
const timerSlot = element[CONTEXT_TIMER];
|
|
2741
|
-
if (timerSlot && typeof timerSlot === 'object') {
|
|
2742
|
-
for (const key of Object.keys(timerSlot)) {
|
|
2743
|
-
if (timerSlot[key]?.timeout)
|
|
2744
|
-
clearTimeout(timerSlot[key].timeout);
|
|
2745
|
-
}
|
|
2746
|
-
delete element[CONTEXT_TIMER];
|
|
2747
|
-
}
|
|
2748
|
-
for (const handler of handlers) {
|
|
2749
|
-
// Clean up wrapped method
|
|
2750
|
-
const wrappedMethodName = `__wrapped_${handler.methodName}`;
|
|
2751
|
-
delete element[wrappedMethodName];
|
|
2752
|
-
}
|
|
2753
|
-
// Unregister from Context if available
|
|
2754
|
-
const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2755
|
-
if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
|
|
2756
|
-
ctx[CONTEXT_UNREGISTER](element);
|
|
2757
|
-
}
|
|
2758
|
-
delete element[NAVIGATION_CONTEXT_INSTANCE];
|
|
2759
|
-
delete element[CONTEXT_CALLED];
|
|
2760
|
-
}
|
|
2761
|
-
|
|
2762
2858
|
/**
|
|
2763
2859
|
* Template system for Snice v3.0.0
|
|
2764
2860
|
* Provides html`` and css`` tagged template processors with differential rendering
|
|
@@ -2994,14 +3090,32 @@ const NOT_COMMITTED = Symbol('not-committed');
|
|
|
2994
3090
|
function markPreUpgradePropertyBinding(element, propertyName) {
|
|
2995
3091
|
const tagName = element.localName;
|
|
2996
3092
|
if (!tagName?.includes('-'))
|
|
2997
|
-
return;
|
|
3093
|
+
return false;
|
|
2998
3094
|
const registry = element.ownerDocument?.defaultView?.customElements ?? globalThis.customElements;
|
|
2999
3095
|
if (registry?.get(tagName))
|
|
3000
|
-
return;
|
|
3096
|
+
return false;
|
|
3001
3097
|
const target = element;
|
|
3002
3098
|
if (!target[PRE_UPGRADE_PROPERTY_BINDINGS])
|
|
3003
3099
|
target[PRE_UPGRADE_PROPERTY_BINDINGS] = new Set();
|
|
3004
3100
|
target[PRE_UPGRADE_PROPERTY_BINDINGS].add(propertyName);
|
|
3101
|
+
return true;
|
|
3102
|
+
}
|
|
3103
|
+
function commitPropertyValue(element, propertyName, value) {
|
|
3104
|
+
if (!markPreUpgradePropertyBinding(element, propertyName)) {
|
|
3105
|
+
element[propertyName] = value;
|
|
3106
|
+
return;
|
|
3107
|
+
}
|
|
3108
|
+
// An undefined custom element can inherit a native IDL setter with the same
|
|
3109
|
+
// name. Assignment would invoke that setter (for example HTMLElement.role),
|
|
3110
|
+
// stringify structured data into an attribute, and leave no own value for
|
|
3111
|
+
// @property's upgrade adoption. Park every pre-upgrade binding as the own,
|
|
3112
|
+
// configurable value that the initializer already knows how to replay.
|
|
3113
|
+
Object.defineProperty(element, propertyName, {
|
|
3114
|
+
configurable: true,
|
|
3115
|
+
enumerable: true,
|
|
3116
|
+
writable: true,
|
|
3117
|
+
value,
|
|
3118
|
+
});
|
|
3005
3119
|
}
|
|
3006
3120
|
// noChange sentinel - preserves the currently committed value
|
|
3007
3121
|
const noChange = Symbol.for('snice:no-change');
|
|
@@ -4638,15 +4752,13 @@ class SpreadPart extends Part {
|
|
|
4638
4752
|
commitProperties(next) {
|
|
4639
4753
|
for (const key of Object.keys(this.committed)) {
|
|
4640
4754
|
if (!Object.prototype.hasOwnProperty.call(next, key)) {
|
|
4641
|
-
|
|
4642
|
-
this.element[key] = undefined;
|
|
4755
|
+
commitPropertyValue(this.element, key, undefined);
|
|
4643
4756
|
}
|
|
4644
4757
|
}
|
|
4645
4758
|
for (const [key, value] of Object.entries(next)) {
|
|
4646
4759
|
if (Object.is(this.committed[key], value))
|
|
4647
4760
|
continue;
|
|
4648
|
-
|
|
4649
|
-
this.element[key] = value === nothing ? undefined : value;
|
|
4761
|
+
commitPropertyValue(this.element, key, value === nothing ? undefined : value);
|
|
4650
4762
|
}
|
|
4651
4763
|
}
|
|
4652
4764
|
commitAttributes(next) {
|
|
@@ -4773,8 +4885,7 @@ class PropertyPart extends Part {
|
|
|
4773
4885
|
return;
|
|
4774
4886
|
}
|
|
4775
4887
|
this._committedValue = value;
|
|
4776
|
-
|
|
4777
|
-
this.element[this.name] = value === nothing ? undefined : value;
|
|
4888
|
+
commitPropertyValue(this.element, this.name, value === nothing ? undefined : value);
|
|
4778
4889
|
}
|
|
4779
4890
|
clear() {
|
|
4780
4891
|
// This part is being destroyed with its owning template. The element is
|
|
@@ -6806,7 +6917,7 @@ function applyElementFunctionality(constructor) {
|
|
|
6806
6917
|
// Re-establish handlers that get cleaned up on disconnect
|
|
6807
6918
|
setupEventHandlers(this, this);
|
|
6808
6919
|
setupResponseHandlers(this, this);
|
|
6809
|
-
setupContextHandler(this);
|
|
6920
|
+
void setupContextHandler(this, 'task');
|
|
6810
6921
|
// Re-establish observers that get cleaned up on disconnect
|
|
6811
6922
|
try {
|
|
6812
6923
|
setupObservers(this, this);
|
|
@@ -6931,7 +7042,7 @@ function applyElementFunctionality(constructor) {
|
|
|
6931
7042
|
}
|
|
6932
7043
|
setupEventHandlers(this, this);
|
|
6933
7044
|
setupResponseHandlers(this, this);
|
|
6934
|
-
setupContextHandler(this);
|
|
7045
|
+
void setupContextHandler(this, 'task');
|
|
6935
7046
|
this[INITIALIZED] = true;
|
|
6936
7047
|
// One-time (per class) sanity check: a @watch name with no matching
|
|
6937
7048
|
// @property never fires — surface the typo instead of staying silent.
|
|
@@ -8636,10 +8747,11 @@ function bindContextDaemons(context) {
|
|
|
8636
8747
|
*
|
|
8637
8748
|
* Daemon instances must already exist in context.daemons. The returned cleanup
|
|
8638
8749
|
* removes the provider and deactivates framework communication for daemons no
|
|
8639
|
-
* longer provided by any context.
|
|
8750
|
+
* longer provided by any context. An optional fetch function is exposed on the
|
|
8751
|
+
* same boundary through getContextFetch() without modifying the context object.
|
|
8640
8752
|
*/
|
|
8641
|
-
function
|
|
8642
|
-
const releaseProvider = installContextProvider(root, context);
|
|
8753
|
+
function provideContextBoundary(root, context, options, navigation) {
|
|
8754
|
+
const releaseProvider = installContextProvider(root, context, options.fetch, navigation);
|
|
8643
8755
|
let releaseDaemons;
|
|
8644
8756
|
try {
|
|
8645
8757
|
releaseDaemons = bindContextDaemons(context);
|
|
@@ -8657,6 +8769,15 @@ function provideContext(root, context) {
|
|
|
8657
8769
|
releaseDaemons?.();
|
|
8658
8770
|
};
|
|
8659
8771
|
}
|
|
8772
|
+
function provideContext(root, context, options = {}) {
|
|
8773
|
+
return provideContextBoundary(root, context, options);
|
|
8774
|
+
}
|
|
8775
|
+
/** @internal Router-owned provider including live navigation state. */
|
|
8776
|
+
function provideRouterContext(root, navigation) {
|
|
8777
|
+
return provideContextBoundary(root, navigation.application, {
|
|
8778
|
+
fetch: navigation.fetch,
|
|
8779
|
+
}, navigation);
|
|
8780
|
+
}
|
|
8660
8781
|
|
|
8661
8782
|
// Router historically allows a later Router instance to take over the same
|
|
8662
8783
|
// target. Track only Router-owned provider releases so that handoff remains
|
|
@@ -8700,7 +8821,7 @@ function Router(options) {
|
|
|
8700
8821
|
return;
|
|
8701
8822
|
releaseContextProvider?.();
|
|
8702
8823
|
routerContextProviders.get(target)?.();
|
|
8703
|
-
const releaseProvidedContext =
|
|
8824
|
+
const releaseProvidedContext = provideRouterContext(target, navigationContext);
|
|
8704
8825
|
let released = false;
|
|
8705
8826
|
const release = () => {
|
|
8706
8827
|
if (released)
|
|
@@ -9586,5 +9707,5 @@ if (typeof document !== 'undefined') {
|
|
|
9586
9707
|
// Supports event delegation, keyboard modifiers, debounce/throttle - see docs/events.md
|
|
9587
9708
|
// Template event syntax (@click=${handler}) is also available as an alternative.
|
|
9588
9709
|
|
|
9589
|
-
export { Context, ContextAwareFetcher, IS_CONTROLLER_INSTANCE, Router, SimpleArray, SniceElement, TransitionMode, adopted, applyElementFunctionality, attachController, classMap, clearDebounceTimers, clearMemoizeCache, clearThrottleTimers, context$1 as context, context as contextProperty, controller, createRequestHandler, css, daemon, debounce, detachController, dispatch, dispose, element, escapeAttr, escapeHtml, getBodyScrollLockCount, getContext, getController, getSymbol, html, isSafeUrl, layout, live, lockBodyScroll, memoize, moved, noChange, nothing, observe, on, once, parseDuration, property, provideContext, query, queryAll, ready, reconnect, render, repeat, request, resetOnce, respond, setDisableElementReadyWarnings, setStrictRenderErrors, state, styleMap, styles, svg, throttle, trackRenders, unlockBodyScroll, unsafeHTML, useNativeElementControllers, waitForAllCustomElements, waitForElementDefined, waitForElementReady, watch };
|
|
9710
|
+
export { Context, ContextAwareFetcher, IS_CONTROLLER_INSTANCE, Router, SimpleArray, SniceElement, TransitionMode, adopted, applyElementFunctionality, attachController, classMap, clearDebounceTimers, clearMemoizeCache, clearThrottleTimers, context$1 as context, context as contextProperty, controller, createRequestHandler, css, daemon, debounce, detachController, dispatch, dispose, element, escapeAttr, escapeHtml, getBodyScrollLockCount, getContext, getContextFetch, getController, getSymbol, html, isSafeUrl, layout, live, lockBodyScroll, memoize, moved, noChange, nothing, observe, on, once, parseDuration, property, provideContext, query, queryAll, ready, reconnect, render, repeat, request, resetOnce, respond, setDisableElementReadyWarnings, setStrictRenderErrors, state, styleMap, styles, svg, throttle, trackRenders, unlockBodyScroll, unsafeHTML, useNativeElementControllers, waitForAllCustomElements, waitForElementDefined, waitForElementReady, watch };
|
|
9590
9711
|
//# sourceMappingURL=index.esm.js.map
|