@jsenv/navi 0.29.8 → 0.29.9

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.
@@ -51959,25 +51959,30 @@ installImportMetaCssBuild(import.meta);/**
51959
51959
  * A value one steps through, one press at a time: what is chosen sits between
51960
51960
  * the way back and the way on, and the two of them are the whole control.
51961
51961
  *
51962
- * Days for now DaySpin below but nothing here is about days except how
51963
- * one is written and what "one step" adds. The name says where this is going:
51964
- * a picker whose value is stepped rather than typed (a month, a page, a size),
51965
- * shown as the picker it is.
51962
+ * `Spin` knows nothing about what it steps through. It is handed how to move
51963
+ * one step (`valueAtStep`), how to tell two values apart (`compareValues`) and
51964
+ * what to write for one (`renderValue`); everything else the frame, the two
51965
+ * ways out, the ends one cannot go past, the value a form carries — is the
51966
+ * same whatever the value is. `DaySpin` and `NumberSpin` at the bottom are two
51967
+ * of those answers, and a caller can write a third.
51968
+ *
51969
+ * The middle is one of two things, and that is the only real fork here:
51970
+ *
51971
+ * - a value one PICKS (`DaySpin`): a headless picker holds it, pressing the
51972
+ * middle opens it, and the three slides of a looping container show the one
51973
+ * before, this one and the one after — a window over a row with no end.
51974
+ * - a value one TYPES (`editable`, `NumberSpin`): the middle IS the field.
51975
+ * Nothing travels — one cannot slide what is being typed into — and the
51976
+ * arrows step the value where the caret already is.
51966
51977
  *
51967
51978
  * A picker, so it lives here: what one presses in the middle IS a picker, and
51968
51979
  * the stepping is a way of showing it. It is headless and behind the three
51969
51980
  * slides — there is one value being chosen, so there is one picker for it.
51970
51981
  *
51971
- * Three slides for a row with no end, kept by a looping slide container: a
51972
- * press travels by one, then the window comes back to the middle while the
51973
- * value moves one step under it (see its `loop`/`onLoop`). So the three are
51974
- * only ever "the one before, this one, the one after".
51975
- *
51976
- * Two things take the keyboard and no more: the container (arrows step,
51977
- * Enter/Space open the picker) and the two chevrons. What is in the middle is
51978
- * not a control — a click on the container opens the picker by command — which
51979
- * is what keeps the focus where the travel happens instead of moving it into a
51980
- * slide that is about to leave.
51982
+ * Two things take the keyboard and no more: the middle (the container in the
51983
+ * picking case, the field in the typing one) and nothing else the chevrons
51984
+ * refuse it on purpose, which is what keeps the focus where the travel happens
51985
+ * instead of moving it into a slide that is about to leave.
51981
51986
  */
51982
51987
  const css$p = /* css */`
51983
51988
  @layer navi {
@@ -51991,7 +51996,7 @@ const css$p = /* css */`
51991
51996
 
51992
51997
  .navi_picker_spin {
51993
51998
  /* The padding is written on what is inside the box rather than on the box
51994
- — the day takes all four sides, the two chevrons only the vertical ones
51999
+ — the value takes all four sides, the two chevrons only the vertical ones
51995
52000
  — so the four sides are resolved once here, in the side-then-axis-then
51996
52001
  -shorthand order a Box resolves them in. What writes them: the padding
51997
52002
  props, through PICKER_SPIN_STYLE_CSS_VARS below. */
@@ -52025,7 +52030,7 @@ const css$p = /* css */`
52025
52030
  );
52026
52031
  /* What the loading outline is drawn around. */
52027
52032
  position: relative;
52028
- /* Written in the control font, like the picker it wraps: the day and its
52033
+ /* Written in the control font, like the picker it wraps: the value and its
52029
52034
  two chevrons are a control, not running text. */
52030
52035
  font-size: var(--navi-control-font-size);
52031
52036
  font-family: var(--navi-control-font-family);
@@ -52043,16 +52048,19 @@ const css$p = /* css */`
52043
52048
  outline-color: var(--navi-focus-outline-color);
52044
52049
  outline-offset: 0px;
52045
52050
  }
52046
- /* The days hold the keyboard, and this box wears their ring: the container
52047
- fills it, so its own ring would be drawn a pixel inside this border and
52048
- two rings that close together read as a mistake. Same offer a dialog and a
52049
- popover answer (data-focus-outline-delegate, see slide_container.jsx), and
52050
- the same reply — the delegate stands down.
52051
+ /* The middle holds the keyboard, and this box wears its ring: whatever is in
52052
+ there fills it, so a ring of its own would be drawn a pixel inside this
52053
+ border and two rings that close together read as a mistake. Same offer a
52054
+ dialog and a popover answer (data-focus-outline-delegate, see
52055
+ slide_container.jsx), and the same reply — the delegate stands down; a
52056
+ field says it with an outline of zero width instead (see Spin's own
52057
+ outlineWidth below).
52051
52058
  Said on this box too (the first selector): nothing focuses it for real —
52052
- it is the container that takes the keyboard — but it is where the ring is
52059
+ it is the middle that takes the keyboard — but it is where the ring is
52053
52060
  drawn, so a demo can hold it there and show what it looks like. */
52054
52061
  .navi_picker_spin[data-focus-visible],
52055
- .navi_picker_spin:has([data-focus-outline-delegate][data-focus-visible]) {
52062
+ .navi_picker_spin:has([data-focus-outline-delegate][data-focus-visible]),
52063
+ .navi_picker_spin:has(.navi_input[data-focus-visible]) {
52056
52064
  outline-style: solid;
52057
52065
  }
52058
52066
  .navi_picker_spin [data-focus-outline-delegate] {
@@ -52103,6 +52111,14 @@ const css$p = /* css */`
52103
52111
  width: min(100%, var(--picker-spin-picker-width, 12ch));
52104
52112
  translate: -50% 0;
52105
52113
  }
52114
+ /* A middle one types into is the field itself: it takes the whole room
52115
+ between the chevrons rather than sitting in the centre of it, so the
52116
+ caret is where the value is and a click anywhere in the middle lands in
52117
+ the field. */
52118
+ .navi_picker_spin_middle > .navi_input {
52119
+ min-width: 0;
52120
+ flex: 1 1 auto;
52121
+ }
52106
52122
  /* Where the padding lands: all four sides on the value, the two vertical
52107
52123
  ones on the chevrons below — the same number above and below is what makes
52108
52124
  the three one line rather than three boxes, while sideways it is the room
@@ -52128,9 +52144,9 @@ const css$p = /* css */`
52128
52144
  .navi_picker_spin[data-disabled] [data-slide-container] {
52129
52145
  cursor: default;
52130
52146
  }
52131
- /* Kept inside its own slide: the three days share one cell, so anything
52132
- sticking out would be written across the two beside it. A day too long for
52133
- the box simply wraps — the box grows, and the words are all there; say
52147
+ /* Kept inside its own slide: the three values share one cell, so anything
52148
+ sticking out would be written across the two beside it. A value too long
52149
+ for the box simply wraps — the box grows, and the words are all there; say
52134
52150
  maxLines to cut it instead, which the text itself knows how to do. */
52135
52151
  .navi_picker_spin [data-slide] > * {
52136
52152
  max-width: 100%;
@@ -52206,53 +52222,73 @@ const css$p = /* css */`
52206
52222
 
52207
52223
  /**
52208
52224
  * @type {import("ignore:preact").FunctionComponent<{
52209
- * value?: string,
52210
- * defaultValue?: string,
52211
- * signal?: import("@preact/signals").Signal<string>,
52225
+ * value?: any,
52226
+ * defaultValue?: any,
52227
+ * signal?: import("@preact/signals").Signal<any>,
52212
52228
  * name?: string,
52213
- * min?: string,
52214
- * max?: string,
52229
+ * min?: any,
52230
+ * max?: any,
52215
52231
  * step?: number,
52232
+ * type?: string,
52233
+ * editable?: boolean,
52234
+ * growsUpward?: boolean,
52235
+ * fallbackValue?: any,
52236
+ * valueAtStep: (value: any, count: number) => any,
52237
+ * compareValues?: (a: any, b: any) => number,
52238
+ * renderValue?: (value: any) => import("ignore:preact").ComponentChildren,
52239
+ * controlProps?: object,
52216
52240
  * duration?: number,
52217
- * lang?: string,
52218
- * renderDay?: (day: string) => import("ignore:preact").ComponentChildren,
52241
+ * vertical?: boolean,
52219
52242
  * previousLabel?: string,
52220
52243
  * nextLabel?: string,
52221
52244
  * [key: string]: any,
52222
52245
  * }>}
52223
- * @param {string} [value] The day shown, as "YYYY-MM-DD". Held from above:
52224
- * `uiAction` says when it should move. Say `signal` for a two-way binding
52225
- * instead, or `defaultValue` to let the spin hold the day itself.
52226
- * @param {number} [step=1] How many days a press covers 7 for a week at a
52227
- * time, and the label then names the day one lands on, as it always does.
52246
+ * @param {any} [value] The value shown. Held from above: `uiAction` says when
52247
+ * it should move. Say `signal` for a two-way binding instead, or
52248
+ * `defaultValue` to let the spin hold the value itself.
52249
+ * @param {(value: any, count: number) => any} valueAtStep What is `count` steps
52250
+ * away from `value` — the whole of what a spin has to know about what it
52251
+ * steps through. Called with -1 and +1 (times `step`) for the two ways out.
52252
+ * @param {(a: any, b: any) => number} [compareValues] Which of two values comes
52253
+ * first, the way a sort comparator answers. Only `min`/`max` need it, and the
52254
+ * default compares them as they compare with `<` — which is what an ISO date
52255
+ * wants and what a number does not.
52256
+ * @param {any} [fallbackValue] What is shown when nobody said anything: a spin
52257
+ * always shows a value, so there is always one to fall back on.
52258
+ * @param {string} [type="text"] What kind of value it is, handed to the control
52259
+ * holding it — a picker's `type` ("date", "time"…) or an input's.
52260
+ * @param {boolean} [editable] The middle is typed into rather than pressed:
52261
+ * the field IS the middle, and nothing travels. Without it the value is
52262
+ * picked — a headless picker behind three slides that travel one step at a
52263
+ * press.
52264
+ * @param {object} [controlProps] Anything else the control in the middle takes
52265
+ * (`inputMode`, `maxLength`, `placeholder`…).
52266
+ * @param {number} [step=1] How many steps a press covers.
52228
52267
  * @param {number} [duration=250] How long a travel takes, in milliseconds.
52229
- * @param {string} [min] The first day one can reach, as "YYYY-MM-DD"; `max` is
52230
- * the last. Beyond them the travel simply does not happen and the chevron
52231
- * that way says so.
52232
- * @param {"long"|"short"|"numeric"} [format="long"] How the date is written.
52233
- * Long by default, since this is a control one reads rather than a column
52234
- * one scans; `short` where the room is not there.
52268
+ * @param {any} [min] The first value one can reach; `max` is the last. Beyond
52269
+ * them the travel simply does not happen and the chevron that way says so.
52235
52270
  * @param {string} [padding] The room around the value, `paddingX`/`paddingY`
52236
52271
  * and the four sides included. It goes on what is inside the box rather than
52237
- * on the box: above and below it is taken by the day AND by the two chevrons,
52238
- * which is what makes the three the same height; sideways it is the room
52239
- * between the day and the chevron beside it. Left unsaid it is the padding
52240
- * every picker takes (`--navi-picker-padding-x-default` and its `-y` twin),
52241
- * so a theme that spaces its fields spaces this one with them.
52242
- * @param {number} [maxLines] How many lines the day may take before it is cut
52243
- * with an ellipsis — `maxLines={1}` keeps it on one line. Without it a day
52272
+ * on the box: above and below it is taken by the value AND by the two
52273
+ * chevrons, which is what makes the three the same height; sideways it is the
52274
+ * room between the value and the chevron beside it. Left unsaid it is the
52275
+ * padding every picker takes (`--navi-picker-padding-x-default` and its `-y`
52276
+ * twin), so a theme that spaces its fields spaces this one with them.
52277
+ * @param {number} [maxLines] How many lines the value may take before it is cut
52278
+ * with an ellipsis — `maxLines={1}` keeps it on one line. Without it a value
52244
52279
  * too long for the box wraps, and the box grows.
52245
52280
  * @param {boolean} [vertical] The same control standing up: the ways out above
52246
- * and below rather than left and right, and the days travelling upwards.
52281
+ * and below rather than left and right.
52282
+ * @param {boolean} [growsUpward] Which end of a standing spin holds the value
52283
+ * one steps up to. Off by default — what one walks through comes from below,
52284
+ * the way the next line of a list does. On for a quantity: pressing ▲ has to
52285
+ * mean a bigger number. Nothing to say about a spin lying down, where the way
52286
+ * on is always to the right.
52247
52287
  * Everything a box takes is taken here too — `width`, `borderWidth`,
52248
52288
  * `borderRadius`, `backgroundColor`: this IS a box, and its corners are passed
52249
52289
  * on to the chevrons sitting in them.
52250
- * @param {(day: string) => import("ignore:preact").ComponentChildren} [renderDay] What
52251
- * to write for a day. Defaults to the date plus what it is to today when
52252
- * there is a word for it ("samedi 8 août (demain)"), since a day near now is
52253
- * read as a distance from now before it is read as a date.
52254
52290
  */
52255
- const DaySpin = ({
52291
+ const Spin = ({
52256
52292
  value,
52257
52293
  defaultValue,
52258
52294
  uiAction,
@@ -52262,76 +52298,77 @@ const DaySpin = ({
52262
52298
  max,
52263
52299
  step = 1,
52264
52300
  duration = 250,
52265
- lang,
52266
- format = "long",
52301
+ type = "text",
52302
+ editable,
52303
+ growsUpward,
52304
+ fallbackValue,
52305
+ valueAtStep,
52306
+ compareValues = compareValuesDefault,
52307
+ renderValue = renderValueDefault,
52308
+ controlProps,
52267
52309
  vertical,
52268
52310
  readOnly,
52269
52311
  disabled,
52270
52312
  loading,
52271
52313
  maxLines,
52272
- renderDay = renderDayDefault,
52273
52314
  previousLabel,
52274
52315
  nextLabel,
52275
52316
  ...rest
52276
52317
  }) => {
52277
52318
  import.meta.css = [css$p, "@jsenv/navi/src/control/picker/picker_spin.jsx"];
52278
52319
  const id = useId();
52279
- const containerId = `${id}_days`;
52280
- const pickerId = `${id}_picker`;
52281
- // The picker holds the day, and it is asked rather than shadowed: `value`,
52282
- // `defaultValue` and `signal` are handed to it untouched (see below), it
52283
- // settles which of them wins — and what a form makes of each — and this reads
52284
- // the answer back. Nothing of that story is told twice.
52285
- const pickerRef = useRef();
52286
- const dayFallback = firstDayAllowed({
52287
- min,
52288
- max,
52289
- step
52290
- });
52291
- const day = useControlUIState(pickerRef, value ?? defaultValue ?? signalProp?.peek()) ?? dayFallback;
52320
+ const containerId = `${id}_values`;
52321
+ const controlId = `${id}_control`;
52322
+ // The control holds the value, and it is asked rather than shadowed:
52323
+ // `value`, `defaultValue` and `signal` are handed to it untouched (see
52324
+ // below), it settles which of them wins — and what a form makes of each —
52325
+ // and this reads the answer back. Nothing of that story is told twice.
52326
+ const controlRef = useRef();
52327
+ const middleRef = useRef();
52328
+ const valueShown = useControlUIState(controlRef, value ?? defaultValue ?? signalProp?.peek()) ?? fallbackValue;
52292
52329
 
52293
52330
  // …and the other way round when a signal was handed over: a bound signal is
52294
- // the day, wherever it is moved from — the url, a back/forward, a button
52295
- // elsewhere on the page — and the control follows it. A picker seeded from a
52331
+ // the value, wherever it is moved from — the url, a back/forward, a button
52332
+ // elsewhere on the page — and the control follows it. A control seeded from a
52296
52333
  // signal only writes back into it (see resolveInputProps), which is enough
52297
- // for a field one only ever types into and not for a day that is also moved
52298
- // from outside. Undefined is not a day: the signal has nothing to say, so the
52299
- // control goes back to what it started on.
52300
- const signalDay = signalProp ? signalProp.value : undefined;
52301
- // The day as of the render this effect belongs to, and not one the closure
52334
+ // for a field one only ever types into and not for a value that is also moved
52335
+ // from outside. Undefined is not a value: the signal has nothing to say, so
52336
+ // the control goes back to what it started on.
52337
+ const signalValue = signalProp ? signalProp.value : undefined;
52338
+ // The value as of the render this effect belongs to, and not one the closure
52302
52339
  // captured a while ago: a step writes the signal, the signal brings us back
52303
- // here, and comparing against a stale day would set it a second time — one
52340
+ // here, and comparing against a stale value would set it a second time — one
52304
52341
  // uiAction per step becoming two.
52305
- const dayRef = useRef(day);
52306
- dayRef.current = day;
52342
+ const valueRef = useRef(valueShown);
52343
+ valueRef.current = valueShown;
52307
52344
  useLayoutEffect(() => {
52308
- const pickerEl = pickerRef.current;
52309
- if (!signalProp || !pickerEl) {
52345
+ const controlEl = controlRef.current;
52346
+ if (!signalProp || !controlEl) {
52310
52347
  return;
52311
52348
  }
52312
- if (signalDay === undefined) {
52313
- dispatchRequestResetUIState(pickerEl);
52349
+ if (signalValue === undefined) {
52350
+ dispatchRequestResetUIState(controlEl);
52314
52351
  return;
52315
52352
  }
52316
- if (signalDay !== dayRef.current) {
52317
- dispatchRequestSetUIState(pickerEl, signalDay, {});
52353
+ if (signalValue !== valueRef.current) {
52354
+ dispatchRequestSetUIState(controlEl, signalValue, {});
52318
52355
  }
52319
- }, [signalDay]);
52356
+ }, [signalValue]);
52320
52357
 
52321
- // A step is a change made to the picker, not beside it: it goes in the way a
52358
+ // A step is a change made to the control, not beside it: it goes in the way a
52322
52359
  // paste or a pick from the calendar goes in, so the signal, the form and
52323
52360
  // `uiAction` all learn about it from the same place — and the event that
52324
52361
  // asked for it travels with it, which is how `uiAction` can tell a chevron
52325
52362
  // from the calendar.
52326
- // What asked for the day being set, while it is being set: the picker
52363
+ // What asked for the value being set, while it is being set: the control
52327
52364
  // announces the change as its own input event, which says nothing of what
52328
52365
  // started it — so it is held here for the length of the dispatch and handed
52329
- // to uiAction below. That is how a caller tells a chevron from the calendar.
52366
+ // to uiAction below.
52330
52367
  const stepEventRef = useRef(null);
52331
- const setDay = (dayNext, event) => {
52368
+ const setValue = (valueNext, event) => {
52332
52369
  stepEventRef.current = event;
52333
52370
  try {
52334
- dispatchRequestSetUIState(pickerRef.current, dayNext, {
52371
+ dispatchRequestSetUIState(controlRef.current, valueNext, {
52335
52372
  event
52336
52373
  });
52337
52374
  } finally {
@@ -52340,29 +52377,29 @@ const DaySpin = ({
52340
52377
  };
52341
52378
 
52342
52379
  // Passed through rather than defaulted here: a prop nobody wrote must not
52343
- // reach the picker at all (it reads the presence of `value`, not its
52380
+ // reach the control at all (it reads the presence of `value`, not its
52344
52381
  // content), so each is added only if it was given.
52345
- const dayProps = {};
52382
+ const valueProps = {};
52346
52383
  if (value !== undefined) {
52347
- dayProps.value = value;
52384
+ valueProps.value = value;
52348
52385
  } else {
52349
52386
  if (signalProp) {
52350
- dayProps.signal = signalProp;
52387
+ valueProps.signal = signalProp;
52351
52388
  }
52352
- // A day is always shown, so the picker always HOLDS one: what was named, or
52353
- // what the signal starts on, or today (the nearest day a min/max/step
52354
- // leaves reachable). Said as a default rather than as a value, so a form
52355
- // reads the day shown as an answer one can send rather than as something it
52356
- // already holds and said even when a signal is bound, because a signal
52357
- // with nothing in it would otherwise leave the picker empty while the
52358
- // spin shows a day, and a form has nothing to send about an empty field.
52359
- dayProps.defaultValue = defaultValue ?? signalProp?.options?.getDefaultValue?.(false) ?? dayFallback;
52389
+ // A value is always shown, so the control always HOLDS one: what was named,
52390
+ // or what the signal starts on, or the fallback. Said as a default rather
52391
+ // than as a value, so a form reads what is shown as an answer one can send
52392
+ // rather than as something it already holds and said even when a signal
52393
+ // is bound, because a signal with nothing in it would otherwise leave the
52394
+ // control empty while the spin shows a value, and a form has nothing to
52395
+ // send about an empty field.
52396
+ valueProps.defaultValue = defaultValue ?? signalProp?.options?.getDefaultValue?.(false) ?? fallbackValue;
52360
52397
  }
52361
52398
 
52362
52399
  // Told from above as often as said here: a form running its action puts
52363
52400
  // every control inside it out of service (that is how the chevrons grey out
52364
- // by themselves), and the day they sit around must fade with them — it is one
52365
- // control, not a box with three moods.
52401
+ // by themselves), and the value they sit around must fade with them — it is
52402
+ // one control, not a box with three moods.
52366
52403
  const readOnlyFromAbove = useContext(ReadOnlyContext);
52367
52404
  const loadingFromAbove = useContext(LoadingContext$1);
52368
52405
  const disabledFromAbove = useContext(DisabledContext);
@@ -52388,15 +52425,54 @@ const DaySpin = ({
52388
52425
  }
52389
52426
  return undefined;
52390
52427
  };
52391
- const dayTextProps = {
52392
- lang,
52393
- format,
52394
- maxLines
52428
+ const valuePrevious = valueAtStep(valueShown, -step);
52429
+ const valueNext = valueAtStep(valueShown, step);
52430
+ const hasMin = min !== undefined && min !== "";
52431
+ const hasMax = max !== undefined && max !== "";
52432
+ const previousAllowed = !hasMin || compareValues(valuePrevious, min) >= 0;
52433
+ const nextAllowed = !hasMax || compareValues(valueNext, max) <= 0;
52434
+
52435
+ // Where the keyboard is put back after a press on a chevron: whatever holds
52436
+ // it in this spin, so one can keep going with the keys where one was. Found
52437
+ // in the middle rather than by id — a field's id lands on the box around it,
52438
+ // and what takes the keyboard is the input inside.
52439
+ const focusMiddle = () => {
52440
+ const target = editable ? middleRef.current?.querySelector(".navi_control_input") : document.getElementById(containerId);
52441
+ target?.focus({
52442
+ preventScroll: true
52443
+ });
52444
+ };
52445
+
52446
+ // Which end of a standing spin holds the value one steps UP to. A quantity
52447
+ // grows upwards — pressing ▲ on a number means a bigger number, and anything
52448
+ // else is read as a bug. What one walks through does the opposite: the day
52449
+ // after today arrives from below, the way the next line of a list does.
52450
+ const startIsNext = vertical && growsUpward;
52451
+ const valueAtStart = startIsNext ? valueNext : valuePrevious;
52452
+ const valueAtEnd = startIsNext ? valuePrevious : valueNext;
52453
+ const startAllowed = startIsNext ? nextAllowed : previousAllowed;
52454
+ const endAllowed = startIsNext ? previousAllowed : nextAllowed;
52455
+ const wayOut = atStart => {
52456
+ const isNext = atStart ? startIsNext : !startIsNext;
52457
+ return jsx(WayOut, {
52458
+ unavailableMessage: wayOutMessage(atStart ? startAllowed : endAllowed, isNext ? "spin.nothing_after" : "spin.nothing_before"),
52459
+ label: isNext ? nextLabel ?? naviI18n("spin.next") : previousLabel ?? naviI18n("spin.previous"),
52460
+ onPress: e => {
52461
+ focusMiddle();
52462
+ if (editable) {
52463
+ setValue(atStart ? valueAtStart : valueAtEnd, e);
52464
+ return;
52465
+ }
52466
+ // A direction on the map, not a value: the slides are laid out from
52467
+ // start to end (see below), so the way out at the start walks
52468
+ // backwards through them whichever value sits there.
52469
+ const command = atStart ? vertical ? "--navi-up" : "--navi-left" : vertical ? "--navi-down" : "--navi-right";
52470
+ triggerNaviCommand(e.currentTarget, command, e);
52471
+ },
52472
+ commandFor: editable ? undefined : containerId,
52473
+ children: atStart ? vertical ? jsx(ChevronUpSvg, {}) : jsx(ChevronLeftSvg, {}) : vertical ? jsx(ChevronDownSvg, {}) : jsx(ChevronRightSvg, {})
52474
+ });
52395
52475
  };
52396
- const dayPrevious = addDays(day, -step);
52397
- const dayNext = addDays(day, step);
52398
- const previousAllowed = !min || dayPrevious >= min;
52399
- const nextAllowed = !max || dayNext <= max;
52400
52476
  return jsxs(Box, {
52401
52477
  ...rest,
52402
52478
  baseClassName: "navi_picker_spin",
@@ -52415,128 +52491,151 @@ const DaySpin = ({
52415
52491
  loading: loading,
52416
52492
  color: "var(--navi-loader-color)",
52417
52493
  inset: -2
52418
- }), jsx(WayOut, {
52419
- command: vertical ? "--navi-up" : "--navi-left",
52420
- containerId: containerId,
52421
- unavailableMessage: wayOutMessage(previousAllowed, "spin.nothing_before"),
52422
- label: previousLabel ?? naviI18n("spin.previous"),
52423
- children: vertical ? jsx(ChevronUpSvg, {}) : jsx(ChevronLeftSvg, {})
52424
- }), jsxs("div", {
52494
+ }), wayOut(true), jsx("div", {
52425
52495
  className: "navi_picker_spin_middle",
52426
- children: [jsx(Picker, {
52427
- ref: pickerRef,
52428
- id: pickerId,
52429
- type: "date",
52430
- variant: "headless",
52431
- name: name
52432
- // Whatever was said about the day, said to the picker: a `value` it
52433
- // holds, a `signal` it follows, a `defaultValue` it merely starts on —
52434
- // including what a form makes of the difference (it HOLDS a value and
52435
- // has nothing to send back, where a default is a suggestion and
52436
- // confirming it is an answer). A day is always shown, so there is
52437
- // always a default: today, when nobody named one.
52438
- ,
52439
-
52440
- ...dayProps,
52496
+ ref: middleRef,
52497
+ children: editable ? jsx(Input, {
52498
+ ref: controlRef,
52499
+ type: type,
52500
+ name: name,
52501
+ ...controlProps,
52502
+ ...valueProps,
52441
52503
  min: min,
52442
52504
  max: max,
52505
+ step: step,
52443
52506
  readOnly: readOnly,
52444
52507
  disabled: disabled,
52445
- loading: loading,
52446
- uiAction: (dayNext, event) => {
52447
- uiAction?.(dayNext, stepEventRef.current ?? event);
52448
- }
52449
- }), jsxs(SlideContainer, {
52450
- id: containerId,
52451
- layout: vertical ? "column" : "row"
52452
- // What is left beside the two chevrons, whatever the days it holds are
52453
- // long: a control that resizes as one steps through it is a control one
52454
- // has to aim at twice.
52508
+ loading: loading
52509
+ // No frame of its own inside a frame, and no ring of its own
52510
+ // either: the spin draws both (see the CSS above), and an outline
52511
+ // of zero width is how a field stands down without its focus
52512
+ // state being touched.
52455
52513
  ,
52456
52514
 
52515
+ variant: "discrete",
52516
+ outlineWidth: "0",
52517
+ textAlign: "center",
52457
52518
  expandX: true,
52458
- defaultCurrent: "current",
52459
- duration: `${duration}ms`
52460
- // The three days are a window over an endless row: the container plays
52461
- // the travel and comes back to the middle, and the day moves one step
52462
- // here, in onLoop, as it lands.
52463
- ,
52519
+ uiAction: (valueNext, event) => {
52520
+ uiAction?.(valueNext, stepEventRef.current ?? event);
52521
+ }
52522
+ }) : jsxs(Fragment$1, {
52523
+ children: [jsx(Picker, {
52524
+ ref: controlRef,
52525
+ id: controlId,
52526
+ type: type,
52527
+ variant: "headless",
52528
+ name: name,
52529
+ ...controlProps,
52530
+ ...valueProps,
52531
+ min: min,
52532
+ max: max,
52533
+ readOnly: readOnly,
52534
+ disabled: disabled,
52535
+ loading: loading,
52536
+ uiAction: (valueNext, event) => {
52537
+ uiAction?.(valueNext, stepEventRef.current ?? event);
52538
+ }
52539
+ }), jsxs(SlideContainer, {
52540
+ id: containerId,
52541
+ layout: vertical ? "column" : "row"
52542
+ // What is left beside the two chevrons, whatever the values it
52543
+ // holds are long: a control that resizes as one steps through it
52544
+ // is a control one has to aim at twice.
52545
+ ,
52464
52546
 
52465
- loop: true,
52466
- onLoop: ({
52467
- dx,
52468
- dy,
52469
- event
52470
- }) => {
52471
- // One step, whichever axis it came from: the map is a line, so only
52472
- // one of the two is ever anything but zero. The event goes with it —
52473
- // it is what says a chevron (or an arrow key) asked for this day.
52474
- setDay(addDays(day, (dx || dy) * step), event);
52475
- }
52476
- // The whole middle opens the calendar — a command, like the chevrons
52477
- // send one, and no button of its own: the day would then be one more
52478
- // Tab stop, and the focus would follow it out of the box as it travels.
52479
- ,
52547
+ expandX: true,
52548
+ defaultCurrent: "current",
52549
+ duration: `${duration}ms`
52550
+ // The three values are a window over an endless row: the
52551
+ // container plays the travel and comes back to the middle, and
52552
+ // the value moves one step here, in onLoop, as it lands.
52553
+ ,
52480
52554
 
52481
- commandFor: pickerId
52482
- // Sent whatever state the control is in: the picker is the one that
52483
- // knows it cannot be opened right now, and refusing there is what says
52484
- // so out loud (read-only, busy). Refusing here would be a press that
52485
- // does nothing and explains nothing.
52486
- // preventDefault, because a <Label> around the whole control forwards
52487
- // a click to what it labels the picker and that would open the
52488
- // calendar a second time, right after this command did.
52489
- ,
52555
+ loop: true,
52556
+ onLoop: ({
52557
+ dx,
52558
+ dy,
52559
+ event
52560
+ }) => {
52561
+ // One step, whichever axis it came from: the map is a line, so
52562
+ // only one of the two is ever anything but zero. Towards the
52563
+ // end of the line is a step forward, unless the line was laid
52564
+ // out the other way round (startIsNext). The event goes with
52565
+ // it — it is what says a chevron (or an arrow key) asked for
52566
+ // this value.
52567
+ const towardsEnd = dx || dy;
52568
+ setValue(valueAtStep(valueShown, (startIsNext ? -towardsEnd : towardsEnd) * step), event);
52569
+ }
52570
+ // The whole middle opens the picker — a command, like the
52571
+ // chevrons send one, and no button of its own: the value would
52572
+ // then be one more Tab stop, and the focus would follow it out of
52573
+ // the box as it travels.
52574
+ ,
52490
52575
 
52491
- onClick: e => {
52492
- e.preventDefault();
52493
- triggerNaviCommand(e.currentTarget, "--navi-open", e);
52494
- },
52495
- children: [jsx(Slide, {
52496
- area: "previous",
52497
- flex: true,
52498
- align: "center",
52499
- children: renderDay(dayPrevious, dayTextProps)
52500
- }), jsx(Slide, {
52501
- area: "current",
52502
- flex: true,
52503
- align: "center"
52504
- // The days a min/max leaves out are simply not reachable: the way out
52505
- // is closed on the slide being left, so a key, a chevron and a
52506
- // command are all stopped by the same thing.
52576
+ commandFor: controlId
52577
+ // Sent whatever state the control is in: the picker is the one
52578
+ // that knows it cannot be opened right now, and refusing there is
52579
+ // what says so out loud (read-only, busy). Refusing here would be
52580
+ // a press that does nothing and explains nothing.
52581
+ // preventDefault, because a <Label> around the whole control
52582
+ // forwards a click to what it labels — the picker — and that
52583
+ // would open the calendar a second time, right after this command
52584
+ // did.
52507
52585
  ,
52508
52586
 
52509
- preventNavPrevious: !previousAllowed,
52510
- preventNavNext: !nextAllowed,
52511
- children: renderDay(day, dayTextProps)
52512
- }), jsx(Slide, {
52513
- area: "next",
52514
- flex: true,
52515
- align: "center",
52516
- children: renderDay(dayNext, dayTextProps)
52587
+ onClick: e => {
52588
+ e.preventDefault();
52589
+ triggerNaviCommand(e.currentTarget, "--navi-open", e);
52590
+ },
52591
+ children: [jsx(Slide, {
52592
+ area: "start",
52593
+ flex: true,
52594
+ align: "center",
52595
+ children: renderValue(valueAtStart, {
52596
+ maxLines
52597
+ })
52598
+ }), jsx(Slide, {
52599
+ area: "current",
52600
+ flex: true,
52601
+ align: "center"
52602
+ // The values a min/max leaves out are simply not reachable: the
52603
+ // way out is closed on the slide being left, so a key, a
52604
+ // chevron and a command are all stopped by the same thing.
52605
+ ,
52606
+
52607
+ preventNavPrevious: !startAllowed,
52608
+ preventNavNext: !endAllowed,
52609
+ children: renderValue(valueShown, {
52610
+ maxLines
52611
+ })
52612
+ }), jsx(Slide, {
52613
+ area: "end",
52614
+ flex: true,
52615
+ align: "center",
52616
+ children: renderValue(valueAtEnd, {
52617
+ maxLines
52618
+ })
52619
+ })]
52517
52620
  })]
52518
- })]
52519
- }), jsx(WayOut, {
52520
- command: vertical ? "--navi-down" : "--navi-right",
52521
- containerId: containerId,
52522
- unavailableMessage: wayOutMessage(nextAllowed, "spin.nothing_after"),
52523
- label: nextLabel ?? naviI18n("spin.next"),
52524
- children: vertical ? jsx(ChevronDownSvg, {}) : jsx(ChevronRightSvg, {})
52525
- })]
52621
+ })
52622
+ }), wayOut(false)]
52526
52623
  });
52527
52624
  };
52528
52625
 
52529
52626
  // A way out is a place one presses, not a control: no <button>, on purpose.
52530
52627
  // A <button> is labelable, so a <Label> wrapping the whole spin would bind
52531
- // to the first chevron instead of to the picker — the thing that actually holds
52532
- // the value — and a form would carry two more controls that answer for nothing.
52533
- // It is not focusable either: the keyboard walks the days on the container (see
52534
- // its own tabIndex), where the arrows already mean this.
52628
+ // to the first chevron instead of to the control — the thing that actually
52629
+ // holds the value — and a form would carry two more controls that answer for
52630
+ // nothing.
52631
+ // It is not focusable either: the keyboard walks the values on the middle (see
52632
+ // the container's own tabIndex, or the field's), where the arrows already mean
52633
+ // this.
52535
52634
  const WayOut = ({
52536
- command,
52537
- containerId,
52635
+ commandFor,
52538
52636
  unavailableMessage,
52539
52637
  label,
52638
+ onPress,
52540
52639
  children
52541
52640
  }) => jsx(Box, {
52542
52641
  as: "span",
@@ -52560,38 +52659,32 @@ const WayOut = ({
52560
52659
  // Read by triggerNaviCommand below the same way it reads a button's own.
52561
52660
  ,
52562
52661
 
52563
- commandfor: containerId,
52662
+ commandfor: commandFor,
52564
52663
  flex: true,
52565
52664
  align: "center"
52566
52665
  // A press, answered where it starts: mousedown rather than click, which is
52567
52666
  // what makes holding one feel immediate — and the click after it is stopped
52568
52667
  // below, so a <Label> wrapping the whole control does not forward it to the
52569
- // picker and open the calendar on the way past.
52668
+ // control and open the calendar on the way past.
52570
52669
  ,
52571
52670
 
52572
52671
  onClick: e => {
52573
52672
  e.preventDefault();
52574
52673
  },
52575
52674
  onMouseDown: e => {
52576
- // No focus, no text selection: the keyboard is put on the days below.
52675
+ // No focus, no text selection: the keyboard is put on the middle below.
52577
52676
  e.preventDefault();
52578
- const wayOutElement = e.currentTarget;
52579
52677
  if (unavailableMessage) {
52580
52678
  // Why it does nothing, said where one pressed: a control would have
52581
52679
  // done this through its own interaction gate, and this one has none.
52582
52680
  openCallout(unavailableMessage, {
52583
- anchorElement: wayOutElement,
52681
+ anchorElement: e.currentTarget,
52584
52682
  status: "info",
52585
52683
  openingEvent: e
52586
52684
  });
52587
52685
  return;
52588
52686
  }
52589
- // The keyboard follows the press: the days are where the arrows work, so
52590
- // pressing a chevron leaves one able to keep going with the keys.
52591
- document.getElementById(containerId)?.focus({
52592
- preventScroll: true
52593
- });
52594
- triggerNaviCommand(wayOutElement, command, e);
52687
+ onPress(e);
52595
52688
  },
52596
52689
  children: jsx(Icon, {
52597
52690
  children: children
@@ -52601,8 +52694,8 @@ const PICKER_SPIN_PSEUDO_CLASSES = [":hover", ":focus-visible"];
52601
52694
 
52602
52695
  // A padding written on this box would sit between its border and the chevrons,
52603
52696
  // which are meant to reach the corners they are rounded by — so each padding
52604
- // prop becomes a variable instead, and the CSS above hands it to the day and to
52605
- // the chevrons themselves. Same trick, and same var chain, as Picker's.
52697
+ // prop becomes a variable instead, and the CSS above hands it to the value and
52698
+ // to the chevrons themselves. Same trick, and same var chain, as Picker's.
52606
52699
  const PICKER_SPIN_STYLE_CSS_VARS = {
52607
52700
  padding: "--picker-spin-padding",
52608
52701
  paddingX: "--picker-spin-padding-x",
@@ -52613,6 +52706,138 @@ const PICKER_SPIN_STYLE_CSS_VARS = {
52613
52706
  paddingLeft: "--picker-spin-padding-left"
52614
52707
  };
52615
52708
 
52709
+ // Two values compared the way `<` compares them: right for an ISO day, a time
52710
+ // or anything else written so that its order IS its alphabetical order. A
52711
+ // number is the exception, and NumberSpin below says so.
52712
+ const compareValuesDefault = (a, b) => {
52713
+ if (a < b) {
52714
+ return -1;
52715
+ }
52716
+ if (a > b) {
52717
+ return 1;
52718
+ }
52719
+ return 0;
52720
+ };
52721
+ const renderValueDefault = value => String(value ?? "");
52722
+
52723
+ /**
52724
+ * A whole number one steps through and types into: the field IS the middle, so
52725
+ * the value can be typed as readily as stepped, and the two chevrons stand
52726
+ * above and below it by default — sideways they would be where the caret
52727
+ * moves — with the bigger number up top.
52728
+ *
52729
+ * @type {import("ignore:preact").FunctionComponent<{
52730
+ * value?: number|string,
52731
+ * defaultValue?: number|string,
52732
+ * min?: number,
52733
+ * max?: number,
52734
+ * step?: number,
52735
+ * [key: string]: any,
52736
+ * }>}
52737
+ * @param {number} [min=0] The lowest number one can reach; `max` is the
52738
+ * highest. They also bound what typing can produce, and how wide the field
52739
+ * is asked to be (see `maxLength`).
52740
+ */
52741
+ const NumberSpin = ({
52742
+ min = 0,
52743
+ max,
52744
+ step = 1,
52745
+ vertical = true,
52746
+ growsUpward = true,
52747
+ controlProps,
52748
+ ...rest
52749
+ }) => jsx(Spin, {
52750
+ type: "navi_number",
52751
+ editable: true,
52752
+ growsUpward: growsUpward,
52753
+ min: min,
52754
+ max: max,
52755
+ step: step,
52756
+ vertical: vertical,
52757
+ fallbackValue: min,
52758
+ valueAtStep: (value, count) => numberAtStep(value, count, min),
52759
+ compareValues: (a, b) => Number(a) - Number(b),
52760
+ controlProps: {
52761
+ // The numeric keypad on a phone, and — through
52762
+ // input_resolver_mode — the "this field is full" event a group of
52763
+ // fields moves along on (see useInputGroup).
52764
+ inputMode: "numeric",
52765
+ maxLength: max === undefined ? undefined : String(max).length,
52766
+ ...controlProps
52767
+ },
52768
+ ...rest
52769
+ });
52770
+
52771
+ // One step away, bounds included: a step past `max` is a real number that
52772
+ // simply is not allowed, and Spin is the one that reads it as "nothing that
52773
+ // way" — clamping here would answer the chevron before it had a chance to say
52774
+ // so. A field mid-edit holding nothing (or nothing numeric) starts from `min`.
52775
+ const numberAtStep = (value, count, min) => {
52776
+ const number = Number(value);
52777
+ if (value === "" || value === undefined || Number.isNaN(number)) {
52778
+ return min;
52779
+ }
52780
+ return number + count;
52781
+ };
52782
+
52783
+ /**
52784
+ * A day one steps through: the date plus what it is to today when there is a
52785
+ * word for it, and a calendar behind it for the day that is far from here.
52786
+ *
52787
+ * @type {import("ignore:preact").FunctionComponent<{
52788
+ * value?: string,
52789
+ * defaultValue?: string,
52790
+ * signal?: import("@preact/signals").Signal<string>,
52791
+ * name?: string,
52792
+ * min?: string,
52793
+ * max?: string,
52794
+ * step?: number,
52795
+ * lang?: string,
52796
+ * renderDay?: (day: string) => import("ignore:preact").ComponentChildren,
52797
+ * [key: string]: any,
52798
+ * }>}
52799
+ * @param {string} [value] The day shown, as "YYYY-MM-DD".
52800
+ * @param {number} [step=1] How many days a press covers — 7 for a week at a
52801
+ * time, and the label then names the day one lands on, as it always does.
52802
+ * @param {string} [min] The first day one can reach, as "YYYY-MM-DD"; `max` is
52803
+ * the last.
52804
+ * @param {"long"|"short"|"numeric"} [format="long"] How the date is written.
52805
+ * Long by default, since this is a control one reads rather than a column
52806
+ * one scans; `short` where the room is not there.
52807
+ * @param {(day: string) => import("ignore:preact").ComponentChildren} [renderDay] What
52808
+ * to write for a day. Defaults to the date plus what it is to today when
52809
+ * there is a word for it ("samedi 8 août (demain)"), since a day near now is
52810
+ * read as a distance from now before it is read as a date.
52811
+ */
52812
+ const DaySpin = ({
52813
+ min,
52814
+ max,
52815
+ step = 1,
52816
+ lang,
52817
+ format = "long",
52818
+ renderDay = renderDayDefault,
52819
+ ...rest
52820
+ }) => jsx(Spin, {
52821
+ type: "date",
52822
+ min: min,
52823
+ max: max,
52824
+ step: step,
52825
+ fallbackValue: firstDayAllowed({
52826
+ min,
52827
+ max,
52828
+ step
52829
+ }),
52830
+ valueAtStep: addDays,
52831
+ renderValue: (day, {
52832
+ maxLines
52833
+ }) => renderDay(day, {
52834
+ lang,
52835
+ format,
52836
+ maxLines
52837
+ }),
52838
+ ...rest
52839
+ });
52840
+
52616
52841
  // The date, and what it is to today when that is something one has a word for:
52617
52842
  // "samedi 8 août (demain)" says both where one is and how far that is, and only
52618
52843
  // the second is read at a glance.
@@ -54565,6 +54790,15 @@ const css$k = /* css */`
54565
54790
  --wheel-window-inset: calc((100% - var(--wheel-item-height)) / 2);
54566
54791
  --wheel-band-inset: calc((100% - var(--wheel-emphasis-size)) / 2);
54567
54792
 
54793
+ /* As wide as the rows ON SCREEN, which is not the same as "as wide as
54794
+ the widest value": the rows are a handful of recycled slots, so a wheel
54795
+ whose labels are not all the same width resizes as one scrolls — "9"
54796
+ becoming "10" widens it mid-glide, and whatever holds it (a popup)
54797
+ moves under the finger. Give such a wheel a width and the question is
54798
+ settled once; the per-row padding stays where it is, inside it, and
54799
+ stays scrollable. Digits are the case where this does not arise on its
54800
+ own: data-wheel-type="integer" makes them tabular above, so they all
54801
+ advance the same — until one of them takes a digit more. */
54568
54802
  width: fit-content;
54569
54803
 
54570
54804
  .navi_wheel_viewport {
@@ -54649,6 +54883,9 @@ const css$k = /* css */`
54649
54883
  --wheel-window-inset: calc((100% - var(--wheel-item-width)) / 2);
54650
54884
  --wheel-band-inset: calc((100% - var(--wheel-emphasis-size)) / 2);
54651
54885
 
54886
+ /* The cross axis follows the rows on screen — same story as the vertical
54887
+ branch above, and the same answer: say a height when the rows are not
54888
+ all as tall as each other. */
54652
54889
  height: fit-content;
54653
54890
 
54654
54891
  .navi_wheel_viewport {
@@ -62425,5 +62662,5 @@ const UserSvg = () => jsx("svg", {
62425
62662
  })
62426
62663
  });
62427
62664
 
62428
- 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, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineNaviConfirmPopupOptions, 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, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
62665
+ 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, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineNaviConfirmPopupOptions, 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, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, 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, valueInLocalStorage, windowWidthSignal };
62429
62666
  //# sourceMappingURL=jsenv_navi.js.map