snice 7.7.0 → 7.8.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/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.js +1 -1
- package/adapters/react/calendar.d.ts +1 -0
- package/adapters/react/calendar.d.ts.map +1 -1
- package/adapters/react/calendar.js +1 -1
- package/adapters/react/calendar.js.map +1 -1
- package/adapters/react/calendar.tsx +2 -1
- package/adapters/react/matchRoute.js +1 -1
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +8 -2
- package/custom-elements.json +5 -1
- 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/README.md +2 -2
- package/dist/cdn/calendar/snice-calendar.js +26 -2
- package/dist/cdn/calendar/snice-calendar.js.map +1 -1
- package/dist/cdn/calendar/snice-calendar.min.js +2 -2
- package/dist/cdn/calendar/snice-calendar.min.js.map +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 +130 -31
- 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 +130 -31
- 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/README.md +2 -2
- package/dist/cdn/table/snice-table.esm.js +157 -33
- package/dist/cdn/table/snice-table.esm.js.map +1 -1
- package/dist/cdn/table/snice-table.esm.min.js +4 -4
- package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
- package/dist/cdn/table/snice-table.js +157 -33
- package/dist/cdn/table/snice-table.js.map +1 -1
- package/dist/cdn/table/snice-table.min.js +33 -33
- package/dist/cdn/table/snice-table.min.js.map +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/README.md +2 -2
- package/dist/cdn/tag-input/snice-tag-input.js +10 -16
- package/dist/cdn/tag-input/snice-tag-input.js.map +1 -1
- package/dist/cdn/tag-input/snice-tag-input.min.js +2 -2
- package/dist/cdn/tag-input/snice-tag-input.min.js.map +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/calendar/snice-calendar.d.ts +2 -0
- package/dist/components/calendar/snice-calendar.js +25 -1
- package/dist/components/calendar/snice-calendar.js.map +1 -1
- package/dist/components/table/snice-row.d.ts +6 -0
- package/dist/components/table/snice-row.js +11 -3
- package/dist/components/table/snice-row.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +31 -3
- package/dist/components/table/snice-table.js +89 -16
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/table-cell-presentation.d.ts +11 -0
- package/dist/components/table/table-cell-presentation.js +25 -8
- package/dist/components/table/table-cell-presentation.js.map +1 -1
- package/dist/components/table/table-export.d.ts +6 -0
- package/dist/components/table/table-export.js +11 -2
- package/dist/components/table/table-export.js.map +1 -1
- package/dist/components/table/table-master-detail.d.ts +11 -2
- package/dist/components/table/table-master-detail.js +20 -3
- package/dist/components/table/table-master-detail.js.map +1 -1
- package/dist/components/tag-input/snice-tag-input.d.ts +2 -2
- package/dist/components/tag-input/snice-tag-input.js +9 -15
- package/dist/components/tag-input/snice-tag-input.js.map +1 -1
- package/dist/index.cjs +127 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +127 -28
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +127 -28
- 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/request-response.d.ts +24 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/testing-dom.cjs +1 -1
- package/dist/testing-dom.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/docs/ai/components/calendar.md +8 -0
- package/docs/ai/components/tag-input.md +4 -0
- package/docs/ai/controllers.md +22 -6
- package/docs/components/calendar.md +24 -0
- package/docs/components/tag-input.md +6 -1
- package/docs/controllers.md +57 -6
- package/package.json +1 -1
package/dist/index.iife.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v7.
|
|
2
|
+
* snice v7.7.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.
|
|
@@ -1560,17 +1560,33 @@ var Snice = (function (exports) {
|
|
|
1560
1560
|
});
|
|
1561
1561
|
};
|
|
1562
1562
|
}
|
|
1563
|
-
//
|
|
1564
|
-
|
|
1563
|
+
// Which handler descriptors an instance has already registered, so a second
|
|
1564
|
+
// setup pass only picks up what the first one deferred.
|
|
1565
|
+
const registeredHandlers = new WeakMap();
|
|
1566
|
+
/**
|
|
1567
|
+
* Helper to setup response handlers for elements and controllers.
|
|
1568
|
+
*
|
|
1569
|
+
* Safe to call more than once for the same instance: a handler already
|
|
1570
|
+
* registered is skipped rather than double-bound.
|
|
1571
|
+
*/
|
|
1572
|
+
function setupResponseHandlers(instance, element, options) {
|
|
1565
1573
|
const handlers = instance.constructor[CHANNEL_HANDLERS];
|
|
1566
1574
|
if (!handlers)
|
|
1567
1575
|
return;
|
|
1576
|
+
const claim = options?.claim;
|
|
1577
|
+
let registered = registeredHandlers.get(instance);
|
|
1578
|
+
if (!registered) {
|
|
1579
|
+
registered = new Set();
|
|
1580
|
+
registeredHandlers.set(instance, registered);
|
|
1581
|
+
}
|
|
1568
1582
|
// Store cleanup functions
|
|
1569
1583
|
// Initialize cleanup object if needed
|
|
1570
1584
|
if (!instance[CLEANUP]) {
|
|
1571
1585
|
instance[CLEANUP] = { events: [], channels: [] };
|
|
1572
1586
|
}
|
|
1573
1587
|
for (const handler of handlers) {
|
|
1588
|
+
if (registered.has(handler))
|
|
1589
|
+
continue;
|
|
1574
1590
|
const boundMethod = handler.method.bind(instance);
|
|
1575
1591
|
const eventName = `@request/${handler.channelName}`;
|
|
1576
1592
|
// Create timing variables for debounce/throttle per handler
|
|
@@ -1654,7 +1670,10 @@ var Snice = (function (exports) {
|
|
|
1654
1670
|
// Clear the discovery timeout immediately - we found a handler
|
|
1655
1671
|
discovery.resolve();
|
|
1656
1672
|
// Call the timed responder method and handle the result
|
|
1657
|
-
|
|
1673
|
+
const answer = claim
|
|
1674
|
+
? Promise.resolve(claim()).then(() => timedMethod(payload))
|
|
1675
|
+
: Promise.resolve(timedMethod(payload));
|
|
1676
|
+
answer
|
|
1658
1677
|
.then(result => {
|
|
1659
1678
|
data.resolve(result);
|
|
1660
1679
|
})
|
|
@@ -1669,10 +1688,17 @@ var Snice = (function (exports) {
|
|
|
1669
1688
|
responseTarget = requireDaemonTarget(instance, handler.options.daemon);
|
|
1670
1689
|
}
|
|
1671
1690
|
catch (error) {
|
|
1691
|
+
// The app context reaches a controller through its host element, so it
|
|
1692
|
+
// can be unreachable while the host is still disconnected. Leave the
|
|
1693
|
+
// handler for the later pass instead of dropping it permanently.
|
|
1694
|
+
if (options?.deferUnresolvableDaemons)
|
|
1695
|
+
continue;
|
|
1672
1696
|
console.warn(`[snice/@respond] ${error.message} Responder "${handler.channelName}" skipped.`);
|
|
1697
|
+
registered.add(handler);
|
|
1673
1698
|
continue;
|
|
1674
1699
|
}
|
|
1675
1700
|
}
|
|
1701
|
+
registered.add(handler);
|
|
1676
1702
|
responseTarget.addEventListener(eventName, responseHandler);
|
|
1677
1703
|
instance[CLEANUP].channels.push(() => {
|
|
1678
1704
|
responseTarget.removeEventListener(eventName, responseHandler);
|
|
@@ -1681,6 +1707,7 @@ var Snice = (function (exports) {
|
|
|
1681
1707
|
}
|
|
1682
1708
|
// Helper to cleanup response handlers
|
|
1683
1709
|
function cleanupResponseHandlers(instance) {
|
|
1710
|
+
registeredHandlers.delete(instance);
|
|
1684
1711
|
if (instance[CLEANUP]?.channels) {
|
|
1685
1712
|
for (const cleanup of instance[CLEANUP].channels) {
|
|
1686
1713
|
cleanup();
|
|
@@ -1806,6 +1833,8 @@ var Snice = (function (exports) {
|
|
|
1806
1833
|
* Use in elements or controllers to listen to DOM events or custom events
|
|
1807
1834
|
*/
|
|
1808
1835
|
const ON_HANDLERS = getSymbol('on-handlers');
|
|
1836
|
+
// Per-decoration-site counter — see the registration identity note in `on()`.
|
|
1837
|
+
let registrationCount = 0;
|
|
1809
1838
|
/**
|
|
1810
1839
|
* @on decorator for listening to events
|
|
1811
1840
|
*
|
|
@@ -1867,18 +1896,42 @@ var Snice = (function (exports) {
|
|
|
1867
1896
|
if (!selector && opts.target) {
|
|
1868
1897
|
selector = opts.target;
|
|
1869
1898
|
}
|
|
1899
|
+
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
1900
|
+
// Registration identity — derived from EVERY decorator argument, so no
|
|
1901
|
+
// option can be forgotten here and silently collapse two distinct stacked
|
|
1902
|
+
// @on decorators into one (that is how { debounce: 300 } stacked on a plain
|
|
1903
|
+
// @on for the same event used to lose one of its two registrations).
|
|
1904
|
+
// Options are serialized generically (sorted, so literal key order doesn't
|
|
1905
|
+
// matter); values that can't be compared by value — an EventTarget or a
|
|
1906
|
+
// resolver function passed as `scope` — fall back to this decoration site's
|
|
1907
|
+
// own id, which is stable across instances but unique per @on application.
|
|
1908
|
+
const siteId = `site:${++registrationCount}`;
|
|
1909
|
+
let optionSignature = '';
|
|
1910
|
+
let hasOpaqueOption = false;
|
|
1911
|
+
for (const key of Object.keys(opts).sort()) {
|
|
1912
|
+
const value = opts[key];
|
|
1913
|
+
if (value === undefined)
|
|
1914
|
+
continue;
|
|
1915
|
+
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
|
|
1916
|
+
hasOpaqueOption = true;
|
|
1917
|
+
continue;
|
|
1918
|
+
}
|
|
1919
|
+
optionSignature += `${key}=${String(value)};`;
|
|
1920
|
+
}
|
|
1921
|
+
const argumentKey = `${eventNames.join(',')}::${selector ?? ''}::${optionSignature}${hasOpaqueOption ? `::${siteId}` : ''}`;
|
|
1870
1922
|
return function (originalMethod, context) {
|
|
1871
1923
|
const methodName = context.name;
|
|
1924
|
+
// Same decoration, same method name → same registration. A subclass that
|
|
1925
|
+
// re-declares an identically decorated method must NOT add a second
|
|
1926
|
+
// listener on top of the one its parent's initializer already registered.
|
|
1927
|
+
const registrationKey = `${methodName}::${argumentKey}`;
|
|
1872
1928
|
context.addInitializer(function () {
|
|
1873
1929
|
const constructor = this.constructor;
|
|
1874
|
-
// Dedup by registration identity
|
|
1875
|
-
//
|
|
1876
|
-
//
|
|
1877
|
-
//
|
|
1878
|
-
//
|
|
1879
|
-
// prototype chain.
|
|
1880
|
-
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
1881
|
-
const registrationKey = `${methodName}::${eventNames.join(',')}::${selector ?? ''}::daemon:${opts.daemon ?? ''}::light:${opts.light ?? ''}::shadow:${opts.shadow ?? ''}`;
|
|
1930
|
+
// Dedup by registration identity, NOT by method reference — stacked @on
|
|
1931
|
+
// decorators share one method and must each register. Use hasOwnProperty
|
|
1932
|
+
// so subclasses get their OWN Set instead of inheriting — otherwise
|
|
1933
|
+
// parent and child share state and child registrations pollute parent
|
|
1934
|
+
// (and vice versa) via the prototype chain.
|
|
1882
1935
|
if (!Object.prototype.hasOwnProperty.call(constructor, ON_METHODS)) {
|
|
1883
1936
|
constructor[ON_METHODS] = new Set();
|
|
1884
1937
|
}
|
|
@@ -2893,6 +2946,35 @@ var Snice = (function (exports) {
|
|
|
2893
2946
|
// MutationObservers are guarded from treating it as a string attachment.
|
|
2894
2947
|
restoreDirectControllerAttribute(element);
|
|
2895
2948
|
}
|
|
2949
|
+
// @respond handlers are installed before the readiness gate below, exactly
|
|
2950
|
+
// as elements install theirs in connectedCallback. A child's mount-time
|
|
2951
|
+
// @request can be the very thing keeping the host from becoming ready, so
|
|
2952
|
+
// the responder has to be reachable while `ready` is still pending. Such a
|
|
2953
|
+
// request also releases the gate — it proves the host subtree is live and
|
|
2954
|
+
// that something is blocked on this attachment — and is answered once
|
|
2955
|
+
// attach() and the remaining setup have run.
|
|
2956
|
+
//
|
|
2957
|
+
// A `@respond({ daemon })` handler resolves its target through the host's app
|
|
2958
|
+
// context, which is unreachable while the host is still disconnected (attach
|
|
2959
|
+
// before appendChild). Those are deferred here and registered by the second
|
|
2960
|
+
// pass past the gate, where they behaved correctly before this ordering.
|
|
2961
|
+
let requestClaimed = false;
|
|
2962
|
+
let releaseReadyGate;
|
|
2963
|
+
let completeAttach;
|
|
2964
|
+
let failAttach;
|
|
2965
|
+
const attached = new Promise((resolve, reject) => {
|
|
2966
|
+
completeAttach = resolve;
|
|
2967
|
+
failAttach = reject;
|
|
2968
|
+
});
|
|
2969
|
+
attached.catch(() => { }); // No requester when nothing was claimed
|
|
2970
|
+
setupResponseHandlers(controllerInstance, element, {
|
|
2971
|
+
deferUnresolvableDaemons: true,
|
|
2972
|
+
claim: () => {
|
|
2973
|
+
requestClaimed = true;
|
|
2974
|
+
releaseReadyGate?.();
|
|
2975
|
+
return attached;
|
|
2976
|
+
},
|
|
2977
|
+
});
|
|
2896
2978
|
// Normally a controller waits for its host's full initialization. The sole
|
|
2897
2979
|
// exception is attachController(host, ...) from that host's own @ready
|
|
2898
2980
|
// handler: awaiting ready there would wait on the current handler itself.
|
|
@@ -2905,6 +2987,11 @@ var Snice = (function (exports) {
|
|
|
2905
2987
|
try {
|
|
2906
2988
|
await Promise.race([
|
|
2907
2989
|
element.ready,
|
|
2990
|
+
new Promise(resolve => {
|
|
2991
|
+
if (requestClaimed)
|
|
2992
|
+
return resolve();
|
|
2993
|
+
releaseReadyGate = resolve;
|
|
2994
|
+
}),
|
|
2908
2995
|
new Promise((_, reject) => {
|
|
2909
2996
|
const onAbort = () => {
|
|
2910
2997
|
// Tagged so fire-and-forget call sites can tell this designed
|
|
@@ -2923,8 +3010,10 @@ var Snice = (function (exports) {
|
|
|
2923
3010
|
}
|
|
2924
3011
|
catch (error) {
|
|
2925
3012
|
// Attach never got past `ready` (aborted or deadline). Roll back the
|
|
2926
|
-
// stored references so a later attach does not
|
|
2927
|
-
// instance whose attach() never ran.
|
|
3013
|
+
// stored references and the early responders so a later attach does not
|
|
3014
|
+
// short-circuit against an instance whose attach() never ran.
|
|
3015
|
+
cleanupResponseHandlers(controllerInstance);
|
|
3016
|
+
failAttach(error);
|
|
2928
3017
|
if (element[CONTROLLER_KEY] === controllerInstance) {
|
|
2929
3018
|
if (typeof controller !== 'string') {
|
|
2930
3019
|
writeControllerAttribute(element, null);
|
|
@@ -2946,20 +3035,30 @@ var Snice = (function (exports) {
|
|
|
2946
3035
|
}
|
|
2947
3036
|
// Past `ready` — mark the controller so detach knows attach was actually run.
|
|
2948
3037
|
controllerInstance[CONTROLLER_ATTACHED] = true;
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
await
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
3038
|
+
try {
|
|
3039
|
+
// Run attach in the controller's scope
|
|
3040
|
+
await scope.runOperation(async () => {
|
|
3041
|
+
await controllerInstance.attach(element);
|
|
3042
|
+
});
|
|
3043
|
+
// @context has the same managed lifecycle on controllers as @on,
|
|
3044
|
+
// @observe and @respond. Catch up controllers whose async attach completed
|
|
3045
|
+
// after the Router announced the current navigation.
|
|
3046
|
+
await setupContextHandler(controllerInstance, 'microtask');
|
|
3047
|
+
// Setup @observe observers for controller
|
|
3048
|
+
setupObservers(controllerInstance, element);
|
|
3049
|
+
// Second @respond pass: registers only what the pre-gate pass deferred —
|
|
3050
|
+
// daemon-scoped responders whose app context was not resolvable yet.
|
|
3051
|
+
setupResponseHandlers(controllerInstance, element);
|
|
3052
|
+
// Setup @on event handlers for controller
|
|
3053
|
+
setupEventHandlers(controllerInstance, element);
|
|
3054
|
+
}
|
|
3055
|
+
catch (error) {
|
|
3056
|
+
// A claimed request must not wait on an attachment that never completed.
|
|
3057
|
+
failAttach(error);
|
|
3058
|
+
throw error;
|
|
3059
|
+
}
|
|
3060
|
+
// Answer whatever was claimed while the host was still becoming ready.
|
|
3061
|
+
completeAttach();
|
|
2963
3062
|
element.dispatchEvent(new CustomEvent('controller-attached', {
|
|
2964
3063
|
detail: { name: controllerName, controller: controllerInstance }
|
|
2965
3064
|
}));
|