@jsenv/navi 0.29.19 → 0.29.20
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 +34 -30
- package/dist/jsenv_navi.js.map +4 -4
- package/docs/AI_INSTRUCTIONS.md +4 -0
- package/docs/list_refresh.md +131 -0
- package/docs/resource.md +2 -0
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -12545,10 +12545,17 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
12545
12545
|
action.debug(`${action}.prerun(${stringifyForDisplay(options)})`);
|
|
12546
12546
|
return dispatchSingleAction(action, "prerun", options);
|
|
12547
12547
|
};
|
|
12548
|
+
/**
|
|
12549
|
+
* Requests the action's data. An action that is already RUNNING or
|
|
12550
|
+
* COMPLETED already has it, so the request is a no-op there: use `rerun()`
|
|
12551
|
+
* to force a fresh run ("refresh", "check now", any explicit user intent to
|
|
12552
|
+
* go back to the network).
|
|
12553
|
+
*/
|
|
12548
12554
|
const run = (options) => {
|
|
12549
12555
|
action.debug(`${action}.run(${stringifyForDisplay(options)})`);
|
|
12550
12556
|
return dispatchSingleAction(action, "run", options);
|
|
12551
12557
|
};
|
|
12558
|
+
/** Resets the action and runs it again, whatever state it is in. */
|
|
12552
12559
|
const rerun = (options) => {
|
|
12553
12560
|
action.debug(`${action}.rerun(${stringifyForDisplay(options)})`);
|
|
12554
12561
|
return dispatchSingleAction(action, "rerun", options);
|
|
@@ -17945,6 +17952,10 @@ const useExecuteAction = (
|
|
|
17945
17952
|
*/
|
|
17946
17953
|
|
|
17947
17954
|
const CLICK_TO_EXPAND_SELECTOR = "summary, [aria-expanded]";
|
|
17955
|
+
// A popup is written inside whatever opened it, but it is not part of it on
|
|
17956
|
+
// screen: a control inside a popup must not be read as a click on the region
|
|
17957
|
+
// the popup happens to be nested in.
|
|
17958
|
+
const POPUP_SELECTOR = "[navi-control='popover'], [navi-control='dialog']";
|
|
17948
17959
|
|
|
17949
17960
|
/**
|
|
17950
17961
|
* Cancels `event` when the control consumed a click that a surrounding
|
|
@@ -17970,13 +17981,29 @@ const preventClickToExpand = (element, event) => {
|
|
|
17970
17981
|
}
|
|
17971
17982
|
// From the parent: a control that opens something carries its own
|
|
17972
17983
|
// `aria-expanded` and would find itself.
|
|
17973
|
-
const clickToExpandRegion = parentElement
|
|
17984
|
+
const clickToExpandRegion = findClickToExpandRegion(parentElement);
|
|
17974
17985
|
if (!clickToExpandRegion) {
|
|
17975
17986
|
return;
|
|
17976
17987
|
}
|
|
17977
17988
|
event.preventDefault();
|
|
17978
17989
|
};
|
|
17979
17990
|
|
|
17991
|
+
const findClickToExpandRegion = (element) => {
|
|
17992
|
+
let ancestor = element;
|
|
17993
|
+
while (ancestor) {
|
|
17994
|
+
// Tested first: a popup carries `aria-expanded` of its own, so it would
|
|
17995
|
+
// otherwise pass for the region containing its own content.
|
|
17996
|
+
if (ancestor.matches(POPUP_SELECTOR)) {
|
|
17997
|
+
return null;
|
|
17998
|
+
}
|
|
17999
|
+
if (ancestor.matches(CLICK_TO_EXPAND_SELECTOR)) {
|
|
18000
|
+
return ancestor;
|
|
18001
|
+
}
|
|
18002
|
+
ancestor = ancestor.parentElement;
|
|
18003
|
+
}
|
|
18004
|
+
return null;
|
|
18005
|
+
};
|
|
18006
|
+
|
|
17980
18007
|
const clickDefaultActionIsInert = (element, event) => {
|
|
17981
18008
|
if (!isInertOnClick(element)) {
|
|
17982
18009
|
return false;
|
|
@@ -29822,37 +29849,14 @@ const getActionResultProperties = (action) => {
|
|
|
29822
29849
|
return actionResultPropertiesMap.get(action);
|
|
29823
29850
|
};
|
|
29824
29851
|
|
|
29825
|
-
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
|
|
29830
|
-
* - DELETE operation on the displayed item would display nothing in the UI (action is in IDLE state)
|
|
29831
|
-
* - PUT/PATCH operations update UI via signals, no rerun needed
|
|
29832
|
-
* - This approach minimizes unnecessary API calls
|
|
29833
|
-
*
|
|
29834
|
-
* How to handle:
|
|
29835
|
-
* - Applications can provide custom UI for deleted items (e.g., "Item not found")
|
|
29836
|
-
* - Or redirect users to appropriate pages (e.g., back to list view)
|
|
29837
|
-
*
|
|
29838
|
-
* Alternative (NOT RECOMMENDED):
|
|
29839
|
-
* - Use GET: ["DELETE"] to rerun and display 404 error received from backend
|
|
29840
|
-
* - Poor UX: users expect immediate feedback, not loading + error state
|
|
29841
|
-
*
|
|
29842
|
-
* GET_MANY: ["POST"]
|
|
29843
|
-
* - POST: New items may or may not appear in lists (depends on filters, pagination, etc.)
|
|
29844
|
-
* Backend determines visibility better than client-side logic
|
|
29845
|
-
* - DELETE: Excluded by default because:
|
|
29846
|
-
* • UI handles deletions via store signals (selectAll filters out deleted items)
|
|
29847
|
-
* • DELETE operations rarely change list content beyond item removal
|
|
29848
|
-
* • Avoids unnecessary API calls (can be overridden if needed)
|
|
29849
|
-
*/
|
|
29852
|
+
// PUT/PATCH results update the UI through the store, and DELETE resets the GET
|
|
29853
|
+
// instead of rerunning it, so a GET rerun would only ever cost a request.
|
|
29854
|
+
// A POST is the one case the client cannot decide alone: whether a new item
|
|
29855
|
+
// belongs to a list depends on filters/pagination the backend owns.
|
|
29856
|
+
// Rationale in full, plus when to override: docs/list_refresh.md
|
|
29850
29857
|
const defaultRerunOn = {
|
|
29851
29858
|
GET: false,
|
|
29852
|
-
GET_MANY: [
|
|
29853
|
-
"POST",
|
|
29854
|
-
// "DELETE"
|
|
29855
|
-
],
|
|
29859
|
+
GET_MANY: ["POST"],
|
|
29856
29860
|
};
|
|
29857
29861
|
|
|
29858
29862
|
// This handles ALL resource lifecycle logic (rerun/reset) across all resources
|