@jsenv/navi 0.27.20 → 0.27.21

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"
@@ -33473,11 +33471,9 @@ const PickerArrayUI = () => {
33473
33471
  if (!placeholder) {
33474
33472
  return null;
33475
33473
  }
33476
- return jsx(PickerPlaceholder, {
33477
- children: placeholder
33478
- });
33474
+ return placeholder;
33479
33475
  }
33480
- return jsx(PickerValue, {
33476
+ return jsx(Text, {
33481
33477
  spacing: ", ",
33482
33478
  shrinkWrap: true,
33483
33479
  children: value.map(item => {
@@ -33505,9 +33501,7 @@ const PickerColorUI = () => {
33505
33501
  if (!placeholder) {
33506
33502
  return jsx(Color, {});
33507
33503
  }
33508
- return jsx(PickerPlaceholder, {
33509
- children: placeholder
33510
- });
33504
+ return placeholder;
33511
33505
  }
33512
33506
  return jsx(Color, {
33513
33507
  children: value
@@ -33535,9 +33529,7 @@ const PickerDateUI = props => {
33535
33529
  ...props
33536
33530
  });
33537
33531
  }
33538
- return jsx(PickerPlaceholder, {
33539
- children: placeholder
33540
- });
33532
+ return placeholder;
33541
33533
  }
33542
33534
  return jsx(Time, {
33543
33535
  type: "date",
@@ -33567,9 +33559,7 @@ const PickerMonthUI = () => {
33567
33559
  color: "var(--picker-placeholder-color"
33568
33560
  });
33569
33561
  }
33570
- return jsx(PickerPlaceholder, {
33571
- children: placeholder
33572
- });
33562
+ return placeholder;
33573
33563
  }
33574
33564
  return jsx(Time, {
33575
33565
  type: "month",
@@ -33598,9 +33588,7 @@ const PickerWeekUI = () => {
33598
33588
  color: "var(--picker-placeholder-color"
33599
33589
  });
33600
33590
  }
33601
- return jsx(PickerPlaceholder, {
33602
- children: placeholder
33603
- });
33591
+ return placeholder;
33604
33592
  }
33605
33593
  return jsx(Time, {
33606
33594
  type: "week",
@@ -33630,9 +33618,7 @@ const PickerTimeUI = props => {
33630
33618
  ...props
33631
33619
  });
33632
33620
  }
33633
- return jsx(PickerPlaceholder, {
33634
- children: placeholder
33635
- });
33621
+ return placeholder;
33636
33622
  }
33637
33623
  return jsx(Time, {
33638
33624
  type: "time",
@@ -33661,9 +33647,7 @@ const PickerDatetimeUI = () => {
33661
33647
  color: "var(--picker-placeholder-color"
33662
33648
  });
33663
33649
  }
33664
- return jsx(PickerPlaceholder, {
33665
- children: placeholder
33666
- });
33650
+ return placeholder;
33667
33651
  }
33668
33652
  return jsx(Time, {
33669
33653
  type: "datetime",
@@ -33688,14 +33672,10 @@ const PickerFileUI = () => {
33688
33672
  if (!placeholder) {
33689
33673
  return null;
33690
33674
  }
33691
- return jsx(PickerPlaceholder, {
33692
- children: "placeholder"
33693
- });
33675
+ return placeholder;
33694
33676
  }
33695
33677
  // value is a FileList-like string from the input; display file names
33696
- return jsx(PickerValue, {
33697
- children: value
33698
- });
33678
+ return value;
33699
33679
  };
33700
33680
  const PencilSvg = () => {
33701
33681
  return jsx("svg", {
@@ -36368,7 +36348,6 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36368
36348
  --picker-border-radius: 2px;
36369
36349
  --picker-outline-width: 1px;
36370
36350
  --picker-border-width: 1px;
36371
- --picker-font-size: 14px;
36372
36351
  --picker-padding-x-default: 8px;
36373
36352
  --picker-padding-y-default: 5px;
36374
36353
  --picker-outline-color: var(--navi-focus-outline-color);
@@ -36382,7 +36361,6 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36382
36361
  transparent
36383
36362
  );
36384
36363
  --picker-color-dimmed: color-mix(in srgb, currentColor 60%, transparent);
36385
- --picker-right-slot-size: 1em;
36386
36364
  /* Hover */
36387
36365
  --picker-border-color-hover: color-mix(
36388
36366
  in srgb,
@@ -36435,17 +36413,13 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36435
36413
  var(--picker-padding, var(--picker-padding-y-default))
36436
36414
  )
36437
36415
  );
36438
- --x-picker-padding-right-base: var(
36416
+ --x-picker-padding-right: var(
36439
36417
  --picker-padding-right,
36440
36418
  var(
36441
36419
  --picker-padding-x,
36442
36420
  var(--picker-padding, var(--picker-padding-x-default))
36443
36421
  )
36444
36422
  );
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
36423
  --x-picker-padding-left: var(
36450
36424
  --picker-padding-left,
36451
36425
  var(
@@ -36464,7 +36438,7 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36464
36438
  --x-picker-icon-color: var(--picker-icon-color);
36465
36439
 
36466
36440
  position: relative;
36467
- display: inline-block;
36441
+ display: inline-flex;
36468
36442
  box-sizing: border-box;
36469
36443
  max-width: 100%;
36470
36444
  min-height: calc(
@@ -36475,8 +36449,9 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36475
36449
  padding-bottom: var(--x-picker-padding-bottom);
36476
36450
  padding-left: var(--x-picker-padding-left);
36477
36451
  flex-direction: row;
36452
+ align-items: center;
36453
+ gap: var(--navi-xs);
36478
36454
  color: var(--x-picker-color);
36479
- font-size: var(--picker-font-size);
36480
36455
  text-align: inherit;
36481
36456
  text-overflow: ellipsis;
36482
36457
  background-color: var(--x-picker-background-color);
@@ -36494,29 +36469,32 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36494
36469
  overflow: hidden;
36495
36470
 
36496
36471
  .navi_picker_value {
36497
- display: block;
36472
+ display: inline-block;
36498
36473
  min-width: 0;
36499
36474
  max-width: 100%;
36475
+ flex-grow: 1;
36500
36476
  text-overflow: ellipsis;
36501
36477
  white-space: nowrap;
36502
36478
  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;
36479
+
36480
+ &[navi-placeholder] {
36481
+ color: var(--picker-placeholder-color);
36482
+ }
36483
+
36484
+ .navi_text:not(.navi_more_badge) {
36485
+ max-width: 100%;
36486
+ text-overflow: inherit;
36487
+ vertical-align: middle; /* For some reason it's required to disminish inline-block height */
36488
+ overflow: inherit;
36489
+ }
36511
36490
  }
36512
36491
  .navi_picker_right_slot {
36513
- position: absolute;
36514
- top: 0;
36515
- right: var(--x-picker-padding-right-base);
36516
36492
  display: inline-flex;
36517
- width: var(--picker-right-slot-size);
36518
- padding-top: var(--x-picker-padding-top);
36493
+ height: 1em;
36494
+ height: 1lh;
36519
36495
  flex-shrink: 0;
36496
+ align-items: center;
36497
+ align-self: flex-start;
36520
36498
  justify-content: center;
36521
36499
  color: var(--x-picker-icon-color);
36522
36500
  transform: translateX(25%);
@@ -36536,14 +36514,13 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
36536
36514
  pointer-events: none;
36537
36515
  }
36538
36516
 
36539
- &[data-multiline] {
36517
+ &[data-line-clamp] {
36540
36518
  overflow-wrap: anywhere;
36541
-
36542
- .navi_picker_placeholder {
36543
- white-space: normal;
36544
- }
36545
36519
  .navi_picker_value {
36520
+ display: -webkit-box;
36546
36521
  white-space: normal;
36522
+ -webkit-box-orient: vertical;
36523
+ -webkit-line-clamp: var(--picker-max-rows);
36547
36524
  }
36548
36525
  }
36549
36526
 
@@ -36617,8 +36594,8 @@ const PickerButton = props => {
36617
36594
  ref,
36618
36595
  icon,
36619
36596
  placeholder,
36620
- singleLine,
36621
- ui
36597
+ ui,
36598
+ maxRows
36622
36599
  } = props;
36623
36600
  const inputRef = useRef(null);
36624
36601
  const [inputProps, pickerRemainingProps] = useControlProps({
@@ -36640,6 +36617,7 @@ const PickerButton = props => {
36640
36617
  children
36641
36618
  } = inputProps;
36642
36619
  const loading = basePseudoState[":-navi-loading"];
36620
+ const hasLineClamp = maxRows && maxRows > 1;
36643
36621
  return jsxs(Box, {
36644
36622
  as: "button",
36645
36623
  ref: ref,
@@ -36648,7 +36626,10 @@ const PickerButton = props => {
36648
36626
  "navi-has-placeholder": placeholder ? "" : undefined,
36649
36627
  pseudoClasses: PICKER_BUTTON_PSEUDO_CLASSES,
36650
36628
  disabled: disabled,
36651
- "data-single-line": singleLine ? "" : undefined,
36629
+ "data-line-clamp": hasLineClamp ? "" : undefined,
36630
+ style: {
36631
+ "--picker-max-rows": maxRows || -1
36632
+ },
36652
36633
  ...pickerRemainingProps,
36653
36634
  basePseudoState: basePseudoState,
36654
36635
  styleCSSVars: PickerStyleCSSVars
@@ -36659,7 +36640,7 @@ const PickerButton = props => {
36659
36640
  id: id,
36660
36641
  icon: undefined,
36661
36642
  ui: undefined,
36662
- singleLine: undefined,
36643
+ maxRows: undefined,
36663
36644
  dayLabel: undefined
36664
36645
  // The button is handling the pointer interactions
36665
36646
  ,
@@ -36690,12 +36671,17 @@ const PickerButton = props => {
36690
36671
  onMouseDown: undefined,
36691
36672
  onClick: undefined,
36692
36673
  onKeyDown: undefined
36693
- }), jsx(PickerContext.Provider, {
36694
- value: {
36695
- value,
36696
- placeholder
36697
- },
36698
- children: ui === undefined ? jsx(PickerDefaultUI, {}) : ui
36674
+ }), jsx(Text, {
36675
+ className: "navi_picker_value",
36676
+ "navi-placeholder": value === undefined || value === "" ? "" : undefined,
36677
+ children: jsx(PickerContext.Provider, {
36678
+ value: {
36679
+ value,
36680
+ placeholder,
36681
+ maxRows
36682
+ },
36683
+ children: ui === undefined ? jsx(PickerDefaultUI, {}) : ui
36684
+ })
36699
36685
  }), jsx("span", {
36700
36686
  className: "navi_picker_right_slot",
36701
36687
  children: jsx(Icon, {
@@ -36759,13 +36745,9 @@ const PickerDefaultUI = () => {
36759
36745
  if (!placeholder) {
36760
36746
  return null;
36761
36747
  }
36762
- return jsx(PickerPlaceholder, {
36763
- children: placeholder
36764
- });
36748
+ return placeholder;
36765
36749
  }
36766
- return jsx(PickerValue, {
36767
- children: value
36768
- });
36750
+ return value;
36769
36751
  };
36770
36752
  const PickerFirstResolver = props => {
36771
36753
  const Next = useNextResolver();
@@ -36779,8 +36761,6 @@ const PickerFirstResolver = props => {
36779
36761
  });
36780
36762
  };
36781
36763
  const Picker = createComponentResolver([PickerFirstResolver, ...pickerResolvers, PickerButton]);
36782
- Picker.Placeholder = PickerPlaceholder;
36783
- Picker.Value = PickerValue;
36784
36764
  Picker.UI = PickerDefaultUI;
36785
36765
  Picker.UI.Date = PickerDateUI;
36786
36766
  Picker.UI.Time = PickerTimeUI;
@@ -41340,63 +41320,96 @@ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
41340
41320
  }
41341
41321
  .navi_badge_list {
41342
41322
  flex-wrap: wrap;
41323
+
41324
+ &[navi-badge-list-clone] {
41325
+ position: absolute;
41326
+ width: 100%;
41327
+ visibility: hidden;
41328
+ pointer-events: none;
41329
+ }
41330
+ }
41331
+
41332
+ .navi_badge.navi_badge_more {
41333
+ white-space: nowrap;
41343
41334
  }
41344
41335
  `;
41345
41336
  const BadgeList = ({
41346
41337
  fallback,
41347
41338
  children,
41348
- className,
41349
41339
  shrinkWrap = true,
41340
+ max,
41341
+ maxRows,
41350
41342
  ...props
41351
41343
  }) => {
41352
41344
  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;
41345
+ const measureRef = useRef();
41346
+ const visibleRef = useRef();
41358
41347
  useLayoutEffect(() => {
41359
- if (!shrinkWrap) {
41360
- return undefined;
41361
- }
41362
- const el = ref.current;
41363
- if (!el) {
41348
+ const measureEl = measureRef.current;
41349
+ const visibleEl = visibleRef.current;
41350
+ if (!measureEl || !visibleEl) {
41364
41351
  return undefined;
41365
41352
  }
41366
41353
  let observer;
41367
41354
  let rafId;
41368
- const applyWidth = () => {
41369
- el.style.width = "";
41370
- const optimalWidth = measureWidestChildRow(el);
41371
- if (optimalWidth === null) {
41372
- return;
41355
+ const measure = () => {
41356
+ visibleEl.style.width = "";
41357
+ if (shrinkWrap) {
41358
+ const optimalWidth = measureWidestChildRow(measureEl);
41359
+ if (optimalWidth !== null) {
41360
+ visibleEl.style.width = `${Math.ceil(optimalWidth)}px`;
41361
+ }
41373
41362
  }
41374
- el.style.width = `${Math.ceil(optimalWidth)}px`;
41375
41363
  };
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);
41364
+ measure();
41365
+ const onResize = () => {
41366
+ cancelAnimationFrame(rafId);
41367
+ rafId = requestAnimationFrame(measure);
41368
+ };
41369
+ const outerParent = measureEl.parentElement?.parentElement;
41370
+ if (outerParent) {
41371
+ observer = new ResizeObserver(onResize);
41372
+ observer.observe(outerParent);
41384
41373
  }
41385
- window.addEventListener("resize", applyWidth);
41374
+ window.addEventListener("resize", onResize);
41386
41375
  return () => {
41387
41376
  cancelAnimationFrame(rafId);
41388
41377
  observer?.disconnect();
41389
- window.removeEventListener("resize", applyWidth);
41378
+ window.removeEventListener("resize", onResize);
41390
41379
  };
41391
- });
41380
+ }, [shrinkWrap, children]);
41392
41381
  const childArray = toChildArray(children);
41393
- return jsx(Box, {
41382
+ const hasMax = max !== undefined && childArray.length > max;
41383
+ const visibleChildren = hasMax ? childArray.slice(0, max - 1) : childArray;
41384
+ const hiddenCount = hasMax ? childArray.length - (max - 1) : 0;
41385
+ const sharedProps = {
41386
+ inline: true,
41394
41387
  flex: "x",
41395
41388
  alignY: "center",
41396
41389
  spacing: "xs",
41397
- className: withPropsClassName("navi_badge_list", className),
41398
- ...props,
41399
- children: childArray.length ? children : fallback
41390
+ ...props
41391
+ };
41392
+ return jsxs(Box, {
41393
+ relative: true,
41394
+ children: [jsx(Box, {
41395
+ baseClassName: "navi_badge_list",
41396
+ ...sharedProps,
41397
+ ref: measureRef,
41398
+ "aria-hidden": "true",
41399
+ "navi-badge-list-clone": "",
41400
+ children: childArray
41401
+ }), jsxs(Box, {
41402
+ baseClassName: "navi_badge_list",
41403
+ ...sharedProps,
41404
+ ref: visibleRef,
41405
+ lineClamp: maxRows,
41406
+ children: [visibleChildren.length ? visibleChildren : fallback, hiddenCount > 0 && jsx(Badge, {
41407
+ className: "navi_badge_more",
41408
+ children: naviI18n("badge_list.more", {
41409
+ count: hiddenCount
41410
+ })
41411
+ })]
41412
+ })]
41400
41413
  });
41401
41414
  };
41402
41415