@area8975/ui 0.2.2-dev.38 → 0.2.2-dev.40

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/CHANGELOG.md CHANGED
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. See [commit
8
8
 
9
9
  * add ui-disclosure, a trigger that shows and hides a panel, with section and whole-row triggers and a turning chevron
10
10
  * add `visibleOptions` to ui-table-filters options groups, showing the rest behind a "Show N more" toggle
11
+ * colour the sidebar with the `--sidebar-nav-foreground`, `--sidebar-nav-hover` and `--sidebar-nav-focus` tokens. Sidebar items and the collapse button follow them, and footer content can too by adding the `ui-sidebar-button` class
11
12
 
12
13
  ### Bug Fixes
13
14
 
@@ -1060,10 +1060,6 @@ var UiChartComponent = class UiChartComponent {
1060
1060
  destroyed = false;
1061
1061
  drawnNames = [];
1062
1062
  host = inject(ElementRef);
1063
- drawnSize = {
1064
- width: 0,
1065
- height: 0
1066
- };
1067
1063
  resizeObserver = null;
1068
1064
  constructor() {
1069
1065
  afterNextRender(async () => {
@@ -1071,13 +1067,11 @@ var UiChartComponent = class UiChartComponent {
1071
1067
  if (this.destroyed) return;
1072
1068
  const chart = new Apex(this.canvas().nativeElement, this.withOwnParentResizing(untracked(this.options)));
1073
1069
  chart.addEventListener("updated", () => {
1074
- this.drawnSize = this.hostSize();
1075
1070
  this.applyHidden(chart);
1076
1071
  this.applyEmphasis();
1077
1072
  });
1078
1073
  this.drawnNames = this.seriesNames();
1079
1074
  await chart.render();
1080
- this.drawnSize = this.hostSize();
1081
1075
  this.chart.set(chart);
1082
1076
  this.redrawWhenResized(chart);
1083
1077
  this.applyHidden(chart);
@@ -1120,17 +1114,14 @@ var UiChartComponent = class UiChartComponent {
1120
1114
  }
1121
1115
  redrawWhenResized(chart) {
1122
1116
  this.resizeObserver = new ResizeObserver(() => {
1123
- const size = this.hostSize();
1124
- if (size.width !== this.drawnSize.width || size.height !== this.drawnSize.height) chart.updateSeries(untracked(this.options).series ?? [], false);
1117
+ if (!this.isDrawnAtHostSize()) chart.updateSeries(untracked(this.options).series ?? [], false);
1125
1118
  });
1126
1119
  this.resizeObserver.observe(this.host.nativeElement);
1127
1120
  }
1128
- hostSize() {
1129
- const { offsetWidth, offsetHeight } = this.host.nativeElement;
1130
- return {
1131
- width: offsetWidth,
1132
- height: offsetHeight
1133
- };
1121
+ isDrawnAtHostSize() {
1122
+ const host = this.host.nativeElement;
1123
+ const drawn = this.canvas().nativeElement.querySelector(".apexcharts-canvas");
1124
+ return !!drawn && drawn.offsetWidth === host.offsetWidth && drawn.offsetHeight === host.offsetHeight;
1134
1125
  }
1135
1126
  applyHidden(chart) {
1136
1127
  const hidden = this.hiddenSeries();
@@ -11160,8 +11151,8 @@ var UiSidebarComponent = class UiSidebarComponent {
11160
11151
  })],
11161
11152
  exportAs: ["uiSidebar"],
11162
11153
  ngImport: i0,
11163
- template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
11164
- styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
11154
+ template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"ui-sidebar-button justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
11155
+ styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}::ng-deep .ui-button.ui-sidebar-button{color:var(--sidebar-nav-foreground)}::ng-deep .ui-button.ui-sidebar-button:hover{background-color:var(--sidebar-nav-hover)}::ng-deep .ui-button.ui-sidebar-button:focus-visible{background-color:var(--sidebar-nav-focus)}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
11165
11156
  dependencies: [{
11166
11157
  kind: "component",
11167
11158
  type: UiButtonComponent,
@@ -11209,8 +11200,8 @@ i0.ɵɵngDeclareClassMetadata({
11209
11200
  heroChevronDoubleLeft,
11210
11201
  heroBars3
11211
11202
  })],
11212
- template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
11213
- styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
11203
+ template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"ui-sidebar-button justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
11204
+ styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}::ng-deep .ui-button.ui-sidebar-button{color:var(--sidebar-nav-foreground)}::ng-deep .ui-button.ui-sidebar-button:hover{background-color:var(--sidebar-nav-hover)}::ng-deep .ui-button.ui-sidebar-button:focus-visible{background-color:var(--sidebar-nav-focus)}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
11214
11205
  }]
11215
11206
  }],
11216
11207
  propDecorators: { isOpen: [{
@@ -11315,7 +11306,7 @@ var UiSidebarItemComponent = class UiSidebarItemComponent {
11315
11306
  }
11316
11307
  },
11317
11308
  ngImport: i0,
11318
- template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
11309
+ template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-button ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-button ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
11319
11310
  styles: [":host{display:block}::ng-deep .ui-sidebar-item{height:calc(var(--spacing, .25rem) * 10);width:100%;padding-inline:calc(var(--spacing, .25rem) * 2.5)!important;padding-block:0px!important;white-space:nowrap}::ng-deep .ui-sidebar-item--collapsed{justify-content:center}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
11320
11311
  dependencies: [{
11321
11312
  kind: "component",
@@ -11355,7 +11346,7 @@ i0.ɵɵngDeclareClassMetadata({
11355
11346
  args: [{
11356
11347
  selector: "ui-sidebar-item",
11357
11348
  imports: [UiButtonComponent, NgIcon],
11358
- template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
11349
+ template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-button ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-button ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
11359
11350
  styles: [":host{display:block}::ng-deep .ui-sidebar-item{height:calc(var(--spacing, .25rem) * 10);width:100%;padding-inline:calc(var(--spacing, .25rem) * 2.5)!important;padding-block:0px!important;white-space:nowrap}::ng-deep .ui-sidebar-item--collapsed{justify-content:center}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
11360
11351
  }]
11361
11352
  }],
@@ -13962,9 +13953,10 @@ var UiTableFiltersComponent = class UiTableFiltersComponent {
13962
13953
  value = model({}, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
13963
13954
  collapseBelow = input("lg", ...ngDevMode ? [{ debugName: "collapseBelow" }] : /* istanbul ignore next */ []);
13964
13955
  idPrefix = `ui-table-filters-${nextId++}`;
13965
- anyDate = "any";
13966
- customDate = "custom";
13967
- customDates = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "customDates" }] : /* istanbul ignore next */ []);
13956
+ anyRange = "any";
13957
+ customRange = "custom";
13958
+ customRanges = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "customRanges" }] : /* istanbul ignore next */ []);
13959
+ amountDrafts = signal({}, ...ngDevMode ? [{ debugName: "amountDrafts" }] : /* istanbul ignore next */ []);
13968
13960
  expanded = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []);
13969
13961
  linked = computed(() => {
13970
13962
  const id = this.table();
@@ -14047,7 +14039,7 @@ var UiTableFiltersComponent = class UiTableFiltersComponent {
14047
14039
  };
14048
14040
  }
14049
14041
  dateMode(facet) {
14050
- if (this.customDates().has(facet.id)) return "custom";
14042
+ if (this.customRanges().has(facet.id)) return "custom";
14051
14043
  const applied = this.range(facet);
14052
14044
  if (!applied.start) return "any";
14053
14045
  const index = (facet.presets ?? []).findIndex((preset) => {
@@ -14064,18 +14056,61 @@ var UiTableFiltersComponent = class UiTableFiltersComponent {
14064
14056
  setRange(facet, range) {
14065
14057
  this.apply(facet.id, range.start ? range : void 0);
14066
14058
  }
14059
+ amountRange(facet) {
14060
+ return this.value()[facet.id];
14061
+ }
14062
+ amountMode(facet) {
14063
+ if (this.customRanges().has(facet.id)) return "custom";
14064
+ const applied = this.amountRange(facet);
14065
+ if (!applied) return "any";
14066
+ const index = (facet.presets ?? []).findIndex((preset) => isSameAmountRange(preset.range, applied));
14067
+ return index === -1 ? "custom" : index;
14068
+ }
14069
+ pickAmount(facet, mode) {
14070
+ this.setCustom(facet.id, mode === "custom");
14071
+ this.forgetAmountDraft(facet.id);
14072
+ if (mode === "any") this.apply(facet.id, void 0);
14073
+ else if (mode !== "custom") this.apply(facet.id, facet.presets?.[mode]?.range);
14074
+ }
14075
+ amountText(facet, end) {
14076
+ const draft = this.amountDrafts()[facet.id];
14077
+ const applied = this.amountRange(facet);
14078
+ if (draft && isSameAmountRange(amountRangeFrom(draft), applied)) return draft[end];
14079
+ return applied?.[end]?.toString() ?? "";
14080
+ }
14081
+ typeAmount(facet, end, text) {
14082
+ const draft = {
14083
+ min: this.amountText(facet, "min"),
14084
+ max: this.amountText(facet, "max"),
14085
+ [end]: text
14086
+ };
14087
+ this.amountDrafts.update((drafts) => ({
14088
+ ...drafts,
14089
+ [facet.id]: draft
14090
+ }));
14091
+ this.apply(facet.id, amountRangeFrom(draft));
14092
+ }
14093
+ isAmountValid(facet, end) {
14094
+ const draft = this.amountDrafts()[facet.id];
14095
+ if (!draft) return true;
14096
+ return isReadableAmount(draft[end]) && !isBackwards(draft);
14097
+ }
14067
14098
  clearAll() {
14068
- this.customDates.set(/* @__PURE__ */ new Set());
14099
+ this.customRanges.set(/* @__PURE__ */ new Set());
14100
+ this.amountDrafts.set({});
14069
14101
  this.write(this.withoutOwn(this.currentFilters()));
14070
14102
  }
14071
14103
  setCustom(id, custom) {
14072
- this.customDates.update((ids) => {
14104
+ this.customRanges.update((ids) => {
14073
14105
  const next = new Set(ids);
14074
14106
  if (custom) next.add(id);
14075
14107
  else next.delete(id);
14076
14108
  return next;
14077
14109
  });
14078
14110
  }
14111
+ forgetAmountDraft(id) {
14112
+ this.amountDrafts.update((drafts) => Object.fromEntries(Object.entries(drafts).filter(([draftId]) => draftId !== id)));
14113
+ }
14079
14114
  isPastCutoff(facet, index) {
14080
14115
  return facet.visibleOptions !== void 0 && index >= facet.visibleOptions;
14081
14116
  }
@@ -14153,8 +14188,8 @@ var UiTableFiltersComponent = class UiTableFiltersComponent {
14153
14188
  outputs: { value: "valueChange" },
14154
14189
  host: { classAttribute: "block" },
14155
14190
  ngImport: i0,
14156
- template: "@if (wide()) {\n <div class=\"ui-table-filters-panel ui-table-filters-panel--card\">\n <ng-container *ngTemplateOutlet=\"body; context: { $implicit: true }\" />\n </div>\n} @else {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"gap-x-2 h-9.5 py-0!\"\n (click)=\"drawer.isOpen.set(true)\"\n >\n Filters\n @if (appliedCount()) {\n <ui-badge appearance=\"soft\" size=\"xs\" class=\"ui-text-caption\">{{\n appliedCount()\n }}</ui-badge>\n }\n </ui-button>\n\n <ui-drawer #drawer label=\"Filters\">\n <button\n drawer-actions\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n\n <div class=\"ui-table-filters-panel\">\n <ng-container\n *ngTemplateOutlet=\"body; context: { $implicit: false }\"\n />\n </div>\n </ui-drawer>\n}\n\n<ng-template #body let-showHeader>\n @if (showHeader) {\n <div class=\"ui-table-filters-header\">\n <span class=\"ui-table-filters-title ui-text-body\">\n Filters\n </span>\n\n <button\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n </div>\n }\n\n @for (facet of facets(); track facet.id) {\n <fieldset class=\"ui-table-filters-facet\">\n <legend class=\"ui-table-filters-legend ui-text-body-alt\">\n {{ facet.label }}\n </legend>\n\n <div\n class=\"ui-table-filters-choices\"\n [id]=\"groupName(facet) + '-options'\"\n >\n @switch (facet.kind) {\n @case ('options') {\n @if (facet.multiple) {\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-checkbox\n [id]=\"choiceId(facet, index)\"\n [value]=\"isChecked(facet, option)\"\n (valueChange)=\"check(facet, option, $event)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n } @else {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"null\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any</span>\n </label>\n\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"option.value\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n }\n }\n @case ('dateRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"anyDate\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any time</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"customDate\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (dateMode(facet) === 'custom') {\n <label\n class=\"sr-only\"\n [for]=\"groupName(facet) + '-range'\"\n >{{ facet.label }} range</label>\n <ui-date-range-picker\n class=\"ui-table-filters-range\"\n [id]=\"groupName(facet) + '-range'\"\n [value]=\"range(facet)\"\n (valueChange)=\"setRange(facet, $event)\"\n [placeholder]=\"facet.placeholder ?? 'Select dates'\"\n [min]=\"facet.min ?? null\"\n [max]=\"facet.max ?? null\"\n />\n }\n }\n }\n </div>\n\n @if (facet.kind === 'options' && hiddenCount(facet)) {\n <button\n type=\"button\"\n class=\"ui-table-filters-more ui-text-body-alt\"\n [attr.aria-expanded]=\"isExpanded(facet)\"\n [attr.aria-controls]=\"groupName(facet) + '-options'\"\n (click)=\"toggleExpanded(facet)\"\n >\n @if (isExpanded(facet)) {\n Show fewer\n } @else {\n Show {{ hiddenCount(facet) }} more\n }\n </button>\n }\n </fieldset>\n }\n</ng-template>\n",
14157
- styles: ["@layer properties;.ui-table-filters-panel{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 6)}.ui-table-filters-panel--card{border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--card-line);background-color:var(--card);padding:calc(var(--spacing, .25rem) * 5)}.ui-table-filters-header{display:flex;align-items:center;justify-content:space-between;column-gap:calc(var(--spacing, .25rem) * 3)}.ui-table-filters-title{display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-clear{cursor:pointer;color:var(--muted-foreground-1)}.ui-table-filters-clear:hover{color:var(--foreground)}.ui-table-filters-clear:focus-visible{text-decoration-line:underline}.ui-table-filters-clear:focus-visible{--tw-outline-style: none;outline-style:none}.ui-table-filters-facet{margin:0;min-width:0px;border-style:var(--tw-border-style);border-width:0px;padding:0}.ui-table-filters-legend{margin-bottom:calc(var(--spacing, .25rem) * 3);padding:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-choices{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 2.5)}.ui-table-filters-choice{display:flex;min-width:0px;cursor:pointer;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2.5);color:var(--muted-foreground-2)}.ui-table-filters-choice:hover{color:var(--foreground)}.ui-table-filters-range{margin-top:calc(var(--spacing, .25rem) * .5)}.ui-table-filters-more{margin-top:calc(var(--spacing, .25rem) * 2.5);cursor:pointer;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-filters-more:hover{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:hover{text-decoration-line:underline}.ui-table-filters-more:focus-visible{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:focus-visible{text-decoration-line:underline}.ui-table-filters-more:focus-visible{--tw-outline-style: none;outline-style:none}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
14191
+ template: "@if (wide()) {\n <div class=\"ui-table-filters-panel ui-table-filters-panel--card\">\n <ng-container *ngTemplateOutlet=\"body; context: { $implicit: true }\" />\n </div>\n} @else {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"gap-x-2 h-9.5 py-0!\"\n (click)=\"drawer.isOpen.set(true)\"\n >\n Filters\n @if (appliedCount()) {\n <ui-badge appearance=\"soft\" size=\"xs\" class=\"ui-text-caption\">{{\n appliedCount()\n }}</ui-badge>\n }\n </ui-button>\n\n <ui-drawer #drawer label=\"Filters\">\n <button\n drawer-actions\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n\n <div class=\"ui-table-filters-panel\">\n <ng-container\n *ngTemplateOutlet=\"body; context: { $implicit: false }\"\n />\n </div>\n </ui-drawer>\n}\n\n<ng-template #body let-showHeader>\n @if (showHeader) {\n <div class=\"ui-table-filters-header\">\n <span class=\"ui-table-filters-title ui-text-body\">\n Filters\n </span>\n\n <button\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n </div>\n }\n\n @for (facet of facets(); track facet.id) {\n <fieldset class=\"ui-table-filters-facet\">\n <legend class=\"ui-table-filters-legend ui-text-body-alt\">\n {{ facet.label }}\n </legend>\n\n <div\n class=\"ui-table-filters-choices\"\n [id]=\"groupName(facet) + '-options'\"\n >\n @switch (facet.kind) {\n @case ('options') {\n @if (facet.multiple) {\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-checkbox\n [id]=\"choiceId(facet, index)\"\n [value]=\"isChecked(facet, option)\"\n (valueChange)=\"check(facet, option, $event)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n } @else {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"null\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any</span>\n </label>\n\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"option.value\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n }\n }\n @case ('dateRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"anyRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any time</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"customRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (dateMode(facet) === 'custom') {\n <label\n class=\"sr-only\"\n [for]=\"groupName(facet) + '-range'\"\n >{{ facet.label }} range</label>\n <ui-date-range-picker\n class=\"ui-table-filters-range\"\n [id]=\"groupName(facet) + '-range'\"\n [value]=\"range(facet)\"\n (valueChange)=\"setRange(facet, $event)\"\n [placeholder]=\"facet.placeholder ?? 'Select dates'\"\n [min]=\"facet.min ?? null\"\n [max]=\"facet.max ?? null\"\n />\n }\n }\n @case ('amountRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"anyRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any amount</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"customRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (amountMode(facet) === 'custom') {\n <div class=\"ui-table-filters-amounts\">\n <ui-input\n class=\"ui-table-filters-amount ui-text-body-alt\"\n [id]=\"groupName(facet) + '-min'\"\n inputmode=\"decimal\"\n placeholder=\"Min\"\n [ariaLabel]=\"facet.label + ' from'\"\n [value]=\"amountText(facet, 'min')\"\n (valueChange)=\"typeAmount(facet, 'min', $event)\"\n [validationState]=\"isAmountValid(facet, 'min') ? null : false\"\n >\n @if (facet.prefix) {\n <ng-template #leading>\n <span class=\"ui-table-filters-prefix\">{{\n facet.prefix\n }}</span>\n </ng-template>\n }\n </ui-input>\n\n <span class=\"ui-table-filters-to ui-text-body-alt\">to</span>\n\n <ui-input\n class=\"ui-table-filters-amount ui-text-body-alt\"\n [id]=\"groupName(facet) + '-max'\"\n inputmode=\"decimal\"\n placeholder=\"Max\"\n [ariaLabel]=\"facet.label + ' up to'\"\n [value]=\"amountText(facet, 'max')\"\n (valueChange)=\"typeAmount(facet, 'max', $event)\"\n [validationState]=\"isAmountValid(facet, 'max') ? null : false\"\n >\n @if (facet.prefix) {\n <ng-template #leading>\n <span class=\"ui-table-filters-prefix\">{{\n facet.prefix\n }}</span>\n </ng-template>\n }\n </ui-input>\n </div>\n }\n }\n }\n </div>\n\n @if (facet.kind === 'options' && hiddenCount(facet)) {\n <button\n type=\"button\"\n class=\"ui-table-filters-more ui-text-body-alt\"\n [attr.aria-expanded]=\"isExpanded(facet)\"\n [attr.aria-controls]=\"groupName(facet) + '-options'\"\n (click)=\"toggleExpanded(facet)\"\n >\n @if (isExpanded(facet)) {\n Show fewer\n } @else {\n Show {{ hiddenCount(facet) }} more\n }\n </button>\n }\n </fieldset>\n }\n</ng-template>\n",
14192
+ styles: ["@layer properties;.ui-table-filters-panel{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 6)}.ui-table-filters-panel--card{border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--card-line);background-color:var(--card);padding:calc(var(--spacing, .25rem) * 5)}.ui-table-filters-header{display:flex;align-items:center;justify-content:space-between;column-gap:calc(var(--spacing, .25rem) * 3)}.ui-table-filters-title{display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-clear{cursor:pointer;color:var(--muted-foreground-1)}.ui-table-filters-clear:hover{color:var(--foreground)}.ui-table-filters-clear:focus-visible{text-decoration-line:underline}.ui-table-filters-clear:focus-visible{--tw-outline-style: none;outline-style:none}.ui-table-filters-facet{margin:0;min-width:0px;border-style:var(--tw-border-style);border-width:0px;padding:0}.ui-table-filters-legend{margin-bottom:calc(var(--spacing, .25rem) * 3);padding:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-choices{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 2.5)}.ui-table-filters-choice{display:flex;min-width:0px;cursor:pointer;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2.5);color:var(--muted-foreground-2)}.ui-table-filters-choice:hover{color:var(--foreground)}.ui-table-filters-range{margin-top:calc(var(--spacing, .25rem) * .5)}.ui-table-filters-amounts{margin-top:calc(var(--spacing, .25rem) * .5);display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2)}.ui-table-filters-amount{min-width:0px;flex:1}.ui-table-filters-prefix{padding-inline-start:calc(var(--spacing, .25rem) * 3);color:var(--muted-foreground-1)}.ui-table-filters-to{flex-shrink:0;color:var(--muted-foreground-1)}.ui-table-filters-more{margin-top:calc(var(--spacing, .25rem) * 2.5);cursor:pointer;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-filters-more:hover{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:hover{text-decoration-line:underline}.ui-table-filters-more:focus-visible{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:focus-visible{text-decoration-line:underline}.ui-table-filters-more:focus-visible{--tw-outline-style: none;outline-style:none}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
14158
14193
  dependencies: [
14159
14194
  {
14160
14195
  kind: "directive",
@@ -14233,6 +14268,49 @@ var UiTableFiltersComponent = class UiTableFiltersComponent {
14233
14268
  ],
14234
14269
  outputs: ["valueChange", "validationStateChange"]
14235
14270
  },
14271
+ {
14272
+ kind: "component",
14273
+ type: UiInputComponent,
14274
+ selector: "ui-input",
14275
+ inputs: [
14276
+ "value",
14277
+ "classes",
14278
+ "type",
14279
+ "id",
14280
+ "name",
14281
+ "placeholder",
14282
+ "autocomplete",
14283
+ "inputmode",
14284
+ "required",
14285
+ "disabled",
14286
+ "readonly",
14287
+ "validationState",
14288
+ "min",
14289
+ "max",
14290
+ "step",
14291
+ "pattern",
14292
+ "minlength",
14293
+ "maxlength",
14294
+ "autofocus",
14295
+ "spellcheck",
14296
+ "revealable",
14297
+ "list",
14298
+ "ariaLabel",
14299
+ "describedBy",
14300
+ "inputRole",
14301
+ "ariaExpanded",
14302
+ "ariaControls",
14303
+ "ariaActiveDescendant",
14304
+ "ariaAutocomplete",
14305
+ "ariaHasPopup"
14306
+ ],
14307
+ outputs: [
14308
+ "valueChange",
14309
+ "validationStateChange",
14310
+ "focused",
14311
+ "blurred"
14312
+ ]
14313
+ },
14236
14314
  {
14237
14315
  kind: "component",
14238
14316
  type: UiDateRangePickerComponent,
@@ -14274,11 +14352,12 @@ i0.ɵɵngDeclareClassMetadata({
14274
14352
  UiDrawerComponent,
14275
14353
  UiCheckboxComponent,
14276
14354
  UiRadioComponent,
14355
+ UiInputComponent,
14277
14356
  UiDateRangePickerComponent
14278
14357
  ],
14279
14358
  host: { class: "block" },
14280
- template: "@if (wide()) {\n <div class=\"ui-table-filters-panel ui-table-filters-panel--card\">\n <ng-container *ngTemplateOutlet=\"body; context: { $implicit: true }\" />\n </div>\n} @else {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"gap-x-2 h-9.5 py-0!\"\n (click)=\"drawer.isOpen.set(true)\"\n >\n Filters\n @if (appliedCount()) {\n <ui-badge appearance=\"soft\" size=\"xs\" class=\"ui-text-caption\">{{\n appliedCount()\n }}</ui-badge>\n }\n </ui-button>\n\n <ui-drawer #drawer label=\"Filters\">\n <button\n drawer-actions\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n\n <div class=\"ui-table-filters-panel\">\n <ng-container\n *ngTemplateOutlet=\"body; context: { $implicit: false }\"\n />\n </div>\n </ui-drawer>\n}\n\n<ng-template #body let-showHeader>\n @if (showHeader) {\n <div class=\"ui-table-filters-header\">\n <span class=\"ui-table-filters-title ui-text-body\">\n Filters\n </span>\n\n <button\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n </div>\n }\n\n @for (facet of facets(); track facet.id) {\n <fieldset class=\"ui-table-filters-facet\">\n <legend class=\"ui-table-filters-legend ui-text-body-alt\">\n {{ facet.label }}\n </legend>\n\n <div\n class=\"ui-table-filters-choices\"\n [id]=\"groupName(facet) + '-options'\"\n >\n @switch (facet.kind) {\n @case ('options') {\n @if (facet.multiple) {\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-checkbox\n [id]=\"choiceId(facet, index)\"\n [value]=\"isChecked(facet, option)\"\n (valueChange)=\"check(facet, option, $event)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n } @else {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"null\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any</span>\n </label>\n\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"option.value\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n }\n }\n @case ('dateRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"anyDate\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any time</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"customDate\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (dateMode(facet) === 'custom') {\n <label\n class=\"sr-only\"\n [for]=\"groupName(facet) + '-range'\"\n >{{ facet.label }} range</label>\n <ui-date-range-picker\n class=\"ui-table-filters-range\"\n [id]=\"groupName(facet) + '-range'\"\n [value]=\"range(facet)\"\n (valueChange)=\"setRange(facet, $event)\"\n [placeholder]=\"facet.placeholder ?? 'Select dates'\"\n [min]=\"facet.min ?? null\"\n [max]=\"facet.max ?? null\"\n />\n }\n }\n }\n </div>\n\n @if (facet.kind === 'options' && hiddenCount(facet)) {\n <button\n type=\"button\"\n class=\"ui-table-filters-more ui-text-body-alt\"\n [attr.aria-expanded]=\"isExpanded(facet)\"\n [attr.aria-controls]=\"groupName(facet) + '-options'\"\n (click)=\"toggleExpanded(facet)\"\n >\n @if (isExpanded(facet)) {\n Show fewer\n } @else {\n Show {{ hiddenCount(facet) }} more\n }\n </button>\n }\n </fieldset>\n }\n</ng-template>\n",
14281
- styles: ["@layer properties;.ui-table-filters-panel{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 6)}.ui-table-filters-panel--card{border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--card-line);background-color:var(--card);padding:calc(var(--spacing, .25rem) * 5)}.ui-table-filters-header{display:flex;align-items:center;justify-content:space-between;column-gap:calc(var(--spacing, .25rem) * 3)}.ui-table-filters-title{display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-clear{cursor:pointer;color:var(--muted-foreground-1)}.ui-table-filters-clear:hover{color:var(--foreground)}.ui-table-filters-clear:focus-visible{text-decoration-line:underline}.ui-table-filters-clear:focus-visible{--tw-outline-style: none;outline-style:none}.ui-table-filters-facet{margin:0;min-width:0px;border-style:var(--tw-border-style);border-width:0px;padding:0}.ui-table-filters-legend{margin-bottom:calc(var(--spacing, .25rem) * 3);padding:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-choices{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 2.5)}.ui-table-filters-choice{display:flex;min-width:0px;cursor:pointer;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2.5);color:var(--muted-foreground-2)}.ui-table-filters-choice:hover{color:var(--foreground)}.ui-table-filters-range{margin-top:calc(var(--spacing, .25rem) * .5)}.ui-table-filters-more{margin-top:calc(var(--spacing, .25rem) * 2.5);cursor:pointer;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-filters-more:hover{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:hover{text-decoration-line:underline}.ui-table-filters-more:focus-visible{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:focus-visible{text-decoration-line:underline}.ui-table-filters-more:focus-visible{--tw-outline-style: none;outline-style:none}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
14359
+ template: "@if (wide()) {\n <div class=\"ui-table-filters-panel ui-table-filters-panel--card\">\n <ng-container *ngTemplateOutlet=\"body; context: { $implicit: true }\" />\n </div>\n} @else {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"gap-x-2 h-9.5 py-0!\"\n (click)=\"drawer.isOpen.set(true)\"\n >\n Filters\n @if (appliedCount()) {\n <ui-badge appearance=\"soft\" size=\"xs\" class=\"ui-text-caption\">{{\n appliedCount()\n }}</ui-badge>\n }\n </ui-button>\n\n <ui-drawer #drawer label=\"Filters\">\n <button\n drawer-actions\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n\n <div class=\"ui-table-filters-panel\">\n <ng-container\n *ngTemplateOutlet=\"body; context: { $implicit: false }\"\n />\n </div>\n </ui-drawer>\n}\n\n<ng-template #body let-showHeader>\n @if (showHeader) {\n <div class=\"ui-table-filters-header\">\n <span class=\"ui-table-filters-title ui-text-body\">\n Filters\n </span>\n\n <button\n type=\"button\"\n class=\"ui-table-filters-clear ui-text-body-alt\"\n [class.invisible]=\"!anyApplied()\"\n (click)=\"clearAll()\"\n >\n Clear all\n </button>\n </div>\n }\n\n @for (facet of facets(); track facet.id) {\n <fieldset class=\"ui-table-filters-facet\">\n <legend class=\"ui-table-filters-legend ui-text-body-alt\">\n {{ facet.label }}\n </legend>\n\n <div\n class=\"ui-table-filters-choices\"\n [id]=\"groupName(facet) + '-options'\"\n >\n @switch (facet.kind) {\n @case ('options') {\n @if (facet.multiple) {\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-checkbox\n [id]=\"choiceId(facet, index)\"\n [value]=\"isChecked(facet, option)\"\n (valueChange)=\"check(facet, option, $event)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n } @else {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"null\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any</span>\n </label>\n\n @for (option of facet.options; track option.value; let index = $index) {\n @if (isShown(facet, option, index)) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"picked(facet)\"\n (valueChange)=\"pick(facet, $event)\"\n [option]=\"option.value\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{\n option.label\n }}</span>\n </label>\n }\n }\n }\n }\n @case ('dateRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"anyRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any time</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"dateMode(facet)\"\n (valueChange)=\"pickDate(facet, $event)\"\n [option]=\"customRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (dateMode(facet) === 'custom') {\n <label\n class=\"sr-only\"\n [for]=\"groupName(facet) + '-range'\"\n >{{ facet.label }} range</label>\n <ui-date-range-picker\n class=\"ui-table-filters-range\"\n [id]=\"groupName(facet) + '-range'\"\n [value]=\"range(facet)\"\n (valueChange)=\"setRange(facet, $event)\"\n [placeholder]=\"facet.placeholder ?? 'Select dates'\"\n [min]=\"facet.min ?? null\"\n [max]=\"facet.max ?? null\"\n />\n }\n }\n @case ('amountRange') {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'any')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'any')\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"anyRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Any amount</span>\n </label>\n\n @for (preset of facet.presets ?? []; track preset.label; let index = $index) {\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, index)\"\n >\n <ui-radio\n [id]=\"choiceId(facet, index)\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"index\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">{{ preset.label }}</span>\n </label>\n }\n\n <label\n class=\"ui-table-filters-choice ui-text-body-alt\"\n [for]=\"choiceId(facet, 'custom')\"\n >\n <ui-radio\n [id]=\"choiceId(facet, 'custom')\"\n [value]=\"amountMode(facet)\"\n (valueChange)=\"pickAmount(facet, $event)\"\n [option]=\"customRange\"\n [name]=\"groupName(facet)\"\n />\n <span class=\"truncate\">Custom range</span>\n </label>\n\n @if (amountMode(facet) === 'custom') {\n <div class=\"ui-table-filters-amounts\">\n <ui-input\n class=\"ui-table-filters-amount ui-text-body-alt\"\n [id]=\"groupName(facet) + '-min'\"\n inputmode=\"decimal\"\n placeholder=\"Min\"\n [ariaLabel]=\"facet.label + ' from'\"\n [value]=\"amountText(facet, 'min')\"\n (valueChange)=\"typeAmount(facet, 'min', $event)\"\n [validationState]=\"isAmountValid(facet, 'min') ? null : false\"\n >\n @if (facet.prefix) {\n <ng-template #leading>\n <span class=\"ui-table-filters-prefix\">{{\n facet.prefix\n }}</span>\n </ng-template>\n }\n </ui-input>\n\n <span class=\"ui-table-filters-to ui-text-body-alt\">to</span>\n\n <ui-input\n class=\"ui-table-filters-amount ui-text-body-alt\"\n [id]=\"groupName(facet) + '-max'\"\n inputmode=\"decimal\"\n placeholder=\"Max\"\n [ariaLabel]=\"facet.label + ' up to'\"\n [value]=\"amountText(facet, 'max')\"\n (valueChange)=\"typeAmount(facet, 'max', $event)\"\n [validationState]=\"isAmountValid(facet, 'max') ? null : false\"\n >\n @if (facet.prefix) {\n <ng-template #leading>\n <span class=\"ui-table-filters-prefix\">{{\n facet.prefix\n }}</span>\n </ng-template>\n }\n </ui-input>\n </div>\n }\n }\n }\n </div>\n\n @if (facet.kind === 'options' && hiddenCount(facet)) {\n <button\n type=\"button\"\n class=\"ui-table-filters-more ui-text-body-alt\"\n [attr.aria-expanded]=\"isExpanded(facet)\"\n [attr.aria-controls]=\"groupName(facet) + '-options'\"\n (click)=\"toggleExpanded(facet)\"\n >\n @if (isExpanded(facet)) {\n Show fewer\n } @else {\n Show {{ hiddenCount(facet) }} more\n }\n </button>\n }\n </fieldset>\n }\n</ng-template>\n",
14360
+ styles: ["@layer properties;.ui-table-filters-panel{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 6)}.ui-table-filters-panel--card{border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--card-line);background-color:var(--card);padding:calc(var(--spacing, .25rem) * 5)}.ui-table-filters-header{display:flex;align-items:center;justify-content:space-between;column-gap:calc(var(--spacing, .25rem) * 3)}.ui-table-filters-title{display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-clear{cursor:pointer;color:var(--muted-foreground-1)}.ui-table-filters-clear:hover{color:var(--foreground)}.ui-table-filters-clear:focus-visible{text-decoration-line:underline}.ui-table-filters-clear:focus-visible{--tw-outline-style: none;outline-style:none}.ui-table-filters-facet{margin:0;min-width:0px;border-style:var(--tw-border-style);border-width:0px;padding:0}.ui-table-filters-legend{margin-bottom:calc(var(--spacing, .25rem) * 3);padding:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground)}.ui-table-filters-choices{display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 2.5)}.ui-table-filters-choice{display:flex;min-width:0px;cursor:pointer;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2.5);color:var(--muted-foreground-2)}.ui-table-filters-choice:hover{color:var(--foreground)}.ui-table-filters-range{margin-top:calc(var(--spacing, .25rem) * .5)}.ui-table-filters-amounts{margin-top:calc(var(--spacing, .25rem) * .5);display:flex;align-items:center;column-gap:calc(var(--spacing, .25rem) * 2)}.ui-table-filters-amount{min-width:0px;flex:1}.ui-table-filters-prefix{padding-inline-start:calc(var(--spacing, .25rem) * 3);color:var(--muted-foreground-1)}.ui-table-filters-to{flex-shrink:0;color:var(--muted-foreground-1)}.ui-table-filters-more{margin-top:calc(var(--spacing, .25rem) * 2.5);cursor:pointer;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-filters-more:hover{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:hover{text-decoration-line:underline}.ui-table-filters-more:focus-visible{color:var(--color-primary-600, var(--color-blue-600))}.ui-table-filters-more:focus-visible{text-decoration-line:underline}.ui-table-filters-more:focus-visible{--tw-outline-style: none;outline-style:none}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
14282
14361
  }]
14283
14362
  }],
14284
14363
  ctorParameters: () => [],
@@ -14320,6 +14399,30 @@ i0.ɵɵngDeclareClassMetadata({
14320
14399
  }]
14321
14400
  }
14322
14401
  });
14402
+ function amountFrom(text) {
14403
+ const digits = text.trim().replaceAll(",", "");
14404
+ if (!digits) return null;
14405
+ const amount = Number(digits);
14406
+ return Number.isFinite(amount) ? amount : null;
14407
+ }
14408
+ function isReadableAmount(text) {
14409
+ return !text.trim() || amountFrom(text) !== null;
14410
+ }
14411
+ function isBackwards(draft) {
14412
+ const min = amountFrom(draft.min);
14413
+ const max = amountFrom(draft.max);
14414
+ return min !== null && max !== null && min > max;
14415
+ }
14416
+ function amountRangeFrom(draft) {
14417
+ const range = {
14418
+ min: amountFrom(draft.min),
14419
+ max: amountFrom(draft.max)
14420
+ };
14421
+ return range.min === null && range.max === null || isBackwards(draft) ? void 0 : range;
14422
+ }
14423
+ function isSameAmountRange(first, second) {
14424
+ return (first?.min ?? null) === (second?.min ?? null) && (first?.max ?? null) === (second?.max ?? null);
14425
+ }
14323
14426
  var UiUserMenuComponent = class UiUserMenuComponent {
14324
14427
  dropdown = inject(UiDropdownComponent, { optional: true });
14325
14428
  name = input.required(...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);