@jsenv/navi 0.27.13 → 0.27.15

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.
@@ -18759,15 +18759,15 @@ const resolveValue = (replacements, key, fallback) => {
18759
18759
  return fallback;
18760
18760
  };
18761
18761
 
18762
- const DEFAULT_LANG$1 = "en";
18762
+ const DEFAULT_LANG = "en";
18763
18763
 
18764
18764
  const getBrowserLang = () => {
18765
18765
  if (typeof window === "undefined") {
18766
- return DEFAULT_LANG$1;
18766
+ return DEFAULT_LANG;
18767
18767
  }
18768
18768
  const { navigator } = window;
18769
18769
  if (typeof navigator === "undefined") {
18770
- return DEFAULT_LANG$1;
18770
+ return DEFAULT_LANG;
18771
18771
  }
18772
18772
  const { language } = navigator;
18773
18773
  if (typeof language === "string") {
@@ -18777,7 +18777,7 @@ const getBrowserLang = () => {
18777
18777
  if (Array.isArray(languages) && languages.length > 0) {
18778
18778
  return languages[0];
18779
18779
  }
18780
- return DEFAULT_LANG$1;
18780
+ return DEFAULT_LANG;
18781
18781
  };
18782
18782
 
18783
18783
  const langSignal = signal(getBrowserLang());
@@ -19019,6 +19019,41 @@ naviI18n.addAll({
19019
19019
  pt: "[day] às [time]",
19020
19020
  nl: "[day] om [time]",
19021
19021
  },
19022
+ // [duration] is replaced at runtime with the formatted duration string (e.g. "1h30", "45 min")
19023
+ "time.in_duration": {
19024
+ en: "in [duration]",
19025
+ fr: "dans [duration]",
19026
+ de: "in [duration]",
19027
+ es: "en [duration]",
19028
+ it: "tra [duration]",
19029
+ pt: "em [duration]",
19030
+ nl: "over [duration]",
19031
+ },
19032
+ // Compact duration unit symbols used in "1h30", "45min", etc.
19033
+ "time.duration.hour_symbol": {
19034
+ en: "h",
19035
+ fr: "h",
19036
+ de: "h",
19037
+ es: "h",
19038
+ it: "h",
19039
+ pt: "h",
19040
+ nl: "u",
19041
+ ja: "時間",
19042
+ zh: "小时",
19043
+ ko: "시간",
19044
+ },
19045
+ "time.duration.minute_symbol": {
19046
+ en: "min",
19047
+ fr: "min",
19048
+ de: "min",
19049
+ es: "min",
19050
+ it: "min",
19051
+ pt: "min",
19052
+ nl: "min",
19053
+ ja: "分",
19054
+ zh: "分",
19055
+ ko: "분",
19056
+ },
19022
19057
  });
19023
19058
 
19024
19059
  // List messages — override any key to customize list messages
@@ -19813,8 +19848,6 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-single-space");
19813
19848
  */
19814
19849
 
19815
19850
 
19816
- const DEFAULT_LANG = "en";
19817
-
19818
19851
  /**
19819
19852
  * Formats a date as a human-readable day, appending "(aujourd'hui)" or
19820
19853
  * "(demain)" when the date matches today or tomorrow.
@@ -19964,6 +19997,70 @@ const formatTime = (date, locale) => {
19964
19997
  }).format(date);
19965
19998
  };
19966
19999
 
20000
+ /**
20001
+ * Formats a duration expressed in minutes as a short human-readable string.
20002
+ * Uses Intl.DurationFormat when available, falls back to a compact notation.
20003
+ *
20004
+ * @param {number} minutes
20005
+ * @param {string} locale
20006
+ * @param {{ long?: boolean }} [options]
20007
+ *
20008
+ * @example
20009
+ * formatMinuteDuration(90, "fr") // "1h30" (compact, default)
20010
+ * formatMinuteDuration(90, "fr", { long: true }) // "1 heure 30" or "1 h 30 min" via Intl
20011
+ * formatMinuteDuration(45, "en") // "45min"
20012
+ * formatMinuteDuration(120, "fr") // "2h"
20013
+ */
20014
+ const formatMinuteDuration = (
20015
+ minutes,
20016
+ locale,
20017
+ { long = false } = {},
20018
+ ) => {
20019
+ const h = Math.floor(minutes / 60);
20020
+ const m = minutes % 60;
20021
+ if (long && typeof Intl.DurationFormat !== "undefined") {
20022
+ const fmt = new Intl.DurationFormat(locale, { style: "long" });
20023
+ if (h === 0) {
20024
+ return fmt.format({ minutes: m });
20025
+ }
20026
+ if (m === 0) {
20027
+ return fmt.format({ hours: h });
20028
+ }
20029
+ return fmt.format({ hours: h, minutes: m });
20030
+ }
20031
+ // Compact notation: "1h30", "45min", "2h"
20032
+ const hSym = naviI18n("time.duration.hour_symbol", undefined, {
20033
+ lang: locale,
20034
+ });
20035
+ const mSym = naviI18n("time.duration.minute_symbol", undefined, {
20036
+ lang: locale,
20037
+ });
20038
+ if (h === 0) {
20039
+ return `${m}${mSym}`;
20040
+ }
20041
+ if (m === 0) {
20042
+ return `${h}${hSym}`;
20043
+ }
20044
+ return `${h}${hSym}${String(m).padStart(2, "0")}`;
20045
+ };
20046
+
20047
+ /**
20048
+ * Formats a duration expressed in hours (possibly fractional) as a short human-readable string.
20049
+ *
20050
+ * @param {number} hours
20051
+ * @param {string} locale
20052
+ * @param {{ long?: boolean }} [options]
20053
+ *
20054
+ * @example
20055
+ * formatHourDuration(1.5, "fr") // "1h30"
20056
+ * formatHourDuration(1.5, "fr", { long: true }) // "1 heure 30" or "1 h 30 min" via Intl
20057
+ * formatHourDuration(2, "en") // "2h"
20058
+ */
20059
+ const formatHourDuration = (hours, locale, { long = false } = {}) => {
20060
+ const totalMinutes = Math.round(hours * 60);
20061
+ return formatMinuteDuration(totalMinutes, locale, { long });
20062
+ };
20063
+
19967
20064
  /**
19968
20065
  * Formats a date relative to now: "il y a 3 jours", "dans 2 heures", etc.
19969
20066
  */
@@ -20075,7 +20172,14 @@ const formatFuture = (date, diff, locale, { now }) => {
20075
20172
  if (minutes === 0) {
20076
20173
  return rtf.format(hours, "hour");
20077
20174
  }
20078
- return formatHoursAndMinutes(hours, minutes, locale);
20175
+ const duration = formatMinuteDuration(hours * 60 + minutes, locale, {
20176
+ long: true,
20177
+ });
20178
+ const template = naviI18n("time.in_duration", undefined, { lang: locale });
20179
+ if (template !== "time.in_duration") {
20180
+ return template.replace("[duration]", duration);
20181
+ }
20182
+ return `in ${duration}`;
20079
20183
  }
20080
20184
 
20081
20185
  // < 6h → "dans X heures" (precise enough, skip tomorrow label)
@@ -20133,24 +20237,6 @@ const formatTomorrowAt = (date, locale) => {
20133
20237
  return `${dayLabel} ${timeLabel}`;
20134
20238
  };
20135
20239
 
20136
- // "dans 1 heure 30" — colloquial format, built per language.
20137
- // The plural suffix is applied inline because it depends on the count;
20138
- // a plain string template cannot express this, so we keep it in JS.
20139
- const formatHoursAndMinutes = (hours, minutes, locale) => {
20140
- const lang = (locale || "").split("-")[0];
20141
- const templates = {
20142
- fr: (h, m) => `dans ${h} heure${h > 1 ? "s" : ""} ${m}`,
20143
- en: (h, m) => `in ${h} hour${h > 1 ? "s" : ""} ${m}`,
20144
- de: (h, m) => `in ${h} Stunde${h > 1 ? "n" : ""} ${m}`,
20145
- es: (h, m) => `en ${h} hora${h > 1 ? "s" : ""} ${m}`,
20146
- it: (h, m) => `tra ${h} ora${h > 1 ? "e" : ""} ${m}`,
20147
- pt: (h, m) => `em ${h} hora${h > 1 ? "s" : ""} ${m}`,
20148
- nl: (h, m) => `over ${h} uur ${m}`,
20149
- };
20150
- const template = templates[lang] || templates[DEFAULT_LANG];
20151
- return template(hours, minutes);
20152
- };
20153
-
20154
20240
  const getLessThanMinuteText = (locale) => {
20155
20241
  return naviI18n("time.less_than_minute", undefined, { lang: locale });
20156
20242
  };
@@ -32612,6 +32698,11 @@ const Time = props => {
32612
32698
  ...props
32613
32699
  });
