@eagami/ui 5.14.0 → 5.14.1

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.
package/README.md CHANGED
@@ -19,7 +19,7 @@
19
19
 
20
20
  ## Why Eagami UI
21
21
 
22
- Angular teams usually reach for [Angular Material](https://material.angular.io), [PrimeNG](https://primeng.org), or a Tailwind copy-paste kit like [Spartan](https://spartan.ng). Eagami UI is different where it counts:
22
+ Angular teams usually reach for [Angular Material](https://material.angular.dev), [PrimeNG](https://primeng.org), or a Tailwind copy-paste kit like [Spartan](https://spartan.ng). Eagami UI is different where it counts:
23
23
 
24
24
  - **Themes to your brand.** Give it one color per role and it generates a full, accessibility-checked palette; every other style is a CSS variable you can override (see [design tokens](https://eagami.com/ui/design-tokens)). Light and dark are built in and follow the system preference.
25
25
  - **Lightweight.** One runtime dependency (`tslib`), no CSS framework, and standalone side-effect-free components, so your app bundles only what it imports (the whole library, every component and icon, is ~260 KB gzipped).
@@ -147,4 +147,4 @@ Eagami UI follows [Semantic Versioning](https://semver.org). Breaking changes sh
147
147
  | Rendering | Browser, SSR / prerender (Angular Universal), hydration |
148
148
  | Browsers | Last 2 stable versions of Chrome, Edge, Firefox (plus current ESR), Safari |
149
149
 
150
- > **Upgrading from v0.x?** See [MIGRATION.md](MIGRATION.md).
150
+ > **Upgrading across a major version?** See [MIGRATION.md](MIGRATION.md).
@@ -7851,9 +7851,9 @@ function parseRgbFunc(value) {
7851
7851
  if (parts.length < 3) {
7852
7852
  return null;
7853
7853
  }
7854
- const r = clampByte(parseFloat(parts[0]));
7855
- const g = clampByte(parseFloat(parts[1]));
7856
- const b = clampByte(parseFloat(parts[2]));
7854
+ const r = parseByte(parts[0]);
7855
+ const g = parseByte(parts[1]);
7856
+ const b = parseByte(parts[2]);
7857
7857
  const a = parts[3] !== undefined ? clampAlpha(parts[3]) : 1;
7858
7858
  if ([r, g, b].some(Number.isNaN)) {
7859
7859
  return null;
@@ -7902,7 +7902,12 @@ function parseViaCanvas(value) {
7902
7902
  const data = ctx.getImageData(0, 0, 1, 1).data;
7903
7903
  return { r: data[0], g: data[1], b: data[2], a: data[3] / 255 };
7904
7904
  }
7905
- function hslToRgb(h, s, l) {
7905
+ function hslToRgb(hue, sat, lum) {
7906
+ // `sectorToRgb` assumes a non-negative sector and in-range channels; an out-of-range
7907
+ // `hsl()` string would otherwise yield negative or >255 components
7908
+ const h = ((hue % 360) + 360) % 360;
7909
+ const s = clamp01(sat);
7910
+ const l = clamp01(lum);
7906
7911
  const c = (1 - Math.abs(2 * l - 1)) * s;
7907
7912
  const hh = (h / 60) % 6;
7908
7913
  const x = c * (1 - Math.abs((hh % 2) - 1));
@@ -7914,6 +7919,10 @@ function hslToRgb(h, s, l) {
7914
7919
  b: Math.round((b + m) * 255),
7915
7920
  };
7916
7921
  }
7922
+ function parseByte(value) {
7923
+ const n = parseFloat(value);
7924
+ return clampByte(value.endsWith('%') ? (n / 100) * 255 : n);
7925
+ }
7917
7926
  function clampByte(n) {
7918
7927
  return Math.max(0, Math.min(255, Math.round(n)));
7919
7928
  }
@@ -8940,6 +8949,7 @@ class DatePickerComponent {
8940
8949
  else {
8941
8950
  this.viewMonth.set(month - 1);
8942
8951
  }
8952
+ this.pullFocusIntoView();
8943
8953
  }
8944
8954
  goToNextMonth() {
8945
8955
  const month = this.viewMonth();
@@ -8950,12 +8960,28 @@ class DatePickerComponent {
8950
8960
  else {
8951
8961
  this.viewMonth.set(month + 1);
8952
8962
  }
8963
+ this.pullFocusIntoView();
8953
8964
  }
8954
8965
  goToPrevYear() {
8955
8966
  this.viewYear.update(y => y - 1);
8967
+ this.pullFocusIntoView();
8956
8968
  }
8957
8969
  goToNextYear() {
8958
8970
  this.viewYear.update(y => y + 1);
8971
+ this.pullFocusIntoView();
8972
+ }
8973
+ /**
8974
+ * Moves the roving date into the month now on screen, keeping the day where
8975
+ * the month is long enough. Without this the only tabbable day cell stays in
8976
+ * the month the user navigated away from, so inside the focus-trapped dialog
8977
+ * no day is reachable and the next arrow key snaps the view back.
8978
+ */
8979
+ pullFocusIntoView() {
8980
+ const year = this.viewYear();
8981
+ const month = this.viewMonth();
8982
+ const day = this.focusedDate()?.getDate() ?? 1;
8983
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
8984
+ this.focusedDate.set(new Date(year, month, Math.min(day, daysInMonth)));
8959
8985
  }
8960
8986
  goToToday() {
8961
8987
  const today = this.startOfDay(new Date());
@@ -9097,9 +9123,10 @@ class DatePickerComponent {
9097
9123
  return result;
9098
9124
  }
9099
9125
  addMonths(date, months) {
9100
- const result = new Date(date);
9101
- result.setMonth(date.getMonth() + months);
9102
- return result;
9126
+ // Clamping to the target month's length keeps the step at exactly one
9127
+ // month; a bare setMonth overflows short months into the one after
9128
+ const daysInTarget = new Date(date.getFullYear(), date.getMonth() + months + 1, 0).getDate();
9129
+ return new Date(date.getFullYear(), date.getMonth() + months, Math.min(date.getDate(), daysInTarget));
9103
9130
  }
9104
9131
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: DatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9105
9132
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: DatePickerComponent, isStandalone: true, selector: "ea-date-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, errorMessages: { classPropertyName: "errorMessages", publicName: "errorMessages", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, weekStartsOn: { classPropertyName: "weekStartsOn", publicName: "weekStartsOn", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, providers: [
@@ -9506,6 +9533,12 @@ class DrawerComponent {
9506
9533
  const ease = animation === 'linear' ? 'var(--ease-linear)' : 'var(--ease-out)';
9507
9534
  target.style.transition = `padding var(--duration-slower) ${ease}`;
9508
9535
  }
9536
+ // A target swap while open has to release the previous element too, or its
9537
+ // offset sticks around with nothing left to clear it
9538
+ if (this.pushedTarget && this.pushedTarget !== target) {
9539
+ this.clearPushProperties(this.pushedTarget);
9540
+ this.pushedTarget.style.removeProperty('transition');
9541
+ }
9509
9542
  // Clear every side first so a position change never stacks two offsets
9510
9543
  this.clearPushProperties(target);
9511
9544
  target.style.setProperty(PUSH_PROPERTY[position], `${size}px`);