@jsenv/navi 0.29.128 → 0.29.130

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.
@@ -17633,6 +17633,7 @@ const LAYOUT_PROPS = {
17633
17633
  flexWrap: applyToCssPropWhenTruthy("flexWrap", "wrap", "nowrap"),
17634
17634
  grid: () => {},
17635
17635
  gridTemplateColumns: PASS_THROUGH,
17636
+ gridTemplateRows: PASS_THROUGH,
17636
17637
  display: PASS_THROUGH, // in case people write "display: none" (even if hidden prop is recommended)
17637
17638
  row: () => {},
17638
17639
  column: () => {},
@@ -66925,8 +66926,15 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
66925
66926
  /* The façade is transparent to the pointer — a press on what it draws
66926
66927
  means "open the picker". An own target is the exception, the same way
66927
66928
  the clear cross is one in the slot below: it says the press is aimed at
66928
- IT, so it has to be reachable at all. */
66929
+ IT, so it has to be reachable at all.
66930
+ Positioned as well as pointable: the input covering the box
66931
+ (see [navi-ui-custom] below) is absolute, so it paints over every
66932
+ static element of the façade whatever their pointer-events say — and
66933
+ the press then reaches the input, which is the picker. No offset, so
66934
+ nothing moves; this only puts the own target in the same paint layer
66935
+ as the things it has to be reachable through. */
66929
66936
  [data-own-target] {
66937
+ position: relative;
66930
66938
  pointer-events: auto;
66931
66939
  }
66932
66940
  }
@@ -67170,6 +67178,42 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
67170
67178
  z-index: -1;
67171
67179
  }
67172
67180
  }
67181
+ /* bare: the caller's drawing IS the trigger. No frame, no control line, no
67182
+ slot beside it, no clamp on it — the picker takes the size of what the ui
67183
+ draws, to the pixel, and does nothing to it but catch the press. For a
67184
+ picker that is a whole piece of a layout (a column of a card, a tile)
67185
+ rather than a field: the same drawing can then sit alone somewhere else
67186
+ and be the same box in both places. */
67187
+ &[data-variant="bare"] {
67188
+ --picker-padding-x-default: 0;
67189
+ --picker-padding-y-default: 0;
67190
+ /* The box holds the drawing rather than placing it inside itself: a
67191
+ height the caller gave the picker belongs to the drawing too. */
67192
+ --picker-align-y-default: stretch;
67193
+ --picker-border-width: 0px; /* must carry a unit (px) — used in calc() to offset the custom input overlay */
67194
+ --picker-border-color: transparent;
67195
+ --picker-border-color-hover: var(--picker-border-color);
67196
+ --picker-border-color-readonly: var(--picker-border-color);
67197
+ --picker-border-color-disabled: var(--picker-border-color);
67198
+ --picker-background-color: transparent;
67199
+ --picker-background-color-hover: var(--picker-background-color);
67200
+ --picker-background-color-readonly: var(--picker-background-color);
67201
+ --picker-background-color-disabled: var(--picker-background-color);
67202
+ --x-picker-icon-color: currentColor;
67203
+
67204
+ /* The drawing is the caller's, so it is written on the page's line at
67205
+ the page's size — the control font and the control line belong to the
67206
+ field-like drawings, which this one is not. */
67207
+ font-size: inherit;
67208
+ font-family: inherit;
67209
+ line-height: inherit;
67210
+
67211
+ .navi_picker_box {
67212
+ /* A field is at least one line tall whatever it holds; this is not a
67213
+ field, so its height is the drawing's and nothing else. */
67214
+ min-height: 0;
67215
+ }
67216
+ }
67173
67217
  /* button: drawn as a Button is, from the same tokens (see button_ui.jsx
67174
67218
  and the --navi-button-* vars) — its surface, its padding, a centered
67175
67219
  label, its washed-out read-only and disabled — for a picker that IS a
@@ -67273,7 +67317,10 @@ const PickerButton = props => {
67273
67317
  // A word in a sentence is never truncated — and the clamp's overflow: hidden
67274
67318
  // would cut its dotted underline, which sits on the edge of the line box
67275
67319
  // (WebKit drops it or not depending on the subpixel position of the line).
67276
- const maxLines = variant === "text" ? undefined : maxLinesProp;
67320
+ // A bare picker is not truncated either: the drawing it shows is the
67321
+ // caller's own, and clamping it would be the picker deciding the shape of
67322
+ // something it does not draw.
67323
+ const maxLines = variant === "text" || variant === "bare" ? undefined : maxLinesProp;
67277
67324
  const isSingleLine = maxLines === 1;
67278
67325
  // Same rule as the root: phrasing content inside a sentence.
67279
67326
  const ContentTag = variant === "text" ? "span" : "div";
@@ -67494,7 +67541,7 @@ const PickerButton = props => {
67494
67541
  })
67495
67542
  })
67496
67543
  })
67497
- }), variant === "icon" || variant === "headless" || variant === "button" || variant === "text" || ui === "default" ? null : jsx("span", {
67544
+ }), variant === "icon" || variant === "headless" || variant === "button" || variant === "text" || variant === "bare" || ui === "default" ? null : jsx("span", {
67498
67545
  className: "navi_picker_right_slot",
67499
67546
  children: jsx(PickerOwnContent, {
67500
67547
  children: clearable && interactive && value !== undefined && value !== "" && clearConfirm !== undefined ?
@@ -73474,6 +73521,7 @@ const TimeWheel = ({
73474
73521
  * size?: string,
73475
73522
  * startLabel?: import("ignore:preact").ComponentChildren,
73476
73523
  * endLabel?: import("ignore:preact").ComponentChildren,
73524
+ * labelPosition?: "before" | "above",
73477
73525
  * timeProps?: object,
73478
73526
  * [key: string]: any,
73479
73527
  * }>}
@@ -73482,6 +73530,13 @@ const TimeWheel = ({
73482
73530
  * @param {import("ignore:preact").ComponentChildren} [startLabel] What is written
73483
73531
  * before the first time ("De"), and `endLabel` between the two ("à"). Say
73484
73532
  * `null` for neither.
73533
+ * @param {"before"|"above"} [labelPosition="before"] Where each label stands.
73534
+ * Before its wheels, the span reads as one sentence ("De 9h00 à 18h00").
73535
+ * Above them, each bound is a column — "Début" over its wheels, "Fin" over
73536
+ * the other — two answers side by side, whose wheels land at the same place
73537
+ * whatever the width of the words. Labels that are nouns rather than
73538
+ * prepositions belong there; the group is still a row, and takes `flexWrap`
73539
+ * for screens too narrow to hold both columns.
73485
73540
  * @param {number} [minuteStep=1] How many minutes apart the values on both
73486
73541
  * minute wheels are.
73487
73542
  * @param {{min?: number, max?: number}|number[]} [hours] Which hours both
@@ -73510,6 +73565,7 @@ const TimeRangeWheel = ({
73510
73565
  size,
73511
73566
  startLabel = naviI18n("time_range.from"),
73512
73567
  endLabel = naviI18n("time_range.to"),
73568
+ labelPosition = "before",
73513
73569
  timeProps,
73514
73570
  startTimeProps,
73515
73571
  endTimeProps,
@@ -73577,53 +73633,61 @@ const TimeRangeWheel = ({
73577
73633
  ...rest,
73578
73634
  children: jsxs(AnsweredContext.Provider, {
73579
73635
  value: answeredRef,
73580
- children: [startLabel === null ? null : jsx(Text, {
73581
- size: size,
73582
- className: "navi_time_range_label",
73583
- children: startLabel
73584
- }), jsx(TimeWheel, {
73585
- id: startId,
73586
- ref: startRef,
73587
- name: "start",
73588
- minuteStep: minuteStep,
73589
- hours: hours,
73590
- loop: loop,
73591
- size: size,
73592
- placeholder: placeholder ? placeholder.start : undefined
73593
- // e.detail.value is the settled WHEEL's own value (an hour, a
73594
- // minute) — half a time. What the pair compares is this bound's
73595
- // whole time, read off the element the listener sits on.
73596
- ,
73636
+ children: [jsx(TimeBound, {
73637
+ labelPosition: labelPosition,
73638
+ label: startLabel === null ? null : jsx(Text, {
73639
+ size: size,
73640
+ className: "navi_time_range_label",
73641
+ children: startLabel
73642
+ }),
73643
+ children: jsx(TimeWheel, {
73644
+ id: startId,
73645
+ ref: startRef,
73646
+ name: "start",
73647
+ minuteStep: minuteStep,
73648
+ hours: hours,
73649
+ loop: loop,
73650
+ size: size,
73651
+ placeholder: placeholder ? placeholder.start : undefined
73652
+ // e.detail.value is the settled WHEEL's own value (an hour, a
73653
+ // minute) — half a time. What the pair compares is this bound's
73654
+ // whole time, read off the element the listener sits on.
73655
+ ,
73597
73656
 
73598
- onnavi_wheel_settle: e => {
73599
- keepBoundsApart("start", getUIStateFromElement(e.currentTarget), e);
73600
- },
73601
- ...timeProps,
73602
- ...startTimeProps
73603
- }), endLabel === null ? null : jsx(Text, {
73604
- size: size,
73605
- className: "navi_time_range_label",
73606
- children: endLabel
73607
- }), jsx(TimeWheel, {
73608
- ref: endRef,
73609
- name: "end",
73610
- minuteStep: minuteStep,
73611
- hours: hours,
73612
- loop: loop,
73613
- size: size,
73614
- placeholder: placeholder ? placeholder.end : undefined,
73615
- onnavi_wheel_settle: e => {
73616
- keepBoundsApart("end", getUIStateFromElement(e.currentTarget), e);
73617
- }
73618
- // Which time it comes after, and how much room there must be between
73619
- // the two: said on the LATER of the two, so the answer is given where
73620
- // the time one would have to move is (see time_range_constraint.js).
73621
- ,
73657
+ onnavi_wheel_settle: e => {
73658
+ keepBoundsApart("start", getUIStateFromElement(e.currentTarget), e);
73659
+ },
73660
+ ...timeProps,
73661
+ ...startTimeProps
73662
+ })
73663
+ }), jsx(TimeBound, {
73664
+ labelPosition: labelPosition,
73665
+ label: endLabel === null ? null : jsx(Text, {
73666
+ size: size,
73667
+ className: "navi_time_range_label",
73668
+ children: endLabel
73669
+ }),
73670
+ children: jsx(TimeWheel, {
73671
+ ref: endRef,
73672
+ name: "end",
73673
+ minuteStep: minuteStep,
73674
+ hours: hours,
73675
+ loop: loop,
73676
+ size: size,
73677
+ placeholder: placeholder ? placeholder.end : undefined,
73678
+ onnavi_wheel_settle: e => {
73679
+ keepBoundsApart("end", getUIStateFromElement(e.currentTarget), e);
73680
+ }
73681
+ // Which time it comes after, and how much room there must be between
73682
+ // the two: said on the LATER of the two, so the answer is given where
73683
+ // the time one would have to move is (see time_range_constraint.js).
73684
+ ,
73622
73685
 
73623
- "data-time-after": startId,
73624
- "data-time-min-duration": minDuration,
73625
- ...timeProps,
73626
- ...endTimeProps
73686
+ "data-time-after": startId,
73687
+ "data-time-min-duration": minDuration,
73688
+ ...timeProps,
73689
+ ...endTimeProps
73690
+ })
73627
73691
  })]
73628
73692
  })
73629
73693
  });
@@ -73742,6 +73806,27 @@ const resolveHourList = hours => {
73742
73806
  };
73743
73807
  const padTwo = value => String(value).padStart(2, "0");
73744
73808
 
73809
+ // A label and its wheels. Side by side, they are two items of the group's own
73810
+ // row. One above the other, they are one item: the two bounds then stand at
73811
+ // the same height and their wheels line up whatever the width of the words.
73812
+ const TimeBound = ({
73813
+ labelPosition,
73814
+ label,
73815
+ children
73816
+ }) => {
73817
+ if (labelPosition === "above") {
73818
+ return jsxs(Box, {
73819
+ flex: "y",
73820
+ alignX: "center",
73821
+ spacing: "xs",
73822
+ children: [label, children]
73823
+ });
73824
+ }
73825
+ return jsxs(Fragment$1, {
73826
+ children: [label, children]
73827
+ });
73828
+ };
73829
+
73745
73830
  // The two times as one span, { start, end } — the shape a pair carries.
73746
73831
  const aggregateSpan = childUIStateControllers => {
73747
73832
  const span = {};