32614
32700
  }
32701
+ if (type === "hour") {
32702
+ return jsx(TimeHour, {
32703
+ ...props
32704
+ });
32705
+ }
32615
32706
  return jsx(TimeRelative, {
32616
32707
  ...props
32617
32708
  });
@@ -32754,6 +32845,7 @@ const TimeDatetime = ({
32754
32845
  const TimeTime = ({
32755
32846
  children,
32756
32847
  locale,
32848
+ durationFormat,
32757
32849
  ...props
32758
32850
  }) => {
32759
32851
  const lang = locale || langSignal.value;
@@ -32776,10 +32868,21 @@ const TimeTime = ({
32776
32868
  children: children
32777
32869
  });
32778
32870
  }
32779
- const text = formatTime(date, lang);
32780
32871
  const hh = String(date.getHours()).padStart(2, "0");
32781
32872
  const mm = String(date.getMinutes()).padStart(2, "0");
32782
32873
  const dateTime = `${hh}:${mm}`; // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time#datetime
32874
+ if (durationFormat) {
32875
+ const totalMinutes = date.getHours() * 60 + date.getMinutes();
32876
+ const text = formatMinuteDuration(totalMinutes, lang, {
32877
+ long: durationFormat === "long"
32878
+ });
32879
+ return jsx(TimeText, {
32880
+ dateTime: dateTime,
32881
+ ...props,
32882
+ children: text
32883
+ });
32884
+ }
32885
+ const text = formatTime(date, lang);
32783
32886
  return jsx(TimeText, {
32784
32887
  dateTime: dateTime,
32785
32888
  ...props,
@@ -32789,13 +32892,15 @@ const TimeTime = ({
32789
32892
  const TimeMinute = ({
32790
32893
  children,
32791
32894
  locale,
32895
+ long,
32896
+ timeString,
32792
32897
  ...props
32793
32898
  }) => {
32794
32899
  const lang = locale || langSignal.value;
32795
32900
  if (children === undefined) {
32796
32901
  return jsx(TimeText, {
32797
32902
  ...props,
32798
- children: "--:--"
32903
+ children: timeString ? "--:--" : "--"
32799
32904
  });
32800
32905
  }
32801
32906
  let minutes;
@@ -32811,17 +32916,60 @@ const TimeMinute = ({
32811
32916
  }
32812
32917
  minutes = childrenAsNumber;
32813
32918
  }
32814
- const date = new Date(1970, 0, 1, Math.floor(minutes / 60), minutes % 60, 0);
32815
- const hh = String(date.getHours()).padStart(2, "0");
32816
- const mm = String(date.getMinutes()).padStart(2, "0");
32919
+ const totalHours = Math.floor(minutes / 60);
32920
+ const remainingMinutes = minutes % 60;
32921
+ const hh = String(totalHours).padStart(2, "0");
32922
+ const mm = String(remainingMinutes).padStart(2, "0");
32817
32923
  const dateTime = `${hh}:${mm}`;
32818
- const text = formatTime(date, lang);
32924
+ let text;
32925
+ if (timeString) {
32926
+ const date = new Date(1970, 0, 1, totalHours, remainingMinutes, 0);
32927
+ text = formatTime(date, lang);
32928
+ } else {
32929
+ text = formatMinuteDuration(minutes, lang, {
32930
+ long
32931
+ });
32932
+ }
32819
32933
  return jsx(TimeText, {
32820
32934
  dateTime: dateTime,
32821
32935
  ...props,
32822
32936
  children: text
32823
32937
  });
32824
32938
  };
32939
+ const TimeHour = ({
32940
+ children,
32941
+ locale,
32942
+ long,
32943
+ ...props
32944
+ }) => {
32945
+ const lang = locale || langSignal.value;
32946
+ if (children === undefined) {
32947
+ return jsx(TimeText, {
32948
+ ...props,
32949
+ children: "--"
32950
+ });
32951
+ }
32952
+ let hours;
32953
+ if (typeof children === "number") {
32954
+ hours = children;
32955
+ } else {
32956
+ const childrenAsNumber = Number(children);
32957
+ if (isNaN(childrenAsNumber)) {
32958
+ return jsx(TimeText, {
32959
+ ...props,
32960
+ children: children
32961
+ });
32962
+ }
32963
+ hours = childrenAsNumber;
32964
+ }
32965
+ const text = formatHourDuration(hours, lang, {
32966
+ long
32967
+ });
32968
+ return jsx(TimeText, {
32969
+ ...props,
32970
+ children: text
32971
+ });
32972
+ };
32825
32973
  const TimeRelative = ({
32826
32974
  children,
32827
32975
  locale,
@@ -33051,7 +33199,7 @@ const PickerTime = props => {
33051
33199
  type: "time"
33052
33200
  });
33053
33201
  };
33054
- const PickerTimeUI = () => {
33202
+ const PickerTimeUI = props => {
33055
33203
  const {
33056
33204
  value,
33057
33205
  placeholder
@@ -33060,7 +33208,8 @@ const PickerTimeUI = () => {
33060
33208
  if (!placeholder) {
33061
33209
  return jsx(Time, {
33062
33210
  type: "time",
33063
- color: "var(--picker-placeholder-color"
33211
+ color: "var(--picker-placeholder-color",
33212
+ ...props
33064
33213
  });
33065
33214
  }
33066
33215
  return jsx(PickerPlaceholder, {
@@ -33069,6 +33218,7 @@ const PickerTimeUI = () => {
33069
33218
  }
33070
33219
  return jsx(Time, {
33071
33220
  type: "time",
33221
+ ...props,
33072
33222
  children: value
33073
33223
  });
33074
33224
  };
@@ -35726,7 +35876,8 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
35726
35876
  )
35727
35877
  );
35728
35878
  --x-picker-padding-right: calc(
35729
- var(--x-picker-padding-right-base) + var(--picker-right-slot-size) - 2px
35879
+ var(--x-picker-padding-right-base) + var(--picker-right-slot-size) +
35880
+ var(--picker-right-slot-size) * 0.25
35730
35881
  );
35731
35882
  --x-picker-padding-left: var(
35732
35883
  --picker-padding-left,