@jsenv/navi 0.29.39 → 0.29.41
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/dist/jsenv_navi.js +102 -1
- package/dist/jsenv_navi.js.map +5 -2
- package/docs/AI_INSTRUCTIONS.md +3 -2
- package/docs/actions.md +37 -0
- package/docs/control_value.md +2 -2
- package/docs/scroll.md +53 -0
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -52142,6 +52142,82 @@ const PickerNaviMinute = props => {
|
|
|
52142
52142
|
});
|
|
52143
52143
|
};
|
|
52144
52144
|
|
|
52145
|
+
/*
|
|
52146
|
+
* Who is scrolling right now, told to the DOM: while an element scrolls it
|
|
52147
|
+
* carries `navi-scrolling`, so anyone concerned reacts in CSS, without a
|
|
52148
|
+
* listener and without a subscription.
|
|
52149
|
+
*
|
|
52150
|
+
* The one this exists for is hover. A scroll moves the content under a
|
|
52151
|
+
* motionless pointer, so the browser dispatches mouseenter/mouseleave for every
|
|
52152
|
+
* element crossing the cursor — a dozen per wheel tick. Those hovers are noise:
|
|
52153
|
+
* the user asked to scroll, not to hover. Anything doing real work on hover (a
|
|
52154
|
+
* map highlight, a preview, a prefetch) then pays for that noise on the main
|
|
52155
|
+
* thread, exactly while a scroll animation is running. A rule matching
|
|
52156
|
+
* `[navi-scrolling] *` takes the rows out of hit-testing and the browser
|
|
52157
|
+
* suppresses it all, at no cost per element.
|
|
52158
|
+
*
|
|
52159
|
+
* One capturing listener on the document sees them all: "scroll" does not
|
|
52160
|
+
* bubble, but it does propagate in the capture phase.
|
|
52161
|
+
*/
|
|
52162
|
+
|
|
52163
|
+
|
|
52164
|
+
// A scroller is still moving after its last "scroll" event (momentum, smooth
|
|
52165
|
+
// scrolling, the gap between two wheel ticks), so "still scrolling" is a
|
|
52166
|
+
// timeout: long enough to bridge that gap, short enough that hover comes back
|
|
52167
|
+
// as soon as the user stops.
|
|
52168
|
+
const SCROLL_IDLE_DELAY = 120;
|
|
52169
|
+
|
|
52170
|
+
/**
|
|
52171
|
+
* True while anything in the page is being scrolled.
|
|
52172
|
+
*/
|
|
52173
|
+
const scrollActivitySignal = signal(false);
|
|
52174
|
+
|
|
52175
|
+
/**
|
|
52176
|
+
* @param {Element} [element] The scroller to ask about; any scroller when omitted.
|
|
52177
|
+
* @returns {boolean}
|
|
52178
|
+
*/
|
|
52179
|
+
const isScrolling = (element) => {
|
|
52180
|
+
if (element === undefined) {
|
|
52181
|
+
return scrollActivitySignal.peek();
|
|
52182
|
+
}
|
|
52183
|
+
return asScroller(element).hasAttribute("navi-scrolling");
|
|
52184
|
+
};
|
|
52185
|
+
|
|
52186
|
+
// The page scroll is dispatched on the document; the element carrying the
|
|
52187
|
+
// attribute is the one CSS can reach, document.scrollingElement.
|
|
52188
|
+
const asScroller = (eventTargetOrElement) => {
|
|
52189
|
+
if (eventTargetOrElement === document || eventTargetOrElement === window) {
|
|
52190
|
+
return document.scrollingElement;
|
|
52191
|
+
}
|
|
52192
|
+
return eventTargetOrElement;
|
|
52193
|
+
};
|
|
52194
|
+
|
|
52195
|
+
const idleTimeoutMap = new Map();
|
|
52196
|
+
document.addEventListener(
|
|
52197
|
+
"scroll",
|
|
52198
|
+
(e) => {
|
|
52199
|
+
const scroller = asScroller(e.target);
|
|
52200
|
+
const idleTimeout = idleTimeoutMap.get(scroller);
|
|
52201
|
+
if (idleTimeout !== undefined) {
|
|
52202
|
+
clearTimeout(idleTimeout);
|
|
52203
|
+
} else {
|
|
52204
|
+
scroller.setAttribute("navi-scrolling", "");
|
|
52205
|
+
scrollActivitySignal.value = true;
|
|
52206
|
+
}
|
|
52207
|
+
idleTimeoutMap.set(
|
|
52208
|
+
scroller,
|
|
52209
|
+
setTimeout(() => {
|
|
52210
|
+
idleTimeoutMap.delete(scroller);
|
|
52211
|
+
scroller.removeAttribute("navi-scrolling");
|
|
52212
|
+
if (idleTimeoutMap.size === 0) {
|
|
52213
|
+
scrollActivitySignal.value = false;
|
|
52214
|
+
}
|
|
52215
|
+
}, SCROLL_IDLE_DELAY),
|
|
52216
|
+
);
|
|
52217
|
+
},
|
|
52218
|
+
{ capture: true, passive: true },
|
|
52219
|
+
);
|
|
52220
|
+
|
|
52145
52221
|
const LoadingDotsSvg = () => {
|
|
52146
52222
|
return jsxs("svg", {
|
|
52147
52223
|
viewBox: "0 0 200 200",
|
|
@@ -53764,6 +53840,17 @@ const css$v = /* css */`
|
|
|
53764
53840
|
}
|
|
53765
53841
|
}
|
|
53766
53842
|
|
|
53843
|
+
/* A scroll moves the rows under a motionless pointer: the browser then
|
|
53844
|
+
fires mouseenter/mouseleave for every row crossing the cursor, and
|
|
53845
|
+
whoever reacts to hover (a highlight elsewhere, a prefetch, a map) pays
|
|
53846
|
+
for those while the scroll animation runs. Out of hit-testing, the
|
|
53847
|
+
browser suppresses them all — see utils/scroll_activity.js for who
|
|
53848
|
+
writes navi-scrolling. The scroller itself keeps its own hit-testing, so
|
|
53849
|
+
the wheel and the scrollbar go on reaching it. */
|
|
53850
|
+
&:not([navi-hover-while-scrolling]) .navi_list:is([navi-scrolling] *) {
|
|
53851
|
+
pointer-events: none;
|
|
53852
|
+
}
|
|
53853
|
+
|
|
53767
53854
|
/* Scrolling with the page means sticking to the viewport, and a FixedBar
|
|
53768
53855
|
is in front of that viewport: without the offset a sticky label lands
|
|
53769
53856
|
behind the bar. The bar publishes the room it takes (see
|
|
@@ -54239,6 +54326,7 @@ const ListUI = props => {
|
|
|
54239
54326
|
defaultScrolled = "start",
|
|
54240
54327
|
onScrolledChange,
|
|
54241
54328
|
scroller = "self",
|
|
54329
|
+
hoverWhileScrolling = false,
|
|
54242
54330
|
lockSize,
|
|
54243
54331
|
columns,
|
|
54244
54332
|
searchText,
|
|
@@ -54432,6 +54520,7 @@ const ListUI = props => {
|
|
|
54432
54520
|
popover: popover,
|
|
54433
54521
|
"data-horizontal": horizontal ? "" : undefined,
|
|
54434
54522
|
"data-scroller": getScrollerAttribute(scroller),
|
|
54523
|
+
"navi-hover-while-scrolling": hoverWhileScrolling ? "" : undefined,
|
|
54435
54524
|
"data-expand-x": expandX || expand ? "" : undefined,
|
|
54436
54525
|
"data-expand-y": expandY || expand ? "" : undefined,
|
|
54437
54526
|
expandX: expandX,
|
|
@@ -54515,6 +54604,7 @@ const ListFirstResolver = props => {
|
|
|
54515
54604
|
* defaultScrolled?: "start" | "end" | number | {id: string, offset?: number},
|
|
54516
54605
|
* onScrolledChange?: (scrolled: {id: string, index: number, offset: number}) => void,
|
|
54517
54606
|
* scroller?: "self" | "parent" | "document" | Element | {current: Element},
|
|
54607
|
+
* hoverWhileScrolling?: boolean,
|
|
54518
54608
|
* fallback?: import("ignore:preact").ComponentChildren,
|
|
54519
54609
|
* searchFallback?: import("ignore:preact").ComponentChildren,
|
|
54520
54610
|
* searchText?: string,
|
|
@@ -54609,6 +54699,17 @@ const ListFirstResolver = props => {
|
|
|
54609
54699
|
* scroll once it fills up is picked up then. When that is still not the box
|
|
54610
54700
|
* you mean, say so: `"document"`, or the element itself (a ref works) —
|
|
54611
54701
|
* nothing is guessed then.
|
|
54702
|
+
* @param {boolean} [props.hoverWhileScrolling=false]
|
|
54703
|
+
* Whether the rows still answer the pointer while the scroller they live in
|
|
54704
|
+
* is moving. They do not by default: a scroll slides the rows under a
|
|
54705
|
+
* motionless pointer, so the browser reports a hover on each of them, and
|
|
54706
|
+
* the user asked to scroll, not to hover. The cost of taking them at face
|
|
54707
|
+
* value is paid by whatever hover triggers — a highlight elsewhere in the
|
|
54708
|
+
* tree, a prefetch, a map — at the worst moment, mid-scroll.
|
|
54709
|
+
*
|
|
54710
|
+
* Pass `true` for a list whose rows must stay live under the pointer while
|
|
54711
|
+
* it scrolls. The trade of the default is the mirror one: right after a
|
|
54712
|
+
* scroll, the row under the pointer lights up only once the pointer moves.
|
|
54612
54713
|
* @param {number} [props.maxLength]
|
|
54613
54714
|
* How many items a `selectable multiple` list accepts — the same word, and
|
|
54614
54715
|
* the same behaviour, as `maxLength` on a text field: a rule the list is
|
|
@@ -70485,5 +70586,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
70485
70586
|
})
|
|
70486
70587
|
});
|
|
70487
70588
|
|
|
70488
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
70589
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
70489
70590
|
//# sourceMappingURL=jsenv_navi.js.map
|