@jsenv/navi 0.27.20 → 0.27.22

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.
@@ -18403,6 +18403,14 @@ naviI18n.addAll({
18403
18403
  },
18404
18404
  });
18405
18405
 
18406
+ // Badge list messages
18407
+ naviI18n.addAll({
18408
+ "badge_list.more": {
18409
+ en: "+[count] more",
18410
+ fr: "+[count] de plus",
18411
+ },
18412
+ });
18413
+
18406
18414
  // Constraint validation messages — override any key to customize error messages
18407
18415
  naviI18n.addAll({
18408
18416
  "constraint.available": {
@@ -32019,19 +32027,6 @@ const RadioGroupInterface = props => {
32019
32027
  });
32020
32028
  };
32021
32029
 
32022
- const PickerPlaceholder = props => {
32023
- return jsx(Text, {
32024
- className: "navi_picker_placeholder",
32025
- ...props
32026
- });
32027
- };
32028
- const PickerValue = props => {
32029
- return jsx(Text, {
32030
- className: "navi_picker_value",
32031
- ...props
32032
- });
32033
- };
32034
-
32035
32030
  const PickerContext = createContext();
32036
32031
 
32037
32032
  const windowWidthSignal = signal(window.innerWidth);
@@ -32388,7 +32383,10 @@ const Popover = props => {
32388
32383
  popoverEl.removeAttribute("data-anchor-hidden");
32389
32384
  positionPopover(event);
32390
32385
  }, {
32391
- event: e
32386
+ event: e,
32387
+ // it's ok for the popover to become unsync with the anchor size
32388
+ // (we could even argue it's a feature as it helps to keep the popover position stable)
32389
+ skipElementResize: true
32392
32390
  });
