@jsenv/navi 0.29.120 → 0.29.121
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 +356 -25
- package/dist/jsenv_navi.js.map +30 -17
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -4256,6 +4256,53 @@ const findControlProxy = (el) => {
|
|
|
4256
4256
|
return firstProxy;
|
|
4257
4257
|
};
|
|
4258
4258
|
|
|
4259
|
+
/**
|
|
4260
|
+
* Typography reset shared by the surfaces a control opens: callout, popover,
|
|
4261
|
+
* dialog.
|
|
4262
|
+
*
|
|
4263
|
+
* A surface is painted on top of the page but lives in the DOM subtree of the
|
|
4264
|
+
* element it opens from, so every inherited text property of that element
|
|
4265
|
+
* reaches it. The ink an element chose for its own background — centered,
|
|
4266
|
+
* shadowed, uppercase, letter-spaced, kept on one line — arrives on paper that
|
|
4267
|
+
* has none of that background, and the caller discovers it as a symptom
|
|
4268
|
+
* (a blurred tooltip, a centered message) with nothing on screen pointing back
|
|
4269
|
+
* to the rule three elements up. A surface writes its own text, on its own
|
|
4270
|
+
* paper, in the document's terms.
|
|
4271
|
+
*
|
|
4272
|
+
* Every one of them is set to its initial value rather than `revert`: only
|
|
4273
|
+
* `color` and `background-color` are declared by the UA on a `[popover]`/
|
|
4274
|
+
* `<dialog>`, so `revert` on any of these would roll back to the inherited
|
|
4275
|
+
* value — the very thing to stop. `text-align: initial` is `start`, which
|
|
4276
|
+
* still reads the surface's own `direction`, so an RTL document keeps its
|
|
4277
|
+
* side.
|
|
4278
|
+
*
|
|
4279
|
+
* `font-family` is deliberately absent: a surface keeps the face of what
|
|
4280
|
+
* opened it, so a section written in a display font gets its tooltips in that
|
|
4281
|
+
* font. `color`, `font-size` and `font-weight` are absent too — each surface
|
|
4282
|
+
* answers those its own way (a popup writes in --navi-popup-color and follows
|
|
4283
|
+
* the size of what opened it; a callout reverts to the document's ink and
|
|
4284
|
+
* size).
|
|
4285
|
+
*
|
|
4286
|
+
* In `@layer navi` so an app that wants one of these back says so on the
|
|
4287
|
+
* surface and wins, without having to out-specify anything.
|
|
4288
|
+
*/
|
|
4289
|
+
const surfaceTextCss = /* css */ `
|
|
4290
|
+
@layer navi {
|
|
4291
|
+
.navi_callout,
|
|
4292
|
+
.navi_popover,
|
|
4293
|
+
.navi_dialog {
|
|
4294
|
+
font-style: initial;
|
|
4295
|
+
text-align: initial;
|
|
4296
|
+
text-indent: initial;
|
|
4297
|
+
text-transform: initial;
|
|
4298
|
+
text-shadow: none;
|
|
4299
|
+
white-space: initial;
|
|
4300
|
+
word-spacing: initial;
|
|
4301
|
+
letter-spacing: initial;
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
`;
|
|
4305
|
+
|
|
4259
4306
|
const CalloutContext = createContext();
|
|
4260
4307
|
const useCalloutRequestClose = () => {
|
|
4261
4308
|
return useContext(CalloutContext)?.requestClose;
|
|
@@ -4601,7 +4648,6 @@ const css$11 = /* css */`
|
|
|
4601
4648
|
box-sizing: border-box;
|
|
4602
4649
|
box-decoration-break: clone;
|
|
4603
4650
|
align-self: center;
|
|
4604
|
-
white-space: normal; /* Override in case ancetor sets nowrap */
|
|
4605
4651
|
word-break: break-word;
|
|
4606
4652
|
overflow-wrap: anywhere;
|
|
4607
4653
|
|
|
@@ -4670,6 +4716,8 @@ const css$11 = /* css */`
|
|
|
4670
4716
|
}
|
|
4671
4717
|
}
|
|
4672
4718
|
}
|
|
4719
|
+
|
|
4720
|
+
${surfaceTextCss}
|
|
4673
4721
|
`;
|
|
4674
4722
|
|
|
4675
4723
|
/**
|
|
@@ -39602,6 +39650,155 @@ const LinkCurrentIndicator = () => {
|
|
|
39602
39650
|
};
|
|
39603
39651
|
markAsOutsideTextFlow(LinkCurrentIndicator);
|
|
39604
39652
|
|
|
39653
|
+
/**
|
|
39654
|
+
* What a SlideContainer is doing, read from outside it.
|
|
39655
|
+
*
|
|
39656
|
+
* Only slides go in the box, so everything drawn AROUND the travel is written
|
|
39657
|
+
* around it — a chevron pinned to the edge of a full-screen viewer, a "3 / 8"
|
|
39658
|
+
* counter, a bar. Those need to know things the box alone knows: where one is,
|
|
39659
|
+
* and whether there is anywhere to go that way. A container driven by nobody
|
|
39660
|
+
* (no `current`, no `signal`) knows them and no one else does, so this is also
|
|
39661
|
+
* what keeps such a container usable without lifting its state out of it.
|
|
39662
|
+
*
|
|
39663
|
+
* Two channels, and they answer two different questions. The attributes the box
|
|
39664
|
+
* paints on itself are the STATE: they are there for whoever arrives later, and
|
|
39665
|
+
* CSS draws with them without any of this ([data-slide-ways~="right"]). The
|
|
39666
|
+
* event it dispatches is the NEWS: it says WHEN something changed, which no
|
|
39667
|
+
* attribute can say. So this reads the first and listens to the second.
|
|
39668
|
+
*
|
|
39669
|
+
* Not watching the DOM for it, which is the tempting third way and the wrong
|
|
39670
|
+
* one: a write is not a change. Under a finger the box writes where the picture
|
|
39671
|
+
* leans on every frame, with the same value in it more often than not, and a
|
|
39672
|
+
* watcher is woken for every one of them — while the box itself knows perfectly
|
|
39673
|
+
* well whether anything is different, and says so once.
|
|
39674
|
+
*
|
|
39675
|
+
* Nothing is told to the box in return, and nothing has to be wired: it
|
|
39676
|
+
* announces to itself and to its followers, so the thing doing the reading sits
|
|
39677
|
+
* anywhere on the page — in a fixed bar, in the frame around the box, in a
|
|
39678
|
+
* dialog holding it — and a container which never re-renders (a travel it drove
|
|
39679
|
+
* itself) is still followed.
|
|
39680
|
+
*
|
|
39681
|
+
* Reading only. Asking for a travel is what it always was: a command aimed at
|
|
39682
|
+
* the box (`commandFor={id}` + `--navi-right`, or triggerNaviCommand) — one way
|
|
39683
|
+
* of asking, wherever the asking is written.
|
|
39684
|
+
*/
|
|
39685
|
+
|
|
39686
|
+
|
|
39687
|
+
// The vocabulary the box publishes, in one place: written by slide_container,
|
|
39688
|
+
// read here and by anything styling in CSS alone
|
|
39689
|
+
// ([data-slide-ways~="right"]).
|
|
39690
|
+
const SLIDE_CURRENT_ATTRIBUTE = "data-slide-current";
|
|
39691
|
+
const SLIDE_TOWARD_ATTRIBUTE = "data-slide-travel-toward";
|
|
39692
|
+
// Where a travel WOULD go right now: there is a slide that way and the one on
|
|
39693
|
+
// screen lets go of it.
|
|
39694
|
+
const SLIDE_WAYS_ATTRIBUTE = "data-slide-ways";
|
|
39695
|
+
// …and where there is a slide that way but the one on screen holds on to the
|
|
39696
|
+
// user (preventNav, or a `required` step still unanswered). Two facts, not one:
|
|
39697
|
+
// a way out leading nowhere is not there, while a way out being held is there
|
|
39698
|
+
// and says no — which is why it stays visible and explainable rather than
|
|
39699
|
+
// hidden.
|
|
39700
|
+
const SLIDE_HELD_ATTRIBUTE = "data-slide-held";
|
|
39701
|
+
// …and the one word said out loud, on the box and on every follower of it, when
|
|
39702
|
+
// any of the above has actually changed. It carries the whole state as its
|
|
39703
|
+
// detail, so `onnavi_slide_state` on the box is a way of hearing it too.
|
|
39704
|
+
const SLIDE_STATE_EVENT = "navi_slide_state";
|
|
39705
|
+
|
|
39706
|
+
const NO_WAYS = [];
|
|
39707
|
+
const NOTHING = {
|
|
39708
|
+
current: undefined,
|
|
39709
|
+
toward: undefined,
|
|
39710
|
+
areas: NO_WAYS,
|
|
39711
|
+
ways: NO_WAYS,
|
|
39712
|
+
held: NO_WAYS,
|
|
39713
|
+
};
|
|
39714
|
+
|
|
39715
|
+
const wordsOf = (element, attribute) => {
|
|
39716
|
+
const value = element.getAttribute(attribute);
|
|
39717
|
+
return value ? value.split(" ") : NO_WAYS;
|
|
39718
|
+
};
|
|
39719
|
+
|
|
39720
|
+
const readSlideContainerState = (element) => ({
|
|
39721
|
+
current: element.getAttribute(SLIDE_CURRENT_ATTRIBUTE) ?? undefined,
|
|
39722
|
+
toward: element.getAttribute(SLIDE_TOWARD_ATTRIBUTE) ?? undefined,
|
|
39723
|
+
// In DOM order, which is the order of the walk for a line and the order the
|
|
39724
|
+
// areas were written in for a map — the same order everything else reads
|
|
39725
|
+
// (see readMap).
|
|
39726
|
+
areas: Array.from(
|
|
39727
|
+
element.querySelectorAll(":scope > [data-slide-track] > [data-slide]"),
|
|
39728
|
+
(slideElement) =>
|
|
39729
|
+
slideElement.getAttribute("data-slide-area") || slideElement.id || "",
|
|
39730
|
+
),
|
|
39731
|
+
ways: wordsOf(element, SLIDE_WAYS_ATTRIBUTE),
|
|
39732
|
+
held: wordsOf(element, SLIDE_HELD_ATTRIBUTE),
|
|
39733
|
+
});
|
|
39734
|
+
|
|
39735
|
+
const sameSlideContainerState = (a, b) =>
|
|
39736
|
+
a.current === b.current &&
|
|
39737
|
+
a.toward === b.toward &&
|
|
39738
|
+
a.areas.join(" ") === b.areas.join(" ") &&
|
|
39739
|
+
a.ways.join(" ") === b.ways.join(" ") &&
|
|
39740
|
+
a.held.join(" ") === b.held.join(" ");
|
|
39741
|
+
|
|
39742
|
+
/**
|
|
39743
|
+
* @param {string|Element|{current: Element}} [target] - the container: its id
|
|
39744
|
+
* (the way everything else addresses one), the element, or a ref to it. Not a
|
|
39745
|
+
* follower — a follower is painted for CSS to draw with, the box is what holds
|
|
39746
|
+
* the walk. Nothing at all is allowed and answers "no container": a component
|
|
39747
|
+
* that may or may not be wired to one calls this unconditionally, like every
|
|
39748
|
+
* hook.
|
|
39749
|
+
* @returns {{
|
|
39750
|
+
* current: string|undefined,
|
|
39751
|
+
* toward: string|undefined,
|
|
39752
|
+
* areas: string[],
|
|
39753
|
+
* can: (direction: "left"|"right"|"up"|"down") => boolean,
|
|
39754
|
+
* held: (direction: "left"|"right"|"up"|"down") => boolean,
|
|
39755
|
+
* }} where the box stands. `current` is the slide on screen — the one being
|
|
39756
|
+
* travelled TO while a travel plays, because that is what one is looking at;
|
|
39757
|
+
* `toward` is the other slide in the frame while the picture is between two,
|
|
39758
|
+
* and nothing at rest. `can` is "a travel that way would happen", `held` is
|
|
39759
|
+
* "there is a slide that way and this one says no" — a chevron is dead in
|
|
39760
|
+
* both cases and only the second is worth explaining.
|
|
39761
|
+
*/
|
|
39762
|
+
const useSlideContainer = (target) => {
|
|
39763
|
+
const [state, setState] = useState(NOTHING);
|
|
39764
|
+
|
|
39765
|
+
useLayoutEffect(() => {
|
|
39766
|
+
const element =
|
|
39767
|
+
typeof target === "string"
|
|
39768
|
+
? document.getElementById(target)
|
|
39769
|
+
: target && "current" in target
|
|
39770
|
+
? target.current
|
|
39771
|
+
: target;
|
|
39772
|
+
if (!element) {
|
|
39773
|
+
setState(NOTHING);
|
|
39774
|
+
return undefined;
|
|
39775
|
+
}
|
|
39776
|
+
// Read off the DOM rather than taken from the event's detail, even though
|
|
39777
|
+
// the two say the same thing: the first read has no event to take it from
|
|
39778
|
+
// (the box was already standing somewhere when this mounted), and one way
|
|
39779
|
+
// of reading is one thing that can be wrong.
|
|
39780
|
+
const read = () => {
|
|
39781
|
+
const nextState = readSlideContainerState(element);
|
|
39782
|
+
setState((previous) =>
|
|
39783
|
+
sameSlideContainerState(previous, nextState) ? previous : nextState,
|
|
39784
|
+
);
|
|
39785
|
+
};
|
|
39786
|
+
read();
|
|
39787
|
+
element.addEventListener(SLIDE_STATE_EVENT, read);
|
|
39788
|
+
return () => {
|
|
39789
|
+
element.removeEventListener(SLIDE_STATE_EVENT, read);
|
|
39790
|
+
};
|
|
39791
|
+
}, [target]);
|
|
39792
|
+
|
|
39793
|
+
return {
|
|
39794
|
+
current: state.current,
|
|
39795
|
+
toward: state.toward,
|
|
39796
|
+
areas: state.areas,
|
|
39797
|
+
can: (direction) => state.ways.includes(direction),
|
|
39798
|
+
held: (direction) => state.held.includes(direction),
|
|
39799
|
+
};
|
|
39800
|
+
};
|
|
39801
|
+
|
|
39605
39802
|
installImportMetaCssBuild(import.meta);/**
|
|
39606
39803
|
* TabList component with support for horizontal and vertical layouts
|
|
39607
39804
|
* https://dribbble.com/search/tabs
|
|
@@ -40000,19 +40197,17 @@ const Nav = ({
|
|
|
40000
40197
|
}
|
|
40001
40198
|
slideContainerElementRef.current = containerElement;
|
|
40002
40199
|
const readContainer = () => {
|
|
40003
|
-
setCurrentSlideArea(containerElement.getAttribute(
|
|
40200
|
+
setCurrentSlideArea(containerElement.getAttribute(SLIDE_CURRENT_ATTRIBUTE) ?? undefined);
|
|
40004
40201
|
paintIndicatorGeometryRef.current();
|
|
40005
40202
|
};
|
|
40006
40203
|
readContainer();
|
|
40007
|
-
//
|
|
40008
|
-
//
|
|
40009
|
-
//
|
|
40010
|
-
// rather than
|
|
40011
|
-
|
|
40012
|
-
|
|
40013
|
-
|
|
40014
|
-
attributeFilter: ["data-slide-current", "data-slide-travel-toward"]
|
|
40015
|
-
});
|
|
40204
|
+
// Where one is and what the picture leans on are written on the container,
|
|
40205
|
+
// and the container says out loud when either has changed: this row is not
|
|
40206
|
+
// in the box (it sits above it, in a fixed bar, anywhere), so it reads the
|
|
40207
|
+
// first and listens to the second. Listening rather than watching the DOM
|
|
40208
|
+
// because a write is not a change — the attribute the trait follows is
|
|
40209
|
+
// written on every frame of a gesture with the same value in it.
|
|
40210
|
+
containerElement.addEventListener(SLIDE_STATE_EVENT, readContainer);
|
|
40016
40211
|
// A row whose tabs changed width — a badge count, a font that just
|
|
40017
40212
|
// arrived, a window resized — is measured again: what was written is
|
|
40018
40213
|
// pixels, and pixels go stale.
|
|
@@ -40021,7 +40216,7 @@ const Nav = ({
|
|
|
40021
40216
|
});
|
|
40022
40217
|
sizeObserver.observe(navRef.current);
|
|
40023
40218
|
return () => {
|
|
40024
|
-
|
|
40219
|
+
containerElement.removeEventListener(SLIDE_STATE_EVENT, readContainer);
|
|
40025
40220
|
sizeObserver.disconnect();
|
|
40026
40221
|
slideContainerElementRef.current = null;
|
|
40027
40222
|
};
|
|
@@ -49916,6 +50111,13 @@ const readArea = slideElement => slideElement.getAttribute("data-slide-area") ||
|
|
|
49916
50111
|
* screens are steps rather than places — so the keys keep the meaning the
|
|
49917
50112
|
* content gives them, and travelling stays something one asks for (a button,
|
|
49918
50113
|
* a command).
|
|
50114
|
+
* WHERE they are heard is a separate question, and it is not answered here: a
|
|
50115
|
+
* key only ever reaches what has the focus, so this box hears the ones pressed
|
|
50116
|
+
* inside it — and every follower of it hears the rest. A chevron pinned to the
|
|
50117
|
+
* edge of a full-screen surface is outside the box by necessity (only slides
|
|
50118
|
+
* go in it), so the surface says `data-slide-container-follows={id}` and the
|
|
50119
|
+
* arrows keep walking wherever the keyboard is in it. See the paragraph above
|
|
50120
|
+
* about what is drawn AROUND the travel.
|
|
49919
50121
|
* @param {boolean|"x"|"y"|"xy"} [props.travelByDrag=true] - whether a pointer
|
|
49920
50122
|
* dragging the slides travels. On by default: slides side by side are
|
|
49921
50123
|
* something one expects to push around with a thumb. Off where the gesture
|
|
@@ -50236,7 +50438,7 @@ const SlideContainer = ({
|
|
|
50236
50438
|
// there is nothing else for it to read — a slide the container holds by
|
|
50237
50439
|
// itself is known to no one else.
|
|
50238
50440
|
const paintCurrentArea = area => {
|
|
50239
|
-
containerRef.current?.setAttribute(
|
|
50441
|
+
containerRef.current?.setAttribute(SLIDE_CURRENT_ATTRIBUTE, area);
|
|
50240
50442
|
};
|
|
50241
50443
|
const markAnswered = area => {
|
|
50242
50444
|
const order = readMap().slideElements.map(readArea);
|
|
@@ -50559,6 +50761,14 @@ const SlideContainer = ({
|
|
|
50559
50761
|
if (!stageRef.current) {
|
|
50560
50762
|
drawnAreaRef.current = currentArea;
|
|
50561
50763
|
}
|
|
50764
|
+
// Said last, and after data-current has been written: what a travel would do
|
|
50765
|
+
// is read off the map from the slide that is now current, and off the locks
|
|
50766
|
+
// that slide is wearing in this very commit.
|
|
50767
|
+
paintWays(currentElement);
|
|
50768
|
+
// …and once everything this commit had to write is written, the box says so
|
|
50769
|
+
// — a single announcement for a render that may have changed several of the
|
|
50770
|
+
// facts at once.
|
|
50771
|
+
announceState();
|
|
50562
50772
|
// The finger has the last word: everything above drew the map at rest, and
|
|
50563
50773
|
// where the track actually is right now is where the gesture put it.
|
|
50564
50774
|
paintDrag();
|
|
@@ -51086,11 +51296,94 @@ const SlideContainer = ({
|
|
|
51086
51296
|
const paintTravelToward = area => {
|
|
51087
51297
|
for (const element of travelPainters()) {
|
|
51088
51298
|
if (area) {
|
|
51089
|
-
element.setAttribute(
|
|
51299
|
+
element.setAttribute(SLIDE_TOWARD_ATTRIBUTE, area);
|
|
51090
51300
|
} else {
|
|
51091
|
-
element.removeAttribute(
|
|
51301
|
+
element.removeAttribute(SLIDE_TOWARD_ATTRIBUTE);
|
|
51092
51302
|
}
|
|
51093
51303
|
}
|
|
51304
|
+
// The one fact that changes without a render behind it: under a finger this
|
|
51305
|
+
// is written per frame, so the announcement is left to say whether any of
|
|
51306
|
+
// those writes was a change.
|
|
51307
|
+
announceState();
|
|
51308
|
+
};
|
|
51309
|
+
|
|
51310
|
+
// What a travel would do right now, said in two lists because they are two
|
|
51311
|
+
// different facts: `ways` is where one WOULD go — there is a slide that way
|
|
51312
|
+
// and the one on screen lets go of it — and `held` is where there is a slide
|
|
51313
|
+
// that way and this one holds on to the user (preventNav, a `required` step
|
|
51314
|
+
// still unanswered). A way out leading nowhere is not there; a way out being
|
|
51315
|
+
// held is there and says no, which is why it stays visible and explainable.
|
|
51316
|
+
//
|
|
51317
|
+
// Painted rather than rendered, and on the followers too: only slides go in
|
|
51318
|
+
// this box, so the chevrons, the counters and the bars that go with it are
|
|
51319
|
+
// written AROUND it — in CSS off these attributes
|
|
51320
|
+
// ([data-slide-ways~="right"]), or through useSlideContainer, which watches
|
|
51321
|
+
// them. Nothing is told, everything is read: it is what lets them sit
|
|
51322
|
+
// anywhere, and what lets a container nobody drives still be followed.
|
|
51323
|
+
const paintWays = currentElement => {
|
|
51324
|
+
const ways = [];
|
|
51325
|
+
const held = [];
|
|
51326
|
+
for (const direction of Object.keys(DIRECTIONS)) {
|
|
51327
|
+
const {
|
|
51328
|
+
dx,
|
|
51329
|
+
dy
|
|
51330
|
+
} = DIRECTIONS[direction];
|
|
51331
|
+
if (!mapAxes?.includes(dx ? "x" : "y")) {
|
|
51332
|
+
// Not an axis this map has: a row has no up and no down, and saying so
|
|
51333
|
+
// would be saying it about every row on the page.
|
|
51334
|
+
continue;
|
|
51335
|
+
}
|
|
51336
|
+
if (!areaTowards(dx, dy)) {
|
|
51337
|
+
continue;
|
|
51338
|
+
}
|
|
51339
|
+
const forward = dx > 0 || dy > 0;
|
|
51340
|
+
const isHeld = currentElement?.hasAttribute(forward ? "data-prevent-nav-next" : "data-prevent-nav-previous");
|
|
51341
|
+
(isHeld ? held : ways).push(direction);
|
|
51342
|
+
}
|
|
51343
|
+
for (const element of travelPainters()) {
|
|
51344
|
+
if (ways.length) {
|
|
51345
|
+
element.setAttribute(SLIDE_WAYS_ATTRIBUTE, ways.join(" "));
|
|
51346
|
+
} else {
|
|
51347
|
+
element.removeAttribute(SLIDE_WAYS_ATTRIBUTE);
|
|
51348
|
+
}
|
|
51349
|
+
if (held.length) {
|
|
51350
|
+
element.setAttribute(SLIDE_HELD_ATTRIBUTE, held.join(" "));
|
|
51351
|
+
} else {
|
|
51352
|
+
element.removeAttribute(SLIDE_HELD_ATTRIBUTE);
|
|
51353
|
+
}
|
|
51354
|
+
}
|
|
51355
|
+
};
|
|
51356
|
+
|
|
51357
|
+
// The news, as opposed to the state. Everything painted above IS the state:
|
|
51358
|
+
// it is what anything arriving later reads, and what CSS draws with. What an
|
|
51359
|
+
// attribute cannot say is WHEN it changed — and watching it is the wrong way
|
|
51360
|
+
// to ask, because a write is not a change: `data-slide-travel-toward` is
|
|
51361
|
+
// written on every frame of a gesture with the same value in it, and every
|
|
51362
|
+
// watcher would be woken sixty times a second for nothing. So the box says it
|
|
51363
|
+
// itself, once, and only when something is actually different.
|
|
51364
|
+
//
|
|
51365
|
+
// Said to its followers as well as to itself, exactly as the painting is: a
|
|
51366
|
+
// frame drawn around the box hears what the box is doing without knowing its
|
|
51367
|
+
// id, and a row of tabs beside it listens on the box by id. Not bubbling, like
|
|
51368
|
+
// every other navi event — what is announced is about THIS box, and a box
|
|
51369
|
+
// inside another must not be heard as the one around it.
|
|
51370
|
+
const announcedRef = useRef(null);
|
|
51371
|
+
const announceState = () => {
|
|
51372
|
+
const containerEl = containerRef.current;
|
|
51373
|
+
if (!containerEl) {
|
|
51374
|
+
return;
|
|
51375
|
+
}
|
|
51376
|
+
const state = readSlideContainerState(containerEl);
|
|
51377
|
+
const announced = announcedRef.current;
|
|
51378
|
+
if (announced && sameSlideContainerState(announced, state)) {
|
|
51379
|
+
return;
|
|
51380
|
+
}
|
|
51381
|
+
announcedRef.current = state;
|
|
51382
|
+
for (const element of travelPainters()) {
|
|
51383
|
+
dispatchCustomEvent(element, SLIDE_STATE_EVENT, {
|
|
51384
|
+
...state
|
|
51385
|
+
});
|
|
51386
|
+
}
|
|
51094
51387
|
};
|
|
51095
51388
|
|
|
51096
51389
|
// Where the picture stands relative to the slide that is CURRENT, in boxes:
|
|
@@ -52002,7 +52295,14 @@ const SlideMove = ({
|
|
|
52002
52295
|
label
|
|
52003
52296
|
} = DIRECTIONS[direction];
|
|
52004
52297
|
const forward = dx > 0 || dy > 0;
|
|
52005
|
-
|
|
52298
|
+
// The same fact, read from wherever this way out is written. Inside a slide it
|
|
52299
|
+
// comes down as context — the slide holding the user is this button's
|
|
52300
|
+
// ancestor. Written AROUND the box (only slides go in it, so a chevron pinned
|
|
52301
|
+
// to the edge of a full-screen surface has to be), it is not, so it is read
|
|
52302
|
+
// off the box this button already names to ask for the travel: one prop, and
|
|
52303
|
+
// the way out behaves the same on either side of the box.
|
|
52304
|
+
const slides = useSlideContainer(rest.commandFor);
|
|
52305
|
+
const locked = (forward ? locks?.preventNavNext : locks?.preventNavPrevious) || slides.held(direction);
|
|
52006
52306
|
return jsx(SlideNavButton, {
|
|
52007
52307
|
command: command,
|
|
52008
52308
|
locked: locked,
|
|
@@ -54555,6 +54855,7 @@ const css$E = /* css */`
|
|
|
54555
54855
|
}
|
|
54556
54856
|
}
|
|
54557
54857
|
|
|
54858
|
+
${surfaceTextCss}
|
|
54558
54859
|
${popupCss}
|
|
54559
54860
|
`;
|
|
54560
54861
|
|
|
@@ -56052,6 +56353,7 @@ const css$D = /* css */`
|
|
|
56052
56353
|
}
|
|
56053
56354
|
}
|
|
56054
56355
|
|
|
56356
|
+
${surfaceTextCss}
|
|
56055
56357
|
${popupCss}
|
|
56056
56358
|
`;
|
|
56057
56359
|
|
|
@@ -66172,6 +66474,20 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
|
|
|
66172
66474
|
pointer-events: none;
|
|
66173
66475
|
user-select: none;
|
|
66174
66476
|
|
|
66477
|
+
/* The value the picker draws itself is the control's own text, at the
|
|
66478
|
+
control's font size: it keeps the control line, snapped to the pixel
|
|
66479
|
+
like the field around it. A caller's "ui" is the caller's own drawing
|
|
66480
|
+
of the control, and it is written on the page's line, as the number,
|
|
66481
|
+
so each text it holds keeps a line relative to its own size. The
|
|
66482
|
+
control line is a length (--navi-control-line-height), and inherited
|
|
66483
|
+
it would arrive as the control's pixels: a 14px label under an 18px
|
|
66484
|
+
picker's 23px line carries ~5px of leading above and below that no
|
|
66485
|
+
glyph occupies and nothing on screen explains. Same reason a popup
|
|
66486
|
+
takes the number — see .navi_popup in popup.jsx. */
|
|
66487
|
+
&[data-picker-facade] {
|
|
66488
|
+
line-height: var(--navi-line-height);
|
|
66489
|
+
}
|
|
66490
|
+
|
|
66175
66491
|
&[navi-placeholder] {
|
|
66176
66492
|
color: var(--picker-placeholder-color);
|
|
66177
66493
|
font-style: var(--picker-placeholder-font-style);
|
|
@@ -66311,6 +66627,16 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
|
|
|
66311
66627
|
--x-corner-bottom-left-radius: initial;
|
|
66312
66628
|
|
|
66313
66629
|
display: contents;
|
|
66630
|
+
/* What opens from a control is a page of its own, not part of that
|
|
66631
|
+
control's type scale: it is written at the control font by name,
|
|
66632
|
+
rather than by inheriting the size the picker itself is drawn at. A
|
|
66633
|
+
caller who sizes a picker to the façade it holds (so the padding, the
|
|
66634
|
+
corners and the chevron the picker draws in em land on the text the
|
|
66635
|
+
caller actually wrote) would otherwise take the popup down with it:
|
|
66636
|
+
its title, and everything in it that does not state a size of its
|
|
66637
|
+
own. Same reason the popup is written on the page's line rather than
|
|
66638
|
+
the control's — see .navi_popup in popup.jsx. */
|
|
66639
|
+
font-size: var(--navi-control-font-size);
|
|
66314
66640
|
text-align: initial; /* Don't inherit picker text align */
|
|
66315
66641
|
}
|
|
66316
66642
|
|
|
@@ -66714,6 +67040,12 @@ const PickerButton = props => {
|
|
|
66714
67040
|
}
|
|
66715
67041
|
}), variant === "headless" || ui === "default" ? null : jsx(Text, {
|
|
66716
67042
|
className: "navi_picker_value"
|
|
67043
|
+
// Tells the caller's own drawing of the control from the value
|
|
67044
|
+
// the picker draws itself, so each is written on its own line
|
|
67045
|
+
// (see .navi_picker_value in the CSS above).
|
|
67046
|
+
,
|
|
67047
|
+
|
|
67048
|
+
"data-picker-facade": ui === undefined ? undefined : ""
|
|
66717
67049
|
// A button's label is not a placeholder, however empty the
|
|
66718
67050
|
// picker behind it is.
|
|
66719
67051
|
,
|
|
@@ -78903,8 +79235,8 @@ const StepList = ({
|
|
|
78903
79235
|
}
|
|
78904
79236
|
const rootElement = rootRef.current;
|
|
78905
79237
|
const read = () => {
|
|
78906
|
-
const currentArea = containerElement.getAttribute(
|
|
78907
|
-
const towardArea = containerElement.getAttribute(
|
|
79238
|
+
const currentArea = containerElement.getAttribute(SLIDE_CURRENT_ATTRIBUTE);
|
|
79239
|
+
const towardArea = containerElement.getAttribute(SLIDE_TOWARD_ATTRIBUTE);
|
|
78908
79240
|
setContainerCurrent(currentArea ?? undefined);
|
|
78909
79241
|
const currentIdx = currentArea === null ? -1 : indexOf(currentArea);
|
|
78910
79242
|
if (currentIdx === -1) {
|
|
@@ -78928,13 +79260,12 @@ const StepList = ({
|
|
|
78928
79260
|
rootElement.style.setProperty("--step-list-pos-dx", dx);
|
|
78929
79261
|
};
|
|
78930
79262
|
read();
|
|
78931
|
-
|
|
78932
|
-
|
|
78933
|
-
|
|
78934
|
-
|
|
78935
|
-
});
|
|
79263
|
+
// Read off the container, and re-read when it says something has changed:
|
|
79264
|
+
// a write is not a change, and the attribute the halo follows is written on
|
|
79265
|
+
// every frame of a gesture with the same value in it.
|
|
79266
|
+
containerElement.addEventListener(SLIDE_STATE_EVENT, read);
|
|
78936
79267
|
return () => {
|
|
78937
|
-
|
|
79268
|
+
containerElement.removeEventListener(SLIDE_STATE_EVENT, read);
|
|
78938
79269
|
};
|
|
78939
79270
|
// width: the dots move when the room does, and the written positions are
|
|
78940
79271
|
// pixels of those dots.
|
|
@@ -79765,5 +80096,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
79765
80096
|
})
|
|
79766
80097
|
});
|
|
79767
80098
|
|
|
79768
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, 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, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, 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 };
|
|
80099
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, 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, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
79769
80100
|
//# sourceMappingURL=jsenv_navi.js.map
|