@jsenv/navi 0.29.298 → 0.29.300

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.
@@ -48205,7 +48205,7 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
48205
48205
  * (it wears it itself) and loses the shrink under the finger, which has
48206
48206
  * nothing left to scale but the interactive area itself.
48207
48207
  */
48208
- const Button = createComponentResolver([ButtonFirstResolver, ButtonRouteResolver, ButtonCommandPropResolver, ButtonConfirmResolver, ButtonUI]);
48208
+ const Button = /*#__PURE__*/createComponentResolver([ButtonFirstResolver, ButtonRouteResolver, ButtonCommandPropResolver, ButtonConfirmResolver, ButtonUI]);
48209
48209
 
48210
48210
  installImportMetaCssBuild(import.meta);
48211
48211
  const css$O = /* css */`.navi_control_swap {
@@ -51573,7 +51573,7 @@ const InputTextualFirstResolver = props => {
51573
51573
  ...props
51574
51574
  });
51575
51575
  };
51576
- const InputTextual = createComponentResolver([InputTextualAsTextResolver, InputTextualFirstResolver, InputWithListResolver, InputWithSuggestionsResolver, InputTypeResolver, InputModeResolver, InputHeadlessResolver, InputTextualUI]);
51576
+ const InputTextual = /*#__PURE__*/createComponentResolver([InputTextualAsTextResolver, InputTextualFirstResolver, InputWithListResolver, InputWithSuggestionsResolver, InputTypeResolver, InputModeResolver, InputHeadlessResolver, InputTextualUI]);
51577
51577
  const RealInput = ({
51578
51578
  maxLength,
51579
51579
  ...domProps
@@ -61569,6 +61569,7 @@ const css$B = /* css */`.navi_picker {
61569
61569
  --popover-background-color: var(--picker-popup-background-color, var(--navi-popup-background-color));
61570
61570
  --popover-outline-width: var(--picker-outline-width);
61571
61571
  --popover-outline-color: var(--picker-outline-color);
61572
+ --popover-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
61572
61573
  --popover-max-height: var(--picker-popover-max-height);
61573
61574
  min-width: var(--picker-popover-min-width, var(--anchor-width, 0px));
61574
61575
  cursor: default;
@@ -61605,6 +61606,7 @@ const css$B = /* css */`.navi_picker {
61605
61606
  --dialog-background-color: var(--picker-popup-background-color, var(--navi-popup-background-color));
61606
61607
  --dialog-outline-width: var(--picker-outline-width);
61607
61608
  --dialog-outline-color: var(--picker-outline-color);
61609
+ --dialog-box-shadow: var(--picker-popup-box-shadow, var(--navi-popup-box-shadow));
61608
61610
  --dialog-min-width: var(--picker-dialog-min-width);
61609
61611
  --dialog-min-height: var(--picker-dialog-min-height);
61610
61612
  --dialog-max-width: var(--picker-dialog-max-width);
@@ -61789,7 +61791,10 @@ const PickerCustom = props => {
61789
61791
  // hands the popup that controller, and a controlled Dialog/Popover reads
61790
61792
  // no onOpen/onClose of its own.
61791
61793
  onOpen,
61792
- onClose
61794
+ onClose,
61795
+ // What opens the popup — the press, or an interaction navi detects
61796
+ // ("longpress", "contextmenu"…, or a list of them). See the JSDoc.
61797
+ openOn = "press"
61793
61798
  } = props;
61794
61799
  // Resolve the id the same way useControlProps does (own id > Field's id > generated id)
61795
61800
  // before computing popupId below, so two Pickers without an explicit id never collide.
@@ -61825,6 +61830,7 @@ const PickerCustom = props => {
61825
61830
  delete pickerProps.onConfirm;
61826
61831
  delete pickerProps.onOpen;
61827
61832
  delete pickerProps.onClose;
61833
+ delete pickerProps.openOn;
61828
61834
  // Read below for the popup alone; on the trigger it would land on the DOM as
61829
61835
  // an unknown attribute holding a ref object.
61830
61836
  delete pickerProps.anchor;
@@ -62222,7 +62228,29 @@ const PickerCustom = props => {
62222
62228
  // could then never form. So the picker steps back and opens on the click,
62223
62229
  // which the browser only delivers if the press stayed a press (a gesture
62224
62230
  // swallows the click it leaves behind).
62225
- const interactionsDispute = interactionsDisputeThePress(props.interactions);
62231
+ // Opening on something else than the press: the hold, the right click.
62232
+ // Declared on the picker itself, as the caller would declare their own,
62233
+ // so it is read and arbitrated like any other gesture — a swipe on the
62234
+ // same card takes the press a hold would have taken — and gated like one:
62235
+ // a read-only picker refuses it where the finger is. The press is then
62236
+ // nobody's: a tap on the card opens nothing (see the two reactions
62237
+ // below), and the keyboard keeps its own ways in (the shortcuts above).
62238
+ const openOnList = Array.isArray(openOn) ? openOn : [openOn];
62239
+ const opensOnPress = openOnList.includes("press");
62240
+ let interactions = props.interactions;
62241
+ if (!opensOnPress) {
62242
+ interactions = {
62243
+ ...interactions
62244
+ };
62245
+ for (const type of openOnList) {
62246
+ interactions[type] = e => {
62247
+ requestOpen(e);
62248
+ };
62249
+ }
62250
+ pickerProps.interactions = interactions;
62251
+ pickerProps["data-open-on"] = openOnList.join(" ");
62252
+ }
62253
+ const interactionsDispute = interactionsDisputeThePress(interactions);
62226
62254
  Object.assign(pickerProps, {
62227
62255
  eventReactionDefinitions: {
62228
62256
  mouseDown: e => {
@@ -62248,7 +62276,7 @@ const PickerCustom = props => {
62248
62276
  // because that is where such a box says what it travels by — and
62249
62277
  // asked at every press, since what the picker sits in is not the
62250
62278
  // picker's to know at mount.
62251
- if (interactionsDispute || isPressDisputedByDrag(e.target)) {
62279
+ if (!opensOnPress || interactionsDispute || isPressDisputedByDrag(e.target)) {
62252
62280
  return null;
62253
62281
  }
62254
62282
  return {
@@ -62265,6 +62293,11 @@ const PickerCustom = props => {
62265
62293
  if (isWithinPickerContent(e.target)) {
62266
62294
  return null;
62267
62295
  }
62296
+ if (!opensOnPress) {
62297
+ // Neither the tap, nor the click a hold leaves behind: the press
62298
+ // is not what opens this picker.
62299
+ return null;
62300
+ }
62268
62301
  // When a label is clicked it transfers focus to the select
62269
62302
  // in that case we want to open it (otherwise we have already opened on mousedown interaction)
62270
62303
  // And when a gesture disputes the press (see the two disputes
@@ -62345,7 +62378,12 @@ const PickerContentInsidePopup = props => {
62345
62378
  // itself, and this one does not. Popover ignores it, same as Dialog ignores
62346
62379
  // marginWithAnchor.
62347
62380
  dockedOnSmallTouchScreen,
62381
+ // Same again: the dialog takes the trigger's box as a floor (and, with
62382
+ // dialogMaxWidth="var(--anchor-width)", as a ceiling) — what keeps a card
62383
+ // its own width once lifted. Dialog's own `sizeFromAnchor`.
62384
+ dialogSizeFromAnchor,
62348
62385
  animation,
62386
+ animationDuration,
62349
62387
  // mode="callout": what the callout says about what it holds, and paints
62350
62388
  // in its border and icon — "none" for a plain tooltip (see the callout
62351
62389
  // defaults in PickerCustomResolver). And whether it wears a cross: without
@@ -62406,6 +62444,7 @@ const PickerContentInsidePopup = props => {
62406
62444
  mode: mode,
62407
62445
  layer: popupLayer,
62408
62446
  animation: animation,
62447
+ animationDuration: animationDuration,
62409
62448
  positionArea: isPopover ? positionArea ?? (popoverMode === "nearby" ? "bottom-start" : "inset(top-left)") : positionArea,
62410
62449
  marginWithAnchor: isPopover ? popoverSpacing : undefined,
62411
62450
  marginWithContainer: marginWithContainer === undefined && isPopover ? popoverSpacing : marginWithContainer,
@@ -62420,6 +62459,7 @@ const PickerContentInsidePopup = props => {
62420
62459
  expandX: isPopover ? undefined : dialogExpandX,
62421
62460
  expandY: isPopover ? undefined : dialogExpandY,
62422
62461
  dockedOnSmallTouchScreen: isPopover ? undefined : dockedOnSmallTouchScreen,
62462
+ sizeFromAnchor: isPopover ? undefined : dialogSizeFromAnchor,
62423
62463
  children: jsx(PopupModeContext.Provider, {
62424
62464
  value: mode,
62425
62465
  children: children
@@ -65110,209 +65150,6 @@ const ListFirstResolver = props => {
65110
65150
  })
65111
65151
  });
65112
65152
  };
65113
-
65114
- /**
65115
- * List — generic virtualized scroll container.
65116
- * Items must use <List.Item> to participate in tracking.
65117
- *
65118
- * @type {import("ignore:preact").FunctionComponent<{
65119
- * selectable?: boolean,
65120
- * multiple?: boolean,
65121
- * deselectable?: boolean,
65122
- * maxLength?: number,
65123
- * maxLengthGuard?: number,
65124
- * parallelGuard?: number,
65125
- * standalone?: boolean,
65126
- * action?: (value: any) => void,
65127
- * uiAction?: (value: any) => void,
65128
- * popover?: boolean,
65129
- * role?: string,
65130
- * renderBudget?: number | string,
65131
- * renderBudgetSkipCheck?: boolean,
65132
- * virtualItemSize?: number,
65133
- * onListVisibleItemsChange?: (visibleItems: any[]) => void,
65134
- * scrolled?: "start" | "end" | number | {id: string, offset?: number},
65135
- * defaultScrolled?: "start" | "end" | number | {id: string, offset?: number},
65136
- * onScrolledChange?: (scrolled: {id: string, index: number, offset: number}) => void,
65137
- * scroller?: "self" | "parent" | "document" | Element | {current: Element},
65138
- * hoverWhileScrolling?: boolean,
65139
- * fallback?: import("ignore:preact").ComponentChildren,
65140
- * searchFallback?: import("ignore:preact").ComponentChildren,
65141
- * searchText?: string,
65142
- * searchNoMatchMode?: "remove" | "invisible_and_inert" | "muted",
65143
- * loading?: boolean,
65144
- * loadingFallback?: "skeleton" | "loader" | import("ignore:preact").ComponentChildren,
65145
- * loadingSkeletonCount?: number,
65146
- * renderSkeleton?: false | ((index: number) => import("ignore:preact").ComponentChildren),
65147
- * error?: boolean | import("ignore:preact").ComponentChildren,
65148
- * separator?: boolean | import("ignore:preact").ComponentChildren,
65149
- * itemTransition?: boolean,
65150
- * lockSize?: boolean,
65151
- * horizontal?: boolean,
65152
- * spacing?: string,
65153
- * columns?: string,
65154
- * itemColumns?: string,
65155
- * alignX?: string,
65156
- * alignY?: string,
65157
- * flexWrap?: boolean,
65158
- * expandX?: boolean,
65159
- * expandY?: boolean,
65160
- * expand?: boolean,
65161
- * children?: import("ignore:preact").ComponentChildren,
65162
- * [key: string]: any,
65163
- * }>}
65164
- * @param {string} [props.columns]
65165
- * The list's own columns: a `grid-template-columns` value the ITEMS are laid
65166
- * into — a sheet of icons (`repeat(auto-fill, minmax(2.5rem, 1fr))`), a row of
65167
- * choices (`repeat(3, minmax(0, 1fr))`). Each item takes one cell, and an item
65168
- * meant to take a whole line says so for itself
65169
- * (`style={{ gridColumn: "1 / -1" }}`). Several items to a line is a shape the
65170
- * list cannot virtualize — its render window and the room it holds for the
65171
- * rows it does not draw both count one item per line — so it is for a set of
65172
- * items the caller renders whole, not for a `<List.Items>` collection.
65173
- * @param {string} [props.itemColumns]
65174
- * The columns inside an ITEM: a `grid-template-columns` value each item fills
65175
- * with its own children, a table whose cells line up down the list. Every item
65176
- * becomes a subgrid row spanning all the columns, so a column is as wide as
65177
- * the widest cell in it among the rows actually in the DOM — real column
65178
- * sizing that stays right as the window moves. Rows of a table, then, where
65179
- * `columns` above is a grid of items; the two cannot both be set.
65180
- * @param {string} [props.alignX]
65181
- * Where the items sit across the track — `alignX="center"` centres a
65182
- * horizontal list's row of items inside a list wider than they are. Together
65183
- * with `alignY`, `align` and `flexWrap`, this reaches the `<ul>` holding the
65184
- * items rather than the frame drawn around it: the frame's only child is the
65185
- * scroll box, which fills it and has nothing to arrange.
65186
- * @param {boolean} [props.flexWrap]
65187
- * Lets a horizontal list's items fall to the next line instead of running
65188
- * past the edge — a row of choices under a `maxWidth`, say. Same caveat as
65189
- * `columns` above: a line holding several items is not virtualizable.
65190
- * @param {string} [props.overflow]
65191
- * `"visible"` lets the items paint outside the list — a check in a row's
65192
- * corner, a badge crossing the edge. A list clips by default, which is what
65193
- * its rounded corners and its scroll box need, and the two cannot both be
65194
- * true: asking for visible gives up the clipping, corners included.
65195
- * @param {boolean} [props.itemTransition]
65196
- * Names each row, so a change the application wraps in
65197
- * `document.startViewTransition` is seen row by row — rows moving to their new
65198
- * place, an arriving row appearing where it lands — instead of the list
65199
- * cross-fading as a block. The rows are drawn inside the list's own picture,
65200
- * so one coming from outside the visible part of the list is cut at the list's
65201
- * edge like any other overflow. Requires nested view transition groups
65202
- * (Chrome/Edge 140+): elsewhere the rows are left unnamed and the change
65203
- * simply happens — but the browser still names the document root, so the page
65204
- * cross-fades as a whole unless the application says otherwise, which is its
65205
- * call and not the list's:
65206
- * ```css
65207
- * @supports not (view-transition-group: contain) {
65208
- * :root { view-transition-name: none; }
65209
- * }
65210
- * ```
65211
- * @param {false|((index: number) => any)} [props.renderSkeleton]
65212
- * What a row on its way looks like — a row of the shape the real ones will
65213
- * have, so nothing moves when they arrive. Used for the rows a `<List.Items>`
65214
- * stands for and does not hold yet, and for the placeholder rows drawn while
65215
- * the whole list is `loading`. Defaults to a bare `<List.Item skeleton>`.
65216
- * @param {"skeleton"|"loader"|import("ignore:preact").ComponentChildren} [props.loadingFallback="skeleton"]
65217
- * What to display in place of the items while `loading` — that is, while
65218
- * there is nothing to show at all: `"skeleton"` renders
65219
- * `loadingSkeletonCount` placeholder rows (look:
65220
- * `renderSkeleton`), `"loader"` a single centered spinner, and
65221
- * anything else is rendered as-is in a row of its own. A falsy value
65222
- * displays nothing. A list that knows how many rows it will have has no use
65223
- * for this — see `<List.Items count>`, whose not-yet-loaded rows are drawn
65224
- * as skeletons in place, one per row, virtualized like the rest.
65225
- * @param {number} [props.loadingSkeletonCount=3]
65226
- * How many placeholder rows `loadingFallback="skeleton"` draws. `0` says the
65227
- * list is already known to be empty: the empty `fallback` shows right away
65228
- * rather than an empty frame, so nothing moves when the response arrives.
65229
- * @param {"start"|"end"|number|{id: string, offset?: number}} [props.defaultScrolled="start"]
65230
- * Where the list opens, after which the user owns the scroll. `"end"` is a
65231
- * thread read backwards — the last rows are the ones to show, and the ones
65232
- * asked for first. A number opens on that row of the collection. `{id,
65233
- * offset}` — what `onScrolledChange` hands out — opens on a NAMED row,
65234
- * `offset` pixels below where the row would land on its own: the row is asked
65235
- * for by name (see the range's own `around`), then put back by MEASURING it,
65236
- * so it lands where it was even if rows were inserted before it, and whatever
65237
- * the screen it was saved on. `offset: 0` is where a `scrollIntoView()` puts
65238
- * it — in front of the fixed bar the scroller gives room for, below the
65239
- * sticky header and the group label the row lives under — so nothing of that
65240
- * room has to be restated as a number by whoever asks.
65241
- * @param {"start"|"end"|number|{id: string, offset?: number}} [props.scrolled]
65242
- * The same, but held: the list goes back there every time this changes, even
65243
- * after the user has scrolled — the caller owns where the list is (see
65244
- * `defaultScrolled` for the uncontrolled form, and `open`/`defaultOpen`
65245
- * elsewhere in navi for the same pair). When the named row turns out not to
65246
- * exist — a message deleted since — the list opens at `defaultScrolled`
65247
- * instead.
65248
- *
65249
- * In every form the list holds itself there while it is still finding out
65250
- * how many rows there are and how tall one is, and lets go the moment the
65251
- * user reaches for the list.
65252
- * @param {(scrolled: {id: string, index: number, offset: number}) => void} [props.onScrolledChange]
65253
- * Where the list is, as the user scrolls: the row at the top of the view and
65254
- * how far below the place a row lands on its own (see `defaultScrolled`) it
65255
- * starts. Keep it to come back to it
65256
- * later through `scrolled`/`defaultScrolled` — an index would not do, since
65257
- * rows get inserted while a list is being read.
65258
- * @param {"self"|"parent"|"document"|Element|{current: Element}} [props.scroller="self"]
65259
- * Which box scrolls. `"self"` gives the list a scroll box of its own;
65260
- * `"parent"` makes it virtualize against the scrollable ancestor it lives in
65261
- * (the page, a panel) — no scroll box nested inside another one, no height
65262
- * to compute.
65263
- *
65264
- * `"parent"` finds that ancestor by measuring: the nearest one whose content
65265
- * actually overflows it, the page if none does. Declaring `overflow` is not
65266
- * enough to be picked (a box with `overflow-x: auto` that grows with its
65267
- * content computes `overflow-y: auto` without ever scrolling), and the
65268
- * answer is taken again as the geometry moves, so an ancestor that starts to
65269
- * scroll once it fills up is picked up then. When that is still not the box
65270
- * you mean, say so: `"document"`, or the element itself (a ref works) —
65271
- * nothing is guessed then.
65272
- * @param {boolean} [props.hoverWhileScrolling=false]
65273
- * Whether the rows still answer the pointer while the scroller they live in
65274
- * is moving. They do not by default: a scroll slides the rows under a
65275
- * motionless pointer, so the browser reports a hover on each of them, and
65276
- * the user asked to scroll, not to hover. The cost of taking them at face
65277
- * value is paid by whatever hover triggers — a highlight elsewhere in the
65278
- * tree, a prefetch, a map — at the worst moment, mid-scroll.
65279
- *
65280
- * Pass `true` for a list whose rows must stay live under the pointer while
65281
- * it scrolls. The trade of the default is the mirror one: right after a
65282
- * scroll, the row under the pointer lights up only once the pointer moves.
65283
- * @param {boolean} [props.deselectable]
65284
- * A single-select list allowed to hold nothing: the selected row, pressed
65285
- * again, lets go. Without it the list is a radio group — a choice, once
65286
- * made, moves to another row but never goes away. A `multiple` list toggles
65287
- * its rows already.
65288
- * @param {number} [props.maxLength]
65289
- * How many items a `selectable multiple` list accepts — the same word, and
65290
- * the same behaviour, as `maxLength` on a text field: a rule the list is
65291
- * judged against, not a wall. A longer selection is allowed to exist and is
65292
- * reported as invalid, which is what lets a value coming from elsewhere (an
65293
- * API, a URL) be shown and then corrected.
65294
- * @param {number} [props.maxLengthGuard]
65295
- * The same limit, enforced as the selection is made: while the list holds as
65296
- * many items as it accepts, the ones not selected go read-only — still
65297
- * pointable, focusable and pressable, answering `"[max] max."` instead of
65298
- * taking — and `uiAction` is not called. The selected ones stay takeable
65299
- * back, so a selection that arrived too long can always be brought back
65300
- * under the limit. Implies `maxLength` for validity.
65301
- * @param {number} [props.parallelGuard=4]
65302
- * How many runs the rows may have in flight at once, for a list whose rows
65303
- * carry their own `action` (a button per row). While that many are out, every
65304
- * row that is not running goes read-only and says how many it is waiting on;
65305
- * the next press is possible again as soon as one comes back. `Infinity`
65306
- * lifts it. Counts runs, not values — `maxLengthGuard` above is the one that
65307
- * says how many things the selection may hold.
65308
- * @param {boolean} [props.standalone]
65309
- * This list answers for itself: it does not register with the control group
65310
- * or picker around it, so its selection stays out of that value and nothing
65311
- * coming down — a distributed value, a reset — reaches it. What a popup whose
65312
- * one answer is spread over several lists says, so that none of them is taken
65313
- * for the answer itself.
65314
- */
65315
- const List = createComponentResolver([ListFirstResolver, ListSelectableResolver, ListUI]);
65316
65153
  const ListContent = ({
65317
65154
  role,
65318
65155
  fallback,
@@ -67529,14 +67366,13 @@ const LIST_ITEM_STYLE_CSS_VARS = {
67529
67366
  * search-driven scroll-to-top-match behavior. `matchRanges` are [start, end]
67530
67367
  * ranges highlighted via the CSS Highlight API.
67531
67368
  */
67532
- const ListItem = createComponentResolver([ListItemFirstResolver, ListItemRowResolver, ListItemSkeletonResolver, ListItemSelectableResolver, ListItemHeaderOrFooterResolver, ListItemPresentationResolver, ListItemUI],
67369
+ const ListItem = /*#__PURE__*/createComponentResolver([ListItemFirstResolver, ListItemRowResolver, ListItemSkeletonResolver, ListItemSelectableResolver, ListItemHeaderOrFooterResolver, ListItemPresentationResolver, ListItemUI],
67533
67370
  // Rendered by the hundred, and almost always with the same primitive props:
67534
67371
  // a selection change re-renders the list, and every row but two has nothing
67535
67372
  // to change.
67536
67373
  {
67537
67374
  pure: true
67538
67375
  });
67539
- List.Item = ListItem;
67540
67376
 
67541
67377
  // Everything the list knows about the collection while its children are being
67542
67378
  // rendered: how many rows it has in total, which of them are actually held, and
@@ -68296,7 +68132,6 @@ const ListItems = ({
68296
68132
  }
68297
68133
  return rows;
68298
68134
  };
68299
- List.Items = ListItems;
68300
68135
 
68301
68136
  // What is drawn where rows were asked for and never came: the sentence and the
68302
68137
  // way out, in the row itself — the rest of the list is fine, so replacing all
@@ -68897,6 +68732,219 @@ const resolveSeparatorVnode = (separator, gapIndex) => {
68897
68732
  }
68898
68733
  return separator;
68899
68734
  };
68735
+ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, ListSelectableResolver, ListUI]);
68736
+
68737
+ // Declared last because Item and Items are consts defined above, and they are
68738
+ // folded into the declaration rather than written onto List afterwards
68739
+ // (`List.Item = ListItem`): List is what createComponentResolver returns, an
68740
+ // object a bundler cannot see through, so a property assigned to it later is a
68741
+ // side effect it has to keep — and with it List, its rows and everything they
68742
+ // import, in a bundle that never renders a list. See Picker for the same shape.
68743
+ /**
68744
+ * List — generic virtualized scroll container.
68745
+ * Items must use <List.Item> to participate in tracking.
68746
+ *
68747
+ * @type {import("ignore:preact").FunctionComponent<{
68748
+ * selectable?: boolean,
68749
+ * multiple?: boolean,
68750
+ * deselectable?: boolean,
68751
+ * maxLength?: number,
68752
+ * maxLengthGuard?: number,
68753
+ * parallelGuard?: number,
68754
+ * standalone?: boolean,
68755
+ * action?: (value: any) => void,
68756
+ * uiAction?: (value: any) => void,
68757
+ * popover?: boolean,
68758
+ * role?: string,
68759
+ * renderBudget?: number | string,
68760
+ * renderBudgetSkipCheck?: boolean,
68761
+ * virtualItemSize?: number,
68762
+ * onListVisibleItemsChange?: (visibleItems: any[]) => void,
68763
+ * scrolled?: "start" | "end" | number | {id: string, offset?: number},
68764
+ * defaultScrolled?: "start" | "end" | number | {id: string, offset?: number},
68765
+ * onScrolledChange?: (scrolled: {id: string, index: number, offset: number}) => void,
68766
+ * scroller?: "self" | "parent" | "document" | Element | {current: Element},
68767
+ * hoverWhileScrolling?: boolean,
68768
+ * fallback?: import("ignore:preact").ComponentChildren,
68769
+ * searchFallback?: import("ignore:preact").ComponentChildren,
68770
+ * searchText?: string,
68771
+ * searchNoMatchMode?: "remove" | "invisible_and_inert" | "muted",
68772
+ * loading?: boolean,
68773
+ * loadingFallback?: "skeleton" | "loader" | import("ignore:preact").ComponentChildren,
68774
+ * loadingSkeletonCount?: number,
68775
+ * renderSkeleton?: false | ((index: number) => import("ignore:preact").ComponentChildren),
68776
+ * error?: boolean | import("ignore:preact").ComponentChildren,
68777
+ * separator?: boolean | import("ignore:preact").ComponentChildren,
68778
+ * itemTransition?: boolean,
68779
+ * lockSize?: boolean,
68780
+ * horizontal?: boolean,
68781
+ * spacing?: string,
68782
+ * columns?: string,
68783
+ * itemColumns?: string,
68784
+ * alignX?: string,
68785
+ * alignY?: string,
68786
+ * flexWrap?: boolean,
68787
+ * expandX?: boolean,
68788
+ * expandY?: boolean,
68789
+ * expand?: boolean,
68790
+ * children?: import("ignore:preact").ComponentChildren,
68791
+ * [key: string]: any,
68792
+ * }>}
68793
+ * @param {string} [props.columns]
68794
+ * The list's own columns: a `grid-template-columns` value the ITEMS are laid
68795
+ * into — a sheet of icons (`repeat(auto-fill, minmax(2.5rem, 1fr))`), a row of
68796
+ * choices (`repeat(3, minmax(0, 1fr))`). Each item takes one cell, and an item
68797
+ * meant to take a whole line says so for itself
68798
+ * (`style={{ gridColumn: "1 / -1" }}`). Several items to a line is a shape the
68799
+ * list cannot virtualize — its render window and the room it holds for the
68800
+ * rows it does not draw both count one item per line — so it is for a set of
68801
+ * items the caller renders whole, not for a `<List.Items>` collection.
68802
+ * @param {string} [props.itemColumns]
68803
+ * The columns inside an ITEM: a `grid-template-columns` value each item fills
68804
+ * with its own children, a table whose cells line up down the list. Every item
68805
+ * becomes a subgrid row spanning all the columns, so a column is as wide as
68806
+ * the widest cell in it among the rows actually in the DOM — real column
68807
+ * sizing that stays right as the window moves. Rows of a table, then, where
68808
+ * `columns` above is a grid of items; the two cannot both be set.
68809
+ * @param {string} [props.alignX]
68810
+ * Where the items sit across the track — `alignX="center"` centres a
68811
+ * horizontal list's row of items inside a list wider than they are. Together
68812
+ * with `alignY`, `align` and `flexWrap`, this reaches the `<ul>` holding the
68813
+ * items rather than the frame drawn around it: the frame's only child is the
68814
+ * scroll box, which fills it and has nothing to arrange.
68815
+ * @param {boolean} [props.flexWrap]
68816
+ * Lets a horizontal list's items fall to the next line instead of running
68817
+ * past the edge — a row of choices under a `maxWidth`, say. Same caveat as
68818
+ * `columns` above: a line holding several items is not virtualizable.
68819
+ * @param {string} [props.overflow]
68820
+ * `"visible"` lets the items paint outside the list — a check in a row's
68821
+ * corner, a badge crossing the edge. A list clips by default, which is what
68822
+ * its rounded corners and its scroll box need, and the two cannot both be
68823
+ * true: asking for visible gives up the clipping, corners included.
68824
+ * @param {boolean} [props.itemTransition]
68825
+ * Names each row, so a change the application wraps in
68826
+ * `document.startViewTransition` is seen row by row — rows moving to their new
68827
+ * place, an arriving row appearing where it lands — instead of the list
68828
+ * cross-fading as a block. The rows are drawn inside the list's own picture,
68829
+ * so one coming from outside the visible part of the list is cut at the list's
68830
+ * edge like any other overflow. Requires nested view transition groups
68831
+ * (Chrome/Edge 140+): elsewhere the rows are left unnamed and the change
68832
+ * simply happens — but the browser still names the document root, so the page
68833
+ * cross-fades as a whole unless the application says otherwise, which is its
68834
+ * call and not the list's:
68835
+ * ```css
68836
+ * @supports not (view-transition-group: contain) {
68837
+ * :root { view-transition-name: none; }
68838
+ * }
68839
+ * ```
68840
+ * @param {false|((index: number) => any)} [props.renderSkeleton]
68841
+ * What a row on its way looks like — a row of the shape the real ones will
68842
+ * have, so nothing moves when they arrive. Used for the rows a `<List.Items>`
68843
+ * stands for and does not hold yet, and for the placeholder rows drawn while
68844
+ * the whole list is `loading`. Defaults to a bare `<List.Item skeleton>`.
68845
+ * @param {"skeleton"|"loader"|import("ignore:preact").ComponentChildren} [props.loadingFallback="skeleton"]
68846
+ * What to display in place of the items while `loading` — that is, while
68847
+ * there is nothing to show at all: `"skeleton"` renders
68848
+ * `loadingSkeletonCount` placeholder rows (look:
68849
+ * `renderSkeleton`), `"loader"` a single centered spinner, and
68850
+ * anything else is rendered as-is in a row of its own. A falsy value
68851
+ * displays nothing. A list that knows how many rows it will have has no use
68852
+ * for this — see `<List.Items count>`, whose not-yet-loaded rows are drawn
68853
+ * as skeletons in place, one per row, virtualized like the rest.
68854
+ * @param {number} [props.loadingSkeletonCount=3]
68855
+ * How many placeholder rows `loadingFallback="skeleton"` draws. `0` says the
68856
+ * list is already known to be empty: the empty `fallback` shows right away
68857
+ * rather than an empty frame, so nothing moves when the response arrives.
68858
+ * @param {"start"|"end"|number|{id: string, offset?: number}} [props.defaultScrolled="start"]
68859
+ * Where the list opens, after which the user owns the scroll. `"end"` is a
68860
+ * thread read backwards — the last rows are the ones to show, and the ones
68861
+ * asked for first. A number opens on that row of the collection. `{id,
68862
+ * offset}` — what `onScrolledChange` hands out — opens on a NAMED row,
68863
+ * `offset` pixels below where the row would land on its own: the row is asked
68864
+ * for by name (see the range's own `around`), then put back by MEASURING it,
68865
+ * so it lands where it was even if rows were inserted before it, and whatever
68866
+ * the screen it was saved on. `offset: 0` is where a `scrollIntoView()` puts
68867
+ * it — in front of the fixed bar the scroller gives room for, below the
68868
+ * sticky header and the group label the row lives under — so nothing of that
68869
+ * room has to be restated as a number by whoever asks.
68870
+ * @param {"start"|"end"|number|{id: string, offset?: number}} [props.scrolled]
68871
+ * The same, but held: the list goes back there every time this changes, even
68872
+ * after the user has scrolled — the caller owns where the list is (see
68873
+ * `defaultScrolled` for the uncontrolled form, and `open`/`defaultOpen`
68874
+ * elsewhere in navi for the same pair). When the named row turns out not to
68875
+ * exist — a message deleted since — the list opens at `defaultScrolled`
68876
+ * instead.
68877
+ *
68878
+ * In every form the list holds itself there while it is still finding out
68879
+ * how many rows there are and how tall one is, and lets go the moment the
68880
+ * user reaches for the list.
68881
+ * @param {(scrolled: {id: string, index: number, offset: number}) => void} [props.onScrolledChange]
68882
+ * Where the list is, as the user scrolls: the row at the top of the view and
68883
+ * how far below the place a row lands on its own (see `defaultScrolled`) it
68884
+ * starts. Keep it to come back to it
68885
+ * later through `scrolled`/`defaultScrolled` — an index would not do, since
68886
+ * rows get inserted while a list is being read.
68887
+ * @param {"self"|"parent"|"document"|Element|{current: Element}} [props.scroller="self"]
68888
+ * Which box scrolls. `"self"` gives the list a scroll box of its own;
68889
+ * `"parent"` makes it virtualize against the scrollable ancestor it lives in
68890
+ * (the page, a panel) — no scroll box nested inside another one, no height
68891
+ * to compute.
68892
+ *
68893
+ * `"parent"` finds that ancestor by measuring: the nearest one whose content
68894
+ * actually overflows it, the page if none does. Declaring `overflow` is not
68895
+ * enough to be picked (a box with `overflow-x: auto` that grows with its
68896
+ * content computes `overflow-y: auto` without ever scrolling), and the
68897
+ * answer is taken again as the geometry moves, so an ancestor that starts to
68898
+ * scroll once it fills up is picked up then. When that is still not the box
68899
+ * you mean, say so: `"document"`, or the element itself (a ref works) —
68900
+ * nothing is guessed then.
68901
+ * @param {boolean} [props.hoverWhileScrolling=false]
68902
+ * Whether the rows still answer the pointer while the scroller they live in
68903
+ * is moving. They do not by default: a scroll slides the rows under a
68904
+ * motionless pointer, so the browser reports a hover on each of them, and
68905
+ * the user asked to scroll, not to hover. The cost of taking them at face
68906
+ * value is paid by whatever hover triggers — a highlight elsewhere in the
68907
+ * tree, a prefetch, a map — at the worst moment, mid-scroll.
68908
+ *
68909
+ * Pass `true` for a list whose rows must stay live under the pointer while
68910
+ * it scrolls. The trade of the default is the mirror one: right after a
68911
+ * scroll, the row under the pointer lights up only once the pointer moves.
68912
+ * @param {boolean} [props.deselectable]
68913
+ * A single-select list allowed to hold nothing: the selected row, pressed
68914
+ * again, lets go. Without it the list is a radio group — a choice, once
68915
+ * made, moves to another row but never goes away. A `multiple` list toggles
68916
+ * its rows already.
68917
+ * @param {number} [props.maxLength]
68918
+ * How many items a `selectable multiple` list accepts — the same word, and
68919
+ * the same behaviour, as `maxLength` on a text field: a rule the list is
68920
+ * judged against, not a wall. A longer selection is allowed to exist and is
68921
+ * reported as invalid, which is what lets a value coming from elsewhere (an
68922
+ * API, a URL) be shown and then corrected.
68923
+ * @param {number} [props.maxLengthGuard]
68924
+ * The same limit, enforced as the selection is made: while the list holds as
68925
+ * many items as it accepts, the ones not selected go read-only — still
68926
+ * pointable, focusable and pressable, answering `"[max] max."` instead of
68927
+ * taking — and `uiAction` is not called. The selected ones stay takeable
68928
+ * back, so a selection that arrived too long can always be brought back
68929
+ * under the limit. Implies `maxLength` for validity.
68930
+ * @param {number} [props.parallelGuard=4]
68931
+ * How many runs the rows may have in flight at once, for a list whose rows
68932
+ * carry their own `action` (a button per row). While that many are out, every
68933
+ * row that is not running goes read-only and says how many it is waiting on;
68934
+ * the next press is possible again as soon as one comes back. `Infinity`
68935
+ * lifts it. Counts runs, not values — `maxLengthGuard` above is the one that
68936
+ * says how many things the selection may hold.
68937
+ * @param {boolean} [props.standalone]
68938
+ * This list answers for itself: it does not register with the control group
68939
+ * or picker around it, so its selection stays out of that value and nothing
68940
+ * coming down — a distributed value, a reset — reaches it. What a popup whose
68941
+ * one answer is spread over several lists says, so that none of them is taken
68942
+ * for the answer itself.
68943
+ */
68944
+ const List = /*#__PURE__*/Object.assign(ListResolved, {
68945
+ Item: ListItem,
68946
+ Items: ListItems
68947
+ });
68900
68948
 
68901
68949
  const PickerNaviTime = props => {
68902
68950
  const Next = useNextResolver();
@@ -69829,7 +69877,7 @@ const PickerObject = props => {
69829
69877
  "navi-state-shape": "object"
69830
69878
  });
69831
69879
  };
69832
- const PickerObjectUI = asPickerOwnUI(() => {
69880
+ const PickerObjectUI = /*#__PURE__*/asPickerOwnUI(() => {
69833
69881
  const {
69834
69882
  value,
69835
69883
  placeholder
@@ -69864,7 +69912,7 @@ const PickerArray = props => {
69864
69912
  "navi-state-shape": "array"
69865
69913
  });
69866
69914
  };
69867
- const PickerArrayUI = asPickerOwnUI(() => {
69915
+ const PickerArrayUI = /*#__PURE__*/asPickerOwnUI(() => {
69868
69916
  const {
69869
69917
  value,
69870
69918
  placeholder,
@@ -69947,7 +69995,7 @@ const PickerColor = props => {
69947
69995
  ...props
69948
69996
  });
69949
69997
  };
69950
- const PickerColorUI = asPickerOwnUI(() => {
69998
+ const PickerColorUI = /*#__PURE__*/asPickerOwnUI(() => {
69951
69999
  const {
69952
70000
  value,
69953
70001
  placeholder
@@ -69971,7 +70019,7 @@ const PickerDate = props => {
69971
70019
  type: "date"
69972
70020
  });
69973
70021
  };
69974
- const PickerDateUI = asPickerOwnUI(props => {
70022
+ const PickerDateUI = /*#__PURE__*/asPickerOwnUI(props => {
69975
70023
  const {
69976
70024
  value,
69977
70025
  placeholder
@@ -70003,7 +70051,7 @@ const PickerMonth = props => {
70003
70051
  type: "month"
70004
70052
  });
70005
70053
  };
70006
- const PickerMonthUI = asPickerOwnUI(props => {
70054
+ const PickerMonthUI = /*#__PURE__*/asPickerOwnUI(props => {
70007
70055
  const {
70008
70056
  value,
70009
70057
  placeholder
@@ -70034,7 +70082,7 @@ const PickerWeek = props => {
70034
70082
  type: "week"
70035
70083
  });
70036
70084
  };
70037
- const PickerWeekUI = asPickerOwnUI(props => {
70085
+ const PickerWeekUI = /*#__PURE__*/asPickerOwnUI(props => {
70038
70086
  const {
70039
70087
  value,
70040
70088
  placeholder
@@ -70065,7 +70113,7 @@ const PickerTime = props => {
70065
70113
  type: "time"
70066
70114
  });
70067
70115
  };
70068
- const PickerTimeUI = asPickerOwnUI(props => {
70116
+ const PickerTimeUI = /*#__PURE__*/asPickerOwnUI(props => {
70069
70117
  const {
70070
70118
  value,
70071
70119
  placeholder
@@ -70096,7 +70144,7 @@ const PickerDuration = props => {
70096
70144
  "navi-input-type": "duration"
70097
70145
  });
70098
70146
  };
70099
- const PickerDurationUI = asPickerOwnUI(props => {
70147
+ const PickerDurationUI = /*#__PURE__*/asPickerOwnUI(props => {
70100
70148
  const {
70101
70149
  value,
70102
70150
  placeholder
@@ -70126,7 +70174,7 @@ const PickerDatetime = props => {
70126
70174
  type: "datetime-local"
70127
70175
  });
70128
70176
  };
70129
- const PickerDatetimeUI = asPickerOwnUI(props => {
70177
+ const PickerDatetimeUI = /*#__PURE__*/asPickerOwnUI(props => {
70130
70178
  const {
70131
70179
  value,
70132
70180
  placeholder
@@ -70155,7 +70203,7 @@ const PickerFile = props => {
70155
70203
  ...props
70156
70204
  });
70157
70205
  };
70158
- const PickerFileUI = asPickerOwnUI(() => {
70206
+ const PickerFileUI = /*#__PURE__*/asPickerOwnUI(() => {
70159
70207
  const {
70160
70208
  value,
70161
70209
  placeholder
@@ -70371,6 +70419,11 @@ const css$t = /* css */`@layer navi {
70371
70419
  }
70372
70420
  }
70373
70421
 
70422
+ &[data-open-on~="longpress"] {
70423
+ -webkit-touch-callout: none;
70424
+ user-select: none;
70425
+ }
70426
+
70374
70427
  &[navi-ui-custom] {
70375
70428
  & .navi_picker_input {
70376
70429
  top: calc(-1 * (var(--picker-border-width) + var(--x-picker-press-padding-top)));
@@ -71184,6 +71237,7 @@ const PickerStyleCSSVars = {
71184
71237
  "dialogMaxHeight": ["--picker-dialog-max-height", "maxHeight"],
71185
71238
  "popupBackgroundColor": "--picker-popup-background-color",
71186
71239
  "popupBorderRadius": ["--picker-popup-border-radius", "borderRadius"],
71240
+ "popupBoxShadow": ["--picker-popup-box-shadow", "boxShadow"],
71187
71241
  "dialogBorderWidth": ["--picker-dialog-border-width", "borderWidth"],
71188
71242
  "slotSpacing": ["--picker-slot-spacing", "margin"],
71189
71243
  "pressPadding": ["--picker-press-padding", "padding"],
@@ -71247,26 +71301,37 @@ const PickerFirstResolver = props => {
71247
71301
  ...props
71248
71302
  });
71249
71303
  };
71250
- const Picker = createComponentResolver([PickerFirstResolver, PickerPresetResolver, PickerConfirmResolver, PickerCustomResolver, PickerTypeResolver, PickerButton]);
71251
- Picker.Chip = PickerChip;
71252
- Picker.Clear = PickerClear;
71253
- Picker.UI = PickerDefaultUI;
71254
- Picker.UI.Date = PickerDateUI;
71255
- Picker.UI.Time = PickerTimeUI;
71256
- Picker.UI.Duration = PickerDurationUI;
71257
- Picker.UI.Week = PickerWeekUI;
71258
- Picker.UI.Datetime = PickerDatetimeUI;
71259
- Picker.UI.File = PickerFileUI;
71260
- Picker.UI.Color = PickerColorUI;
71261
- Picker.UI.Object = PickerObjectUI;
71262
- Picker.UI.Multiple = PickerArrayUI;
71263
- Picker.UI.PencilSvg = PencilSvg;
71264
- Picker.UI.ChevronDownSvg = ChevronDownSvg$1;
71265
- Picker.UI.ClockSvg = ClockSvg;
71266
- Picker.UI.DurationSvg = DurationSvg;
71267
- Picker.UI.CalendarSvg = CalendarSvg;
71268
- Picker.UI.FileSvg = FileSvg;
71269
- Picker.UI.ColorSvg = ColorSvg;
71304
+ const PickerResolved = /*#__PURE__*/createComponentResolver([PickerFirstResolver, PickerPresetResolver, PickerConfirmResolver, PickerCustomResolver, PickerTypeResolver, PickerButton]);
71305
+ const PickerUI = /*#__PURE__*/Object.assign(PickerDefaultUI, {
71306
+ Date: PickerDateUI,
71307
+ Time: PickerTimeUI,
71308
+ Duration: PickerDurationUI,
71309
+ Week: PickerWeekUI,
71310
+ Datetime: PickerDatetimeUI,
71311
+ File: PickerFileUI,
71312
+ Color: PickerColorUI,
71313
+ Object: PickerObjectUI,
71314
+ Multiple: PickerArrayUI,
71315
+ PencilSvg,
71316
+ ChevronDownSvg: ChevronDownSvg$1,
71317
+ ClockSvg,
71318
+ DurationSvg,
71319
+ CalendarSvg,
71320
+ FileSvg,
71321
+ ColorSvg
71322
+ });
71323
+
71324
+ // Assembled in pure expressions rather than written onto Picker afterwards
71325
+ // (`Picker.Chip = PickerChip`): what createComponentResolver returns is an object
71326
+ // a bundler cannot see through, so a property assigned to it later is a side
71327
+ // effect it has to keep — and with it Picker, every UI and everything they
71328
+ // import, in a bundle that never renders a picker. The annotations say these
71329
+ // calls only create and return; an unused Picker then disappears whole.
71330
+ const Picker = /*#__PURE__*/Object.assign(PickerResolved, {
71331
+ Chip: PickerChip,
71332
+ Clear: PickerClear,
71333
+ UI: PickerUI
71334
+ });
71270
71335
 
71271
71336
  installImportMetaCssBuild(import.meta);
71272
71337
  const css$s = /* css */`@layer navi {
@@ -77243,7 +77308,7 @@ const useTableDragContextValue = ({
77243
77308
  };
77244
77309
  }, [grabTarget, canChangeColumnOrder]);
77245
77310
  };
77246
- const TableDragCloneContainer = forwardRef((props, ref) => {
77311
+ const TableDragCloneContainer = /*#__PURE__*/forwardRef((props, ref) => {
77247
77312
  import.meta.css = [css$k, "@jsenv/navi/src/control/table/drag/table_drag.jsx"];
77248
77313
  const {
77249
77314
  tableId
@@ -77254,7 +77319,7 @@ const TableDragCloneContainer = forwardRef((props, ref) => {
77254
77319
  "data-overlay-for": tableId
77255
77320
  });
77256
77321
  });
77257
- const TableColumnDropPreview = forwardRef((props, ref) => {
77322
+ const TableColumnDropPreview = /*#__PURE__*/forwardRef((props, ref) => {
77258
77323
  return jsxs("div", {
77259
77324
  ref: ref,
77260
77325
  className: "navi_table_column_drop_preview",
@@ -79350,7 +79415,7 @@ const css$f = /* css */`.navi_table_ui {
79350
79415
  overflow: hidden;
79351
79416
  }
79352
79417
  `;
79353
- const TableUI = forwardRef((props, ref) => {
79418
+ const TableUI = /*#__PURE__*/forwardRef((props, ref) => {
79354
79419
  import.meta.css = [css$f, "@jsenv/navi/src/control/table/table_ui.jsx"];
79355
79420
  const {
79356
79421
  tableRef,