32393
32391
  addCleanup(() => {
32394
32392
  rectEffect.disconnect();
@@ -33458,7 +33456,7 @@ const PickerText = props => {
33458
33456
  const PickerArray = props => {
33459
33457
  const Next = useNextResolver();
33460
33458
  return jsx(Next, {
33461
- "data-multiline": "",
33459
+ maxRows: 3,
33462
33460
  ui: jsx(PickerArrayUI, {}),
33463
33461
  ...props,
33464
33462
  type: "navi_picker"
@@ -33467,19 +33465,20 @@ const PickerArray = props => {
33467
33465
  const PickerArrayUI = () => {
33468
33466
  const {
33469
33467
  value,
33470
- placeholder
33468
+ placeholder,
33469
+ maxRows
33471
33470
  } = useContext(PickerContext);
33472
33471
  if (!value || value.length === 0) {
33473
33472
  if (!placeholder) {
33474
33473
  return null;
33475
33474
  }
33476
- return jsx(PickerPlaceholder, {
33477
- children: placeholder
33478
- });
33475
+ return placeholder;
33479
33476
  }
33480
- return jsx(PickerValue, {
33477
+ return jsx(Text, {
33481
33478
  spacing: ", ",
33482
33479
  shrinkWrap: true,
33480
+ lineClamp: maxRows > 1 ? maxRows : undefined,
33481
+ overflowEllipsis: maxRows === 1 ? true : undefined,
33483
33482
  children: value.map(item => {
33484
33483
  return jsx("span", {
33485
33484
  children: item
@@ -33505,9 +33504,7 @@ const PickerColorUI = () => {
33505
33504
  if (!placeholder) {
33506
33505
  return jsx(Color, {});
33507
33506
  }
33508
- return jsx(PickerPlaceholder, {
33509
- children: placeholder
33510
- });
33507
+ return placeholder;
33511
33508
  }
33512
33509
  return jsx(Color, {
33513
33510
  children: value
@@ -33535,9 +33532,7 @@ const PickerDateUI = props => {
33535
33532
  ...props
33536
33533
  });
33537
33534
  }
33538
- return jsx(PickerPlaceholder, {
33539
- children: placeholder
33540
- });
33535
+ return placeholder;
33541
33536
  }
33542
33537
  return jsx(Time, {
33543
33538
  type: "date",
@@ -33567,9 +33562,7 @@ const PickerMonthUI = () => {
33567
33562
  color: "var(--picker-placeholder-color"
33568
33563
  });
33569
33564
  }
33570
- return jsx(PickerPlaceholder, {
33571
- children: placeholder
33572
- });
33565
+ return placeholder;
33573
33566
  }
33574
33567
  return jsx(Time, {
33575
33568
  type: "month",
@@ -33598,9 +33591,7 @@ const PickerWeekUI = () => {
33598
33591
  color: "var(--picker-placeholder-color"
33599
33592
  });
33600
33593
  }
33601
- return jsx(PickerPlaceholder, {
33602
- children: placeholder
33603
- });
33594
+ return placeholder;
33604
33595
  }
33605
33596
  return jsx(Time, {
33606
33597
  type: "week",
@@ -33630,9 +33621,7 @@ const PickerTimeUI = props => {
33630
33621
  ...props
33631
33622
  });
33632
33623
  }
33633
- return jsx(PickerPlaceholder, {
33634
- children: placeholder
33635
- });
33624
+ return placeholder;
33636
33625
  }
33637
33626
  return jsx(Time, {
33638
33627
  type: "time",
@@ -33661,9 +33650,7 @@ const PickerDatetimeUI = () => {
33661
33650
  color: "var(--picker-placeholder-color"
33662
33651
  });
33663
33652
  }
33664
- return jsx(PickerPlaceholder, {
33665
- children: placeholder
33666
- });
33653
+ return placeholder;
33667
33654
  }
33668
33655
  return jsx(Time, {
33669
33656
  type: "datetime",
@@ -33688,14 +33675,10 @@ const PickerFileUI = () => {
33688
33675
  if (!placeholder) {
33689
33676
  return null;
33690
33677
  }
33691
- return jsx(PickerPlaceholder, {
33692
- children: "placeholder"
33693
- });
33678
+ return placeholder;
33694
33679
  }
33695
33680
  // value is a FileList-like string from the input; display file names
33696
- return jsx(PickerValue, {
33697
- children: value
33698
- });
33681
+ return value;
33699
33682
  };
33700
33683
  const PencilSvg = () => {
33701
33684
  return jsx("svg", {
@@ -36368,7 +36351,6 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36368
36351
  --picker-border-radius: 2px;
36369
36352
  --picker-outline-width: 1px;
36370
36353
  --picker-border-width: 1px;
36371
- --picker-font-size: 14px;
36372
36354
  --picker-padding-x-default: 8px;
36373
36355
  --picker-padding-y-default: 5px;
36374
36356
  --picker-outline-color: var(--navi-focus-outline-color);
@@ -36382,7 +36364,6 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36382
36364
  transparent
36383
36365
  );
36384
36366
  --picker-color-dimmed: color-mix(in srgb, currentColor 60%, transparent);
36385
- --picker-right-slot-size: 1em;
36386
36367
  /* Hover */
36387
36368
  --picker-border-color-hover: color-mix(
36388
36369
  in srgb,
@@ -36435,17 +36416,13 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36435
36416
  var(--picker-padding, var(--picker-padding-y-default))
36436
36417
  )
36437
36418
  );
36438
- --x-picker-padding-right-base: var(
36419
+ --x-picker-padding-right: var(
36439
36420
  --picker-padding-right,
36440
36421
  var(
36441
36422
  --picker-padding-x,
36442
36423
  var(--picker-padding, var(--picker-padding-x-default))
36443
36424
  )
36444
36425
  );
36445
- --x-picker-padding-right: calc(
36446
- var(--x-picker-padding-right-base) + var(--picker-right-slot-size) +
36447
- var(--picker-right-slot-size) * 0.25
36448
- );
36449
36426
  --x-picker-padding-left: var(
36450
36427
  --picker-padding-left,
36451
36428
  var(
@@ -36464,7 +36441,7 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36464
36441
  --x-picker-icon-color: var(--picker-icon-color);
36465
36442
 
36466
36443
  position: relative;
36467
- display: inline-block;
36444
+ display: inline-flex;
36468
36445
  box-sizing: border-box;
36469
36446
  max-width: 100%;
36470
36447
  min-height: calc(
@@ -36475,8 +36452,9 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36475
36452
  padding-bottom: var(--x-picker-padding-bottom);
36476
36453
  padding-left: var(--x-picker-padding-left);
36477
36454
  flex-direction: row;
36455
+ align-items: center;
36456
+ gap: var(--navi-xs);
36478
36457
  color: var(--x-picker-color);
36479
- font-size: var(--picker-font-size);
36480
36458
  text-align: inherit;
36481
36459
  text-overflow: ellipsis;
36482
36460
  background-color: var(--x-picker-background-color);
@@ -36494,29 +36472,25 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36494
36472
  overflow: hidden;
36495
36473
 
36496
36474
  .navi_picker_value {
36497
- display: block;
36475
+ display: inline-block;
36498
36476
  min-width: 0;
36499
36477
  max-width: 100%;
36478
+ flex-grow: 1;
36500
36479
  text-overflow: ellipsis;
36501
36480
  white-space: nowrap;
36502
36481
  overflow: hidden;
36503
- }
36504
- .navi_picker_placeholder {
36505
- display: block;
36506
- max-width: 100%;
36507
- color: var(--picker-placeholder-color);
36508
- text-overflow: ellipsis;
36509
- white-space: nowrap;
36510
- overflow: hidden;
36482
+
36483
+ &[navi-placeholder] {
36484
+ color: var(--picker-placeholder-color);
36485
+ }
36511
36486
  }
36512
36487
  .navi_picker_right_slot {
36513
- position: absolute;
36514
- top: 0;
36515
- right: var(--x-picker-padding-right-base);
36516
36488
  display: inline-flex;
36517
- width: var(--picker-right-slot-size);
36518
- padding-top: var(--x-picker-padding-top);
36489
+ height: 1em;
36490
+ height: 1lh;
36519
36491
  flex-shrink: 0;
36492
+ align-items: center;
36493
+ align-self: flex-start;
36520
36494
  justify-content: center;
36521
36495
  color: var(--x-picker-icon-color);
36522
36496
  transform: translateX(25%);
@@ -36536,14 +36510,13 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36536
36510
  pointer-events: none;
36537
36511
  }
36538
36512
 
36539
- &[data-multiline] {
36513
+ &[data-line-clamp] {
36540
36514
  overflow-wrap: anywhere;
36541
-
36542
- .navi_picker_placeholder {
36543
- white-space: normal;
36544
- }
36545
36515
  .navi_picker_value {
36516
+ display: -webkit-box;
36546
36517
  white-space: normal;
36518
+ -webkit-box-orient: vertical;
36519
+ -webkit-line-clamp: var(--picker-max-rows);
36547
36520
  }
36548
36521
  }
36549
36522
 
@@ -36617,8 +36590,8 @@ const PickerButton = props => {
36617
36590
  ref,
36618
36591
  icon,
36619
36592
  placeholder,
36620
- singleLine,
36621
- ui
36593
+ ui,
36594
+ maxRows
36622
36595
  } = props;
36623
36596
  const inputRef = useRef(null);
36624
36597
  const [inputProps, pickerRemainingProps] = useControlProps({
@@ -36640,6 +36613,7 @@ const PickerButton = props => {
36640
36613
  children
36641
36614
  } = inputProps;
36642
36615
  const loading = basePseudoState[":-navi-loading"];
36616
+ const hasLineClamp = maxRows && maxRows > 1;
36643
36617
  return jsxs(Box, {
36644
36618
  as: "button",
36645
36619
  ref: ref,
@@ -36648,7 +36622,10 @@ const PickerButton = props => {
36648
36622
  "navi-has-placeholder": placeholder ? "" : undefined,
36649
36623
  pseudoClasses: PICKER_BUTTON_PSEUDO_CLASSES,
36650
36624
  disabled: disabled,
36651
- "data-single-line": singleLine ? "" : undefined,
36625
+ "data-line-clamp": hasLineClamp ? "" : undefined,
36626
+ style: {
36627
+ "--picker-max-rows": maxRows || -1
36628
+ },
36652
36629
  ...pickerRemainingProps,
36653
36630
  basePseudoState: basePseudoState,
36654
36631
  styleCSSVars: PickerStyleCSSVars
@@ -36659,7 +36636,7 @@ const PickerButton = props => {
36659
36636
  id: id,
36660
36637
  icon: undefined,
36661
36638
  ui: undefined,
36662
- singleLine: undefined,
36639
+ maxRows: undefined,
36663
36640
  dayLabel: undefined
36664
36641
  // The button is handling the pointer interactions
36665
36642
  ,
@@ -36690,12 +36667,17 @@ const PickerButton = props => {
36690
36667
  onMouseDown: undefined,
36691
36668
  onClick: undefined,
36692
36669
  onKeyDown: undefined
36693
- }), jsx(PickerContext.Provider, {
36694
- value: {
36695
- value,
36696
- placeholder
36697
- },
36698
- children: ui === undefined ? jsx(PickerDefaultUI, {}) : ui
36670
+ }), jsx(Text, {
36671
+ className: "navi_picker_value",
36672
+ "navi-placeholder": value === undefined || value === "" ? "" : undefined,
36673
+ children: jsx(PickerContext.Provider, {
36674
+ value: {
36675
+ value,
36676
+ placeholder,
36677
+ maxRows
36678
+ },
36679
+ children: ui === undefined ? jsx(PickerDefaultUI, {}) : ui
36680
+ })
36699
36681
  }), jsx("span", {
36700
36682
  className: "navi_picker_right_slot",
36701
36683
  children: jsx(Icon, {
@@ -36759,13 +36741,9 @@ const PickerDefaultUI = () => {
36759
36741
  if (!placeholder) {
36760
36742
  return null;
36761
36743
  }
36762
- return jsx(PickerPlaceholder, {
36763
- children: placeholder
36764
- });
36744
+ return placeholder;
36765
36745
  }
36766
- return jsx(PickerValue, {
36767
- children: value
36768
- });
36746
+ return value;
36769
36747
  };
36770
36748
  const PickerFirstResolver = props => {
36771
36749
  const Next = useNextResolver();
@@ -36779,8 +36757,6 @@ const PickerFirstResolver = props => {
36779
36757
  });
36780
36758
  };
36781
36759
  const Picker = createComponentResolver([PickerFirstResolver, ...pickerResolvers, PickerButton]);
36782
- Picker.Placeholder = PickerPlaceholder;
36783
- Picker.Value = PickerValue;
36784
36760
  Picker.UI = PickerDefaultUI;
36785
36761
  Picker.UI.Date = PickerDateUI;
36786
36762
  Picker.UI.Time = PickerTimeUI;
@@ -41340,63 +41316,96 @@ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
41340
41316
  }
41341
41317
  .navi_badge_list {
41342
41318
  flex-wrap: wrap;
41319
+
41320
+ &[navi-badge-list-clone] {
41321
+ position: absolute;
41322
+ width: 100%;
41323
+ visibility: hidden;
41324
+ pointer-events: none;
41325
+ }
41326
+ }
41327
+
41328
+ .navi_badge.navi_badge_more {
41329
+ white-space: nowrap;
41343
41330
  }
41344
41331
  `;
41345
41332
  const BadgeList = ({
41346
41333
  fallback,
41347
41334
  children,
41348
- className,
41349
41335
  shrinkWrap = true,
41336
+ max,
41337
+ maxRows,
41350
41338
  ...props
41351
41339
  }) => {
41352
41340
  import.meta.css = [css$9, "@jsenv/navi/src/text/badge_list.jsx"];
41353
- const defaultRef = useRef();
41354
- props.ref = props.ref || defaultRef;
41355
- const {
41356
- ref
41357
- } = props;
41341
+ const measureRef = useRef();
41342
+ const visibleRef = useRef();
41358
41343
  useLayoutEffect(() => {
41359
- if (!shrinkWrap) {
41360
- return undefined;
41361
- }
41362
- const el = ref.current;
41363
- if (!el) {
41344
+ const measureEl = measureRef.current;
41345
+ const visibleEl = visibleRef.current;
41346
+ if (!measureEl || !visibleEl) {
41364
41347
  return undefined;
41365
41348
  }
41366
41349
  let observer;
41367
41350
  let rafId;
41368
- const applyWidth = () => {
41369
- el.style.width = "";
41370
- const optimalWidth = measureWidestChildRow(el);
41371
- if (optimalWidth === null) {
41372
- return;
41351
+ const measure = () => {
41352
+ visibleEl.style.width = "";
41353
+ if (shrinkWrap) {
41354
+ const optimalWidth = measureWidestChildRow(measureEl);
41355
+ if (optimalWidth !== null) {
41356
+ visibleEl.style.width = `${Math.ceil(optimalWidth)}px`;
41357
+ }
41373
41358
  }
41374
- el.style.width = `${Math.ceil(optimalWidth)}px`;
41375
41359
  };
41376
- applyWidth();
41377
- const parent = el.parentElement;
41378
- if (parent) {
41379
- observer = new ResizeObserver(() => {
41380
- cancelAnimationFrame(rafId);
41381
- rafId = requestAnimationFrame(applyWidth);
41382
- });
41383
- observer.observe(parent);
41360
+ measure();
41361
+ const onResize = () => {
41362
+ cancelAnimationFrame(rafId);
41363
+ rafId = requestAnimationFrame(measure);
41364
+ };
41365
+ const outerParent = measureEl.parentElement?.parentElement;
41366
+ if (outerParent) {
41367
+ observer = new ResizeObserver(onResize);
41368
+ observer.observe(outerParent);
41384
41369
  }
41385
- window.addEventListener("resize", applyWidth);
41370
+ window.addEventListener("resize", onResize);
41386
41371
  return () => {
41387
41372
  cancelAnimationFrame(rafId);
41388
41373
  observer?.disconnect();
41389
- window.removeEventListener("resize", applyWidth);
41374
+ window.removeEventListener("resize", onResize);
41390
41375
  };
41391
- });
41376
+ }, [shrinkWrap, children]);
41392
41377
  const childArray = toChildArray(children);
41393
- return jsx(Box, {
41378
+ const hasMax = max !== undefined && childArray.length > max;
41379
+ const visibleChildren = hasMax ? childArray.slice(0, max - 1) : childArray;
41380
+ const hiddenCount = hasMax ? childArray.length - (max - 1) : 0;
41381
+ const sharedProps = {
41382
+ inline: true,
41394
41383
  flex: "x",
41395
41384
  alignY: "center",
41396
41385
  spacing: "xs",
41397
- className: withPropsClassName("navi_badge_list", className),
41398
- ...props,
41399
- children: childArray.length ? children : fallback
41386
+ ...props
41387
+ };
41388
+ return jsxs(Box, {
41389
+ relative: true,
41390
+ children: [jsx(Box, {
41391
+ baseClassName: "navi_badge_list",
41392
+ ...sharedProps,
41393
+ ref: measureRef,
41394
+ "aria-hidden": "true",
41395
+ "navi-badge-list-clone": "",
41396
+ children: childArray
41397
+ }), jsxs(Box, {
41398
+ baseClassName: "navi_badge_list",
41399
+ ...sharedProps,
41400
+ ref: visibleRef,
41401
+ lineClamp: maxRows,
41402
+ children: [visibleChildren.length ? visibleChildren : fallback, hiddenCount > 0 && jsx(Badge, {
41403
+ className: "navi_badge_more",
41404
+ children: naviI18n("badge_list.more", {
41405
+ count: hiddenCount
41406
+ })
41407
+ })]
41408
+ })]
41400
41409
  });
41401
41410
  };
41402
41411