@flywheel-io/vision 19.2.0 → 19.3.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.
@@ -6253,7 +6253,7 @@ class FwSelectMenuComponent {
6253
6253
  }
6254
6254
  }
6255
6255
  get disabledClass() {
6256
- return this.disabled;
6256
+ return this.disabled();
6257
6257
  }
6258
6258
  get value() {
6259
6259
  return this._value;
@@ -6261,36 +6261,59 @@ class FwSelectMenuComponent {
6261
6261
  set value(newValue) {
6262
6262
  this.updateValue(newValue);
6263
6263
  }
6264
- constructor(_changeDetectorRef, ngControl) {
6265
- this._changeDetectorRef = _changeDetectorRef;
6264
+ constructor(ngControl) {
6266
6265
  this.ngControl = ngControl;
6267
- // bind it for the template
6268
- this.JSON = JSON;
6269
- this.options = [];
6270
- this.valueProperty = 'value';
6271
- this.useFullOptionAsValue = false;
6272
- this.titleProperty = 'title';
6273
- this.iconProperty = 'icon';
6274
- this.descriptionProperty = 'description';
6275
- this.showFilter = false;
6276
- this.showReset = false;
6277
- this.disabled = false;
6278
- this.errored = false;
6279
- this.width = '200px';
6280
- this.size = 'medium';
6281
- this.placeholder = 'Select something...';
6266
+ this.options = input([]);
6267
+ this.valueProperty = input('value');
6268
+ this.useFullOptionAsValue = input(false);
6269
+ this.titleProperty = input('title');
6270
+ this.iconProperty = input('icon');
6271
+ this.staticIcon = input(undefined);
6272
+ this.descriptionProperty = input('description');
6273
+ this.showFilter = input(false);
6274
+ this.showReset = input(false);
6275
+ this.disabled = model(false);
6276
+ this.errored = input(false);
6277
+ this.width = input('200px');
6278
+ this.optionsWidth = input(undefined);
6279
+ this.minOptionsHeight = input(undefined);
6280
+ this.maxOptionsHeight = input(undefined);
6281
+ this.size = input('medium');
6282
+ this.placeholder = input('Select something...');
6282
6283
  // eslint-disable-next-line @angular-eslint/no-output-native
6283
6284
  this.change = new EventEmitter();
6284
6285
  this.filterChanged = new EventEmitter();
6285
6286
  this.selectValue = '';
6286
- this.selectTitle = '';
6287
+ this.selectTitle = signal('');
6287
6288
  this.selectIcon = '';
6288
- this.filterValue = '';
6289
+ this.filterValue = signal('');
6289
6290
  this.subscriptions = [];
6290
6291
  this._isOpen = false;
6291
6292
  this.focused = 0;
6292
6293
  this.inFocusOpen = false;
6294
+ this.isTyping = signal(false);
6295
+ // Computed signal for the input display value
6296
+ this.inputDisplayValue = computed(() => this.isTyping() ? this.filterValue() : this.selectTitle());
6293
6297
  this._value = '';
6298
+ this.filteredOptions = computed(() => {
6299
+ const filter = this.filterValue();
6300
+ const opts = this.options();
6301
+ const tProp = this.titleProperty();
6302
+ if (!filter || filter.trim() === '') {
6303
+ return opts;
6304
+ }
6305
+ return opts.filter(opt => opt[tProp]?.toString().toLowerCase()
6306
+ .includes(filter.toLowerCase()));
6307
+ });
6308
+ this.optionsWithValues = computed(() => {
6309
+ const useFull = this.useFullOptionAsValue();
6310
+ const valProp = this.valueProperty();
6311
+ return this.filteredOptions().map(item => ({
6312
+ raw: item,
6313
+ trackingId: useFull ? JSON.stringify(item) : item?.[valProp]?.toString(),
6314
+ value: useFull ? JSON.stringify(item) : item?.[valProp]?.toString(),
6315
+ }));
6316
+ });
6294
6317
  this.onTouched = () => {
6295
6318
  };
6296
6319
  // this is just a different way of binding the controlValueAccessor
@@ -6298,31 +6321,29 @@ class FwSelectMenuComponent {
6298
6321
  if (this.ngControl) {
6299
6322
  this.ngControl.valueAccessor = this;
6300
6323
  }
6301
- }
6302
- ngOnChanges(changes) {
6303
- const currentOptions = changes.options?.currentValue;
6304
- // if the options change check if the title we should be displaying has changed
6305
- if (currentOptions && currentOptions !== changes.options?.previousValue) {
6306
- const selectedOption = currentOptions.find(item => item[this.valueProperty]?.toString() === this.selectValue);
6324
+ // Watch for options changes to update the displayed title
6325
+ effect(() => {
6326
+ const currentOptions = this.options();
6327
+ const vProp = this.valueProperty();
6328
+ const tProp = this.titleProperty();
6329
+ if (!currentOptions || currentOptions.length === 0) {
6330
+ return;
6331
+ }
6332
+ const selectedOption = currentOptions.find(item => item[vProp]?.toString() === this.selectValue);
6307
6333
  if (selectedOption) {
6308
- this.selectTitle = selectedOption[this.titleProperty];
6334
+ this.selectTitle.set(selectedOption[tProp]);
6309
6335
  }
6310
- }
6336
+ });
6311
6337
  }
6312
6338
  ngAfterContentInit() {
6313
- if (!this.options || (this.options.length === 0 && this.menuItems && this.menuItems.length > 0)) {
6314
- this.options = [];
6339
+ // When using content projection with <fw-menu-item> components,
6340
+ // subscribe to their click events and set initial selected state
6341
+ if (this.menuItems && this.menuItems.length > 0) {
6315
6342
  this.menuItems.forEach(item => {
6316
- this.options.push({
6317
- value: item.value.toString(),
6318
- title: item.title.toString(),
6319
- icon: item.icon,
6320
- description: item.description,
6321
- });
6322
6343
  const sub = item.click.subscribe(value => this.menu.writeValue(value));
6323
6344
  this.subscriptions.push(sub);
6324
6345
  if (item.value.toString() === this.selectValue) {
6325
- this.selectTitle = item.title.toString();
6346
+ this.selectTitle.set(item.title.toString());
6326
6347
  this.selectIcon = item.icon;
6327
6348
  }
6328
6349
  });
@@ -6352,9 +6373,7 @@ class FwSelectMenuComponent {
6352
6373
  this.onTouched = fn;
6353
6374
  }
6354
6375
  setDisabledState(isDisabled) {
6355
- this.disabled = isDisabled;
6356
- // eslint-disable-next-line @rx-angular/no-explicit-change-detection-apis
6357
- this._changeDetectorRef.markForCheck();
6376
+ this.disabled.set(isDisabled);
6358
6377
  }
6359
6378
  writeValue(value) {
6360
6379
  value = value ?? '';
@@ -6369,20 +6388,80 @@ class FwSelectMenuComponent {
6369
6388
  this.close();
6370
6389
  return;
6371
6390
  }
6372
- if (this.useFullOptionAsValue) {
6391
+ if (this.useFullOptionAsValue()) {
6373
6392
  const parsedValue = JSON.parse(e);
6374
6393
  this.updateValue(parsedValue);
6375
6394
  }
6376
6395
  else {
6377
6396
  this.updateValue(e);
6378
6397
  }
6398
+ this.isTyping.set(false);
6379
6399
  this.close();
6400
+ this.inFocusOpen = false;
6401
+ }
6402
+ /**
6403
+ * Get all available items for navigation, either from options or menuItems
6404
+ */
6405
+ getAvailableItems() {
6406
+ // If using options input, return filtered options
6407
+ if (this.options().length > 0) {
6408
+ return this.filteredOptions();
6409
+ }
6410
+ // If using content projection, return non-disabled menu items
6411
+ if (this.menuItems && this.menuItems.length > 0) {
6412
+ return this.menuItems.filter(item => !item.disabled);
6413
+ }
6414
+ return [];
6415
+ }
6416
+ /**
6417
+ * Update highlighting for the currently selected item
6418
+ */
6419
+ updateHighlighting() {
6420
+ const currentValue = this.selectValue;
6421
+ // Update highlighting for content-projected menu items
6422
+ if (this.menuItems && this.menuItems.length > 0) {
6423
+ this.menuItems.forEach(item => {
6424
+ item.selected = item.value === currentValue;
6425
+ });
6426
+ }
6427
+ // Update highlighting for options-based menu items via menu component
6428
+ if (this.menu && this.options().length > 0) {
6429
+ this.menu.value = currentValue;
6430
+ this.menu.updateLayout();
6431
+ }
6432
+ }
6433
+ /**
6434
+ * Initialize focused index to the currently selected item
6435
+ */
6436
+ initializeFocusedIndex() {
6437
+ const availableItems = this.getAvailableItems();
6438
+ const currentValue = this.selectValue;
6439
+ // Find the index of the currently selected item
6440
+ const selectedIndex = availableItems.findIndex(item => {
6441
+ if (item instanceof FwMenuItemComponent) {
6442
+ return item.value === currentValue;
6443
+ }
6444
+ else {
6445
+ // For options array items
6446
+ const vProp = this.valueProperty();
6447
+ const itemValue = this.useFullOptionAsValue()
6448
+ ? JSON.stringify(item)
6449
+ : item?.[vProp]?.toString();
6450
+ return itemValue === currentValue;
6451
+ }
6452
+ });
6453
+ // Set focused to the selected index
6454
+ // If no item is selected (selectedIndex is -1), keep it at -1 so first arrow down goes to index 0
6455
+ this.focused = selectedIndex;
6456
+ // Also update the highlighting to show the current selection (if any)
6457
+ this.updateHighlighting();
6380
6458
  }
6381
6459
  moveFocused(direction) {
6460
+ const availableItems = this.getAvailableItems();
6382
6461
  switch (direction) {
6383
6462
  case 'down': {
6384
6463
  this.focused++;
6385
- if (this.focused >= this.options.length) {
6464
+ if (this.focused >= availableItems.length) {
6386
6465
  this.focused = 0;
6387
6466
  }
6388
6467
  break;
@@ -6390,7 +6469,7 @@ class FwSelectMenuComponent {
6390
6469
  case 'up': {
6391
6470
  this.focused--;
6392
6471
  if (this.focused < 0) {
6393
- this.focused = this.options.length - 1;
6472
+ this.focused = availableItems.length - 1;
6394
6473
  }
6395
6474
  break;
6396
6475
  }
@@ -6400,32 +6479,205 @@ class FwSelectMenuComponent {
6400
6479
  }
6401
6480
  }
6402
6481
  }
6482
+ handleFocus() {
6483
+ // Select all text when focusing the input
6484
+ if (this.textInput?.inputRef?.nativeElement && !this.isTyping()) {
6485
+ const input = this.textInput.inputRef.nativeElement;
6486
+ // Select all text immediately - this will select the current value
6487
+ input.select();
6488
+ }
6489
+ }
6490
+ handleInputClick() {
6491
+ // When clicking into the input, select all text if not already typing
6492
+ if (this.textInput?.inputRef?.nativeElement && !this.isTyping()) {
6493
+ const input = this.textInput.inputRef.nativeElement;
6494
+ // Use setTimeout to override the click's cursor positioning
6495
+ setTimeout(() => {
6496
+ input.select();
6497
+ }, 0);
6498
+ }
6499
+ // Initialize highlighting when dropdown opens via click
6500
+ // Use setTimeout to ensure menu is rendered before we try to update it
6501
+ setTimeout(() => {
6502
+ if (this.trigger?.isOpen()) {
6503
+ this.inFocusOpen = true;
6504
+ this.preFocusValue = this.value;
6505
+ this.initializeFocusedIndex();
6506
+ }
6507
+ }, 0);
6508
+ }
6403
6509
  handleKeyDown(event) {
6510
+ // Handle Enter key when typing
6511
+ if (event.key === 'Enter' && this.isTyping()) {
6512
+ event.preventDefault();
6513
+ this.inFocusOpen = false;
6514
+ // Select the currently focused option (respects arrow key navigation)
6515
+ const availableItems = this.getAvailableItems();
6516
+ let newValue;
6517
+ if (availableItems.length > 0) {
6518
+ // Select the item at the focused index (which may have been changed by arrow keys)
6519
+ const selectedItem = availableItems[this.focused];
6520
+ // Handle both options (objects) and menuItems (FwMenuItemComponent)
6521
+ if (selectedItem instanceof FwMenuItemComponent) {
6522
+ newValue = selectedItem.value;
6523
+ }
6524
+ else {
6525
+ newValue = selectedItem;
6526
+ }
6527
+ }
6528
+ else {
6529
+ // No available items, keep current value
6530
+ if (this.useFullOptionAsValue()) {
6531
+ try {
6532
+ newValue = JSON.parse(this.value);
6533
+ }
6534
+ catch {
6535
+ // If parse fails, keep the raw value
6536
+ newValue = this.value;
6537
+ }
6538
+ }
6539
+ else {
6540
+ newValue = this.value;
6541
+ }
6542
+ }
6543
+ // Clear filter and exit typing mode FIRST
6544
+ // This prevents onInputChange from interfering
6545
+ this.filterValue.set('');
6546
+ this.isTyping.set(false);
6547
+ // Update the value (this will set selectTitle signal)
6548
+ this.updateValue(newValue);
6549
+ this.close();
6550
+ return;
6551
+ }
6552
+ // Handle backspace to enter typing mode - only if text is selected or at the beginning
6553
+ if (event.key === 'Backspace' && !this.isTyping() && this.selectTitle()) {
6554
+ // Check if there's a text selection
6555
+ let hasSelection = false;
6556
+ if (this.textInput?.inputRef?.nativeElement) {
6557
+ const input = this.textInput.inputRef.nativeElement;
6558
+ const selectionStart = input.selectionStart ?? 0;
6559
+ const selectionEnd = input.selectionEnd ?? 0;
6560
+ hasSelection = selectionStart !== selectionEnd;
6561
+ }
6562
+ // Only enter typing mode if there's a selection (e.g., from clicking/tabbing in)
6563
+ // Otherwise, let the browser handle backspace naturally without entering typing mode
6564
+ if (hasSelection) {
6565
+ this.isTyping.set(true);
6566
+ this.trigger.open();
6567
+ this._isOpen = true;
6568
+ this.inFocusOpen = true;
6569
+ this.preFocusValue = this.value;
6570
+ this.initializeFocusedIndex();
6571
+ }
6572
+ // Let the default backspace behavior happen regardless
6573
+ return;
6574
+ }
6575
+ // Handle backspace while already typing
6576
+ if (event.key === 'Backspace' && this.isTyping()) {
6577
+ // Let default behavior happen, onInputChange will handle it
6578
+ return;
6579
+ }
6580
+ // Handle regular characters when entering typing mode (not already typing)
6581
+ // Exclude navigation keys like Arrow keys, Home, End, etc.
6582
+ const isNavigationKey = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown', 'Delete'].includes(event.key);
6583
+ if (!this.trigger.isOpen() && !this.isTyping() && this.selectTitle() && event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey && !isNavigationKey) {
6584
+ // Don't prevent default - let the browser handle the character insertion naturally
6585
+ // Just switch to typing mode and the input event will update filterValue
6586
+ this.isTyping.set(true);
6587
+ this.trigger.open();
6588
+ this._isOpen = true;
6589
+ this.inFocusOpen = true;
6590
+ this.preFocusValue = this.value;
6591
+ this.initializeFocusedIndex();
6592
+ // The input event will fire after this keydown, which will update filterValue
6593
+ // and trigger the dropdown to show filtered options
6594
+ return;
6595
+ }
6596
+ // Handle regular characters while already typing (including space)
6597
+ if (this.isTyping() && event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
6598
+ // Let default behavior happen, onInputChange will handle it
6599
+ return;
6600
+ }
6404
6601
  if (this.trigger.isOpen()) {
6405
6602
  if (this.inFocusOpen) {
6406
6603
  if (event.key === 'ArrowDown') {
6604
+ event.preventDefault();
6407
6605
  this.moveFocused('down');
6408
- this.updateValue(this.options[this.focused]);
6606
+ // Defer updateValue to avoid change detection errors
6607
+ setTimeout(() => {
6608
+ const availableItems = this.getAvailableItems();
6609
+ if (availableItems.length > 0) {
6610
+ const selectedItem = availableItems[this.focused];
6611
+ // Handle both options (objects) and menuItems (FwMenuItemComponent)
6612
+ if (selectedItem instanceof FwMenuItemComponent) {
6613
+ this.selectValue = selectedItem.value;
6614
+ // Manually update selected state for all menu items
6615
+ this.menuItems?.forEach(item => {
6616
+ item.selected = item.value === this.selectValue;
6617
+ });
6618
+ this.updateValue(selectedItem.value);
6619
+ }
6620
+ else {
6621
+ // For options array items, set selectValue first for immediate highlighting
6622
+ const vProp = this.valueProperty();
6623
+ this.selectValue = this.useFullOptionAsValue()
6624
+ ? JSON.stringify(selectedItem)
6625
+ : selectedItem?.[vProp]?.toString();
6626
+ if (this.menu) {
6627
+ this.menu.value = this.selectValue;
6628
+ this.menu.updateLayout();
6629
+ }
6630
+ this.updateValue(selectedItem);
6631
+ }
6632
+ }
6633
+ }, 0);
6409
6634
  }
6410
- if (event.key === 'ArrowUp') {
6635
+ else if (event.key === 'ArrowUp') {
6636
+ event.preventDefault();
6411
6637
  this.moveFocused('up');
6412
- this.updateValue(this.options[this.focused]);
6413
- }
6414
- if (event.key === 'Tab') {
6415
- this.close();
6416
- this.inFocusOpen = false;
6417
- this.updateValue(this.preFocusValue);
6638
+ // Defer updateValue to avoid change detection errors
6639
+ setTimeout(() => {
6640
+ const availableItems = this.getAvailableItems();
6641
+ if (availableItems.length > 0) {
6642
+ const selectedItem = availableItems[this.focused];
6643
+ // Handle both options (objects) and menuItems (FwMenuItemComponent)
6644
+ if (selectedItem instanceof FwMenuItemComponent) {
6645
+ this.selectValue = selectedItem.value;
6646
+ // Manually update selected state for all menu items
6647
+ this.menuItems?.forEach(item => {
6648
+ item.selected = item.value === this.selectValue;
6649
+ });
6650
+ this.updateValue(selectedItem.value);
6651
+ }
6652
+ else {
6653
+ // For options array items, set selectValue first for immediate highlighting
6654
+ const vProp = this.valueProperty();
6655
+ this.selectValue = this.useFullOptionAsValue()
6656
+ ? JSON.stringify(selectedItem)
6657
+ : selectedItem?.[vProp]?.toString();
6658
+ if (this.menu) {
6659
+ this.menu.value = this.selectValue;
6660
+ this.menu.updateLayout();
6661
+ }
6662
+ this.updateValue(selectedItem);
6663
+ }
6664
+ }
6665
+ }, 0);
6418
6666
  }
6419
- if (event.key === 'Enter') {
6667
+ else if (event.key === 'Tab') {
6668
+ this.isTyping.set(false);
6420
6669
  this.close();
6421
6670
  this.inFocusOpen = false;
6422
- const newValue = this.useFullOptionAsValue ? this.JSON.parse(this.value) : this.value;
6423
- this.updateValue(newValue);
6671
+ // Defer updateValue to avoid change detection errors
6672
+ setTimeout(() => {
6673
+ this.updateValue(this.preFocusValue);
6674
+ }, 0);
6424
6675
  }
6425
6676
  }
6426
6677
  else {
6427
6678
  this.inFocusOpen = true;
6428
6679
  this.preFocusValue = this.value;
6680
+ this.initializeFocusedIndex();
6429
6681
  }
6430
6682
  }
6431
6683
  else {
@@ -6438,6 +6690,7 @@ class FwSelectMenuComponent {
6438
6690
  handleKeyUp(event) {
6439
6691
  if (this.trigger.isOpen()) {
6440
6692
  if (event.key === 'Escape') {
6693
+ this.isTyping.set(false);
6441
6694
  this.close();
6442
6695
  this.inFocusOpen = false;
6443
6696
  this.updateValue(this.preFocusValue);
@@ -6454,57 +6707,118 @@ class FwSelectMenuComponent {
6454
6707
  updateValue(newValue) {
6455
6708
  // do housekeeping first
6456
6709
  this.onTouched();
6710
+ const vProp = this.valueProperty();
6711
+ const tProp = this.titleProperty();
6712
+ const iProp = this.iconProperty();
6713
+ const fullOption = this.useFullOptionAsValue();
6457
6714
  // null guard
6458
6715
  if (!newValue) {
6459
6716
  this.selectValue = '';
6460
- this.selectTitle = '';
6717
+ this.selectTitle.set('');
6461
6718
  this.selectIcon = '';
6462
6719
  return this.onChange(newValue);
6463
6720
  }
6464
6721
  if (typeof newValue === 'object') {
6465
- this.selectValue = newValue?.[this.valueProperty]?.toString();
6466
- this.selectTitle = newValue?.[this.titleProperty]?.toString();
6467
- this.selectIcon = newValue?.[this.iconProperty];
6468
- const changeToEmit = this.useFullOptionAsValue ? newValue : newValue[this.valueProperty];
6722
+ this.selectValue = newValue?.[vProp]?.toString();
6723
+ this.selectTitle.set(newValue?.[tProp]?.toString());
6724
+ this.selectIcon = newValue?.[iProp];
6725
+ const changeToEmit = fullOption ? newValue : newValue[vProp];
6469
6726
  return this.onChange(changeToEmit);
6470
6727
  }
6471
- // try and find a matching option
6472
- const matchedOption = this.options.find(option => {
6473
- const matchesValue = option[this.valueProperty] === newValue;
6474
- const matchesTitle = option[this.titleProperty] === newValue;
6728
+ // try and find a matching option in the options array
6729
+ const matchedOption = this.options().find(option => {
6730
+ const matchesValue = option[vProp] === newValue || option[vProp]?.toString() === newValue?.toString();
6731
+ const matchesTitle = option[tProp] === newValue || option[tProp]?.toString() === newValue?.toString();
6475
6732
  return matchesValue || matchesTitle;
6476
6733
  });
6477
6734
  if (matchedOption) {
6478
- this.selectValue = matchedOption[this.valueProperty]?.toString();
6479
- this.selectTitle = matchedOption[this.titleProperty]?.toString();
6480
- this.selectIcon = matchedOption[this.iconProperty];
6481
- const changeToEmit = this.useFullOptionAsValue ? matchedOption : matchedOption[this.valueProperty];
6735
+ this.selectValue = matchedOption[vProp]?.toString();
6736
+ this.selectTitle.set(matchedOption[tProp]?.toString());
6737
+ this.selectIcon = matchedOption[iProp];
6738
+ const changeToEmit = fullOption ? matchedOption : matchedOption[vProp];
6482
6739
  return this.onChange(changeToEmit);
6483
6740
  }
6484
- else {
6485
- // fall back to stringify
6486
- const stringified = newValue.toString() || '';
6487
- this.selectValue = stringified;
6488
- this.selectTitle = stringified;
6489
- return this.onChange(stringified);
6741
+ // try and find a matching menu item in content projected items
6742
+ const matchedMenuItem = this.menuItems?.find(item => item.value === newValue);
6743
+ if (matchedMenuItem) {
6744
+ this.selectValue = matchedMenuItem.value?.toString();
6745
+ this.selectTitle.set(matchedMenuItem.title);
6746
+ this.selectIcon = matchedMenuItem.icon;
6747
+ return this.onChange(matchedMenuItem.value);
6490
6748
  }
6749
+ // fall back to stringify
6750
+ const stringified = newValue.toString() || '';
6751
+ this.selectValue = stringified;
6752
+ this.selectTitle.set(stringified);
6753
+ return this.onChange(stringified);
6491
6754
  }
6492
6755
  handleReset() {
6493
- if (this.showReset) {
6756
+ if (this.showReset()) {
6494
6757
  this.updateValue(null);
6495
6758
  }
6496
6759
  }
6497
6760
  close() {
6498
6761
  this.trigger.close();
6499
- this.filterValue = '';
6500
- this.filterChanged.emit(this.filterValue);
6762
+ this.filterValue.set('');
6763
+ this.filterChanged.emit(this.filterValue());
6764
+ this._isOpen = false;
6765
+ this.isTyping.set(false);
6501
6766
  }
6502
6767
  onFilterChanged(value) {
6503
- this.filterValue = value;
6768
+ // Don't let the menu-container overwrite our filterValue when we're typing
6769
+ if (this.isTyping()) {
6770
+ return;
6771
+ }
6772
+ this.filterValue.set(value);
6504
6773
  this.filterChanged.emit(value);
6505
6774
  }
6506
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: FwSelectMenuComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$4.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
6507
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.18", type: FwSelectMenuComponent, isStandalone: true, selector: "fw-select", inputs: { options: "options", valueProperty: "valueProperty", useFullOptionAsValue: "useFullOptionAsValue", titleProperty: "titleProperty", iconProperty: "iconProperty", staticIcon: "staticIcon", descriptionProperty: "descriptionProperty", showFilter: "showFilter", showReset: "showReset", disabled: "disabled", errored: "errored", width: "width", optionsWidth: "optionsWidth", minOptionsHeight: "minOptionsHeight", maxOptionsHeight: "maxOptionsHeight", size: "size", placeholder: "placeholder", value: "value" }, outputs: { change: "change", filterChanged: "filterChanged" }, host: { listeners: { "document:click": "outsideClick($event.target)" }, properties: { "class.disabled": "this.disabledClass" } }, queries: [{ propertyName: "menuItems", predicate: FwMenuItemComponent, descendants: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: CdkMenuTrigger, descendants: true }, { propertyName: "menu", first: true, predicate: FwMenuComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #wrapper [ngStyle]=\"{width: width, cursor: 'pointer'}\">\n <fw-text-input\n fwMenuRegister\n [cdkMenuTriggerFor]=\"selectMenu\"\n [value]=\"selectTitle\"\n [leftIcon]=\"staticIcon || selectIcon || null\"\n [rightIcon]=\"(selectTitle&&showReset)?'close-circled':'chevron-down'\"\n (rightIconAction)=\"handleReset()\"\n [useActionableIcons]=\"true\"\n [placeholder]=\"placeholder\"\n [size]=\"size\"\n [error]=\"errored || (invalid && touched)\"\n (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\"\n [readOnly]=\"true\">\n </fw-text-input>\n <ng-template #selectMenu>\n <fw-menu-container\n [filterText]=\"filterValue\"\n *ngIf=\"!disabled\" [showFilter]=\"showFilter\" [width]=\"optionsWidth || wrapper.offsetWidth + 'px'\"\n [maxHeight]=\"maxOptionsHeight\" [minHeight]=\"minOptionsHeight\" (filterChanged)=\"onFilterChanged($event)\">\n <fw-menu [disabled]=\"disabled\" [value]=\"selectValue\" (change)=\"handleClick($any($event))\">\n <ng-container *ngIf=\"menuItems.length===0\">\n <fw-menu-item\n *ngFor=\"let item of options\"\n [title]=\"item[titleProperty]?.toString()\"\n [description]=\"item[descriptionProperty]\"\n [value]=\"useFullOptionAsValue ? JSON.stringify(item) : item?.[valueProperty]?.toString()\"\n [icon]=\"item[iconProperty]\"\n [disabled]=\"$any(item).disabled\"\n >\n </fw-menu-item>\n </ng-container>\n <div #menuContentWrapper>\n <ng-content select=\"[fw-menu-item, fw-menu-separator, fw-menu-item-group]\"></ng-content>\n </div>\n </fw-menu>\n </fw-menu-container>\n </ng-template>\n</div>\n", styles: [":host{box-sizing:border-box;max-width:100%}:host.disabled{opacity:.4;cursor:not-allowed}:host.disabled>div{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: FwTextInputComponent, selector: "fw-text-input", inputs: ["disabled", "useActionableIcons", "leftIcon", "rightIcon", "prefix", "context", "helperText", "errorText", "errorInIconTooltip", "placeholder", "readOnly", "size", "type", "maxLength", "autofocus", "autocomplete", "value", "error", "width"], outputs: ["leftIconAction", "rightIconAction"] }, { kind: "directive", type: MenuRegisterDirective, selector: "[fwMenuRegister]" }, { kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FwMenuContainerComponent, selector: "fw-menu-container, fw-menu-filter", inputs: ["width", "maxHeight", "minHeight", "border", "shadow", "showFilter", "filterText", "focusFilterOnMount", "offset", "emptyText", "filterFn", "additionalMenuItems", "keyHandler"], outputs: ["filteredMenuItemChange", "filterChanged"] }, { kind: "component", type: FwMenuComponent, selector: "fw-menu", inputs: ["disabled", "size", "multiSelect", "useCheckbox", "value"], outputs: ["change"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["mouseEnterHandlerChange", "click"] }] }); }
6775
+ onInputChange(event) {
6776
+ const inputElement = event.target;
6777
+ const value = inputElement.value;
6778
+ // Update filterValue with the current input value
6779
+ this.filterValue.set(value);
6780
+ // If there's a filter value and we're not already typing, enter typing mode
6781
+ if (value && !this.isTyping()) {
6782
+ this.isTyping.set(true);
6783
+ this.inFocusOpen = true;
6784
+ this.preFocusValue = this.value;
6785
+ this.initializeFocusedIndex();
6786
+ }
6787
+ else {
6788
+ // Reset focused index to 0 when filter changes (only if already typing)
6789
+ this.focused = 0;
6790
+ }
6791
+ // Defer selectValue update to avoid ExpressionChangedAfterItHasBeenCheckedError
6792
+ // This happens because we're updating state during change detection
6793
+ setTimeout(() => {
6794
+ // Update selectValue to first available item for highlighting
6795
+ const availableItems = this.getAvailableItems();
6796
+ if (availableItems.length > 0) {
6797
+ const firstItem = availableItems[0];
6798
+ // Handle both options (objects) and menuItems (FwMenuItemComponent)
6799
+ if (firstItem instanceof FwMenuItemComponent) {
6800
+ this.selectValue = firstItem.value;
6801
+ }
6802
+ else {
6803
+ this.selectValue = this.useFullOptionAsValue()
6804
+ ? JSON.stringify(firstItem)
6805
+ : firstItem[this.valueProperty()]?.toString();
6806
+ }
6807
+ }
6808
+ else {
6809
+ // Clear selection when no items match
6810
+ this.selectValue = '';
6811
+ }
6812
+ }, 0);
6813
+ this.filterChanged.emit(this.filterValue());
6814
+ // Auto-open dropdown when user starts typing
6815
+ if (this.filterValue() && !this.trigger.isOpen()) {
6816
+ this.trigger.open();
6817
+ this._isOpen = true;
6818
+ }
6819
+ }
6820
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: FwSelectMenuComponent, deps: [{ token: i1$4.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
6821
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: FwSelectMenuComponent, isStandalone: true, selector: "fw-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, valueProperty: { classPropertyName: "valueProperty", publicName: "valueProperty", isSignal: true, isRequired: false, transformFunction: null }, useFullOptionAsValue: { classPropertyName: "useFullOptionAsValue", publicName: "useFullOptionAsValue", isSignal: true, isRequired: false, transformFunction: null }, titleProperty: { classPropertyName: "titleProperty", publicName: "titleProperty", isSignal: true, isRequired: false, transformFunction: null }, iconProperty: { classPropertyName: "iconProperty", publicName: "iconProperty", isSignal: true, isRequired: false, transformFunction: null }, staticIcon: { classPropertyName: "staticIcon", publicName: "staticIcon", isSignal: true, isRequired: false, transformFunction: null }, descriptionProperty: { classPropertyName: "descriptionProperty", publicName: "descriptionProperty", isSignal: true, isRequired: false, transformFunction: null }, showFilter: { classPropertyName: "showFilter", publicName: "showFilter", isSignal: true, isRequired: false, transformFunction: null }, showReset: { classPropertyName: "showReset", publicName: "showReset", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errored: { classPropertyName: "errored", publicName: "errored", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, optionsWidth: { classPropertyName: "optionsWidth", publicName: "optionsWidth", isSignal: true, isRequired: false, transformFunction: null }, minOptionsHeight: { classPropertyName: "minOptionsHeight", publicName: "minOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, maxOptionsHeight: { classPropertyName: "maxOptionsHeight", publicName: "maxOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", change: "change", filterChanged: "filterChanged" }, host: { listeners: { "document:click": "outsideClick($event.target)" }, properties: { "class.disabled": "this.disabledClass" } }, queries: [{ propertyName: "menuItems", predicate: FwMenuItemComponent, descendants: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: CdkMenuTrigger, descendants: true }, { propertyName: "menu", first: true, predicate: FwMenuComponent, descendants: true }, { propertyName: "textInput", first: true, predicate: FwTextInputComponent, descendants: true }], ngImport: i0, template: "<div #wrapper [style.width]=\"width()\">\n <fw-text-input\n fwMenuRegister\n [cdkMenuTriggerFor]=\"selectMenu\"\n [value]=\"inputDisplayValue()\"\n [leftIcon]=\"staticIcon() || selectIcon || null\"\n [rightIcon]=\"(selectTitle()&&showReset())?'close-circled':'chevron-down'\"\n (rightIconAction)=\"handleReset()\"\n [useActionableIcons]=\"true\"\n [placeholder]=\"placeholder()\"\n [size]=\"size()\"\n [error]=\"errored() || (invalid && touched)\"\n (input)=\"onInputChange($event)\"\n (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\"\n (focus)=\"handleFocus()\"\n (click)=\"handleInputClick()\"\n [readOnly]=\"false\">\n </fw-text-input>\n <ng-template #selectMenu>\n @if (!disabled()) {\n <fw-menu-container\n [filterText]=\"filterValue()\"\n [showFilter]=\"showFilter()\" [width]=\"optionsWidth() || wrapper.offsetWidth + 'px'\"\n [maxHeight]=\"maxOptionsHeight()\" [minHeight]=\"minOptionsHeight()\" (filterChanged)=\"onFilterChanged($event)\">\n <fw-menu [disabled]=\"disabled()\" [value]=\"selectValue\" (change)=\"handleClick($any($event))\">\n @if (menuItems.length === 0) {\n @if (optionsWithValues().length > 0) {\n @for (item of optionsWithValues(); track item.trackingId) {\n <fw-menu-item\n [title]=\"item.raw[titleProperty()]?.toString()\"\n [description]=\"item.raw[descriptionProperty()]\"\n [value]=\"item.value\"\n [icon]=\"item.raw[iconProperty()]\"\n [disabled]=\"$any(item.raw).disabled\"\n >\n </fw-menu-item>\n }\n } @else {\n @if (isTyping() && filterValue()) {\n <fw-menu-item\n title=\"No matches found...\"\n [disabled]=\"true\"\n >\n </fw-menu-item>\n }\n }\n }\n <div #menuContentWrapper>\n <ng-content select=\"[fw-menu-item, fw-menu-separator, fw-menu-item-group]\"></ng-content>\n </div>\n </fw-menu>\n </fw-menu-container>\n }\n </ng-template>\n</div>\n", styles: [":host{box-sizing:border-box;max-width:100%}:host>div{cursor:pointer}:host.disabled{opacity:.4;cursor:not-allowed}:host.disabled>div{pointer-events:none}\n"], dependencies: [{ kind: "component", type: FwTextInputComponent, selector: "fw-text-input", inputs: ["disabled", "useActionableIcons", "leftIcon", "rightIcon", "prefix", "context", "helperText", "errorText", "errorInIconTooltip", "placeholder", "readOnly", "size", "type", "maxLength", "autofocus", "autocomplete", "value", "error", "width"], outputs: ["leftIconAction", "rightIconAction"] }, { kind: "directive", type: MenuRegisterDirective, selector: "[fwMenuRegister]" }, { kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "component", type: FwMenuContainerComponent, selector: "fw-menu-container, fw-menu-filter", inputs: ["width", "maxHeight", "minHeight", "border", "shadow", "showFilter", "filterText", "focusFilterOnMount", "offset", "emptyText", "filterFn", "additionalMenuItems", "keyHandler"], outputs: ["filteredMenuItemChange", "filterChanged"] }, { kind: "component", type: FwMenuComponent, selector: "fw-menu", inputs: ["disabled", "size", "multiSelect", "useCheckbox", "value"], outputs: ["change"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["mouseEnterHandlerChange", "click"] }] }); }
6508
6822
  }
6509
6823
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: FwSelectMenuComponent, decorators: [{
6510
6824
  type: Component,
@@ -6518,8 +6832,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
6518
6832
  FwMenuComponent,
6519
6833
  NgFor,
6520
6834
  FwMenuItemComponent,
6521
- ], template: "<div #wrapper [ngStyle]=\"{width: width, cursor: 'pointer'}\">\n <fw-text-input\n fwMenuRegister\n [cdkMenuTriggerFor]=\"selectMenu\"\n [value]=\"selectTitle\"\n [leftIcon]=\"staticIcon || selectIcon || null\"\n [rightIcon]=\"(selectTitle&&showReset)?'close-circled':'chevron-down'\"\n (rightIconAction)=\"handleReset()\"\n [useActionableIcons]=\"true\"\n [placeholder]=\"placeholder\"\n [size]=\"size\"\n [error]=\"errored || (invalid && touched)\"\n (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\"\n [readOnly]=\"true\">\n </fw-text-input>\n <ng-template #selectMenu>\n <fw-menu-container\n [filterText]=\"filterValue\"\n *ngIf=\"!disabled\" [showFilter]=\"showFilter\" [width]=\"optionsWidth || wrapper.offsetWidth + 'px'\"\n [maxHeight]=\"maxOptionsHeight\" [minHeight]=\"minOptionsHeight\" (filterChanged)=\"onFilterChanged($event)\">\n <fw-menu [disabled]=\"disabled\" [value]=\"selectValue\" (change)=\"handleClick($any($event))\">\n <ng-container *ngIf=\"menuItems.length===0\">\n <fw-menu-item\n *ngFor=\"let item of options\"\n [title]=\"item[titleProperty]?.toString()\"\n [description]=\"item[descriptionProperty]\"\n [value]=\"useFullOptionAsValue ? JSON.stringify(item) : item?.[valueProperty]?.toString()\"\n [icon]=\"item[iconProperty]\"\n [disabled]=\"$any(item).disabled\"\n >\n </fw-menu-item>\n </ng-container>\n <div #menuContentWrapper>\n <ng-content select=\"[fw-menu-item, fw-menu-separator, fw-menu-item-group]\"></ng-content>\n </div>\n </fw-menu>\n </fw-menu-container>\n </ng-template>\n</div>\n", styles: [":host{box-sizing:border-box;max-width:100%}:host.disabled{opacity:.4;cursor:not-allowed}:host.disabled>div{pointer-events:none}\n"] }]
6522
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$4.NgControl, decorators: [{
6835
+ ], template: "<div #wrapper [style.width]=\"width()\">\n <fw-text-input\n fwMenuRegister\n [cdkMenuTriggerFor]=\"selectMenu\"\n [value]=\"inputDisplayValue()\"\n [leftIcon]=\"staticIcon() || selectIcon || null\"\n [rightIcon]=\"(selectTitle()&&showReset())?'close-circled':'chevron-down'\"\n (rightIconAction)=\"handleReset()\"\n [useActionableIcons]=\"true\"\n [placeholder]=\"placeholder()\"\n [size]=\"size()\"\n [error]=\"errored() || (invalid && touched)\"\n (input)=\"onInputChange($event)\"\n (keyup)=\"handleKeyUp($event)\"\n (keydown)=\"handleKeyDown($event)\"\n (focus)=\"handleFocus()\"\n (click)=\"handleInputClick()\"\n [readOnly]=\"false\">\n </fw-text-input>\n <ng-template #selectMenu>\n @if (!disabled()) {\n <fw-menu-container\n [filterText]=\"filterValue()\"\n [showFilter]=\"showFilter()\" [width]=\"optionsWidth() || wrapper.offsetWidth + 'px'\"\n [maxHeight]=\"maxOptionsHeight()\" [minHeight]=\"minOptionsHeight()\" (filterChanged)=\"onFilterChanged($event)\">\n <fw-menu [disabled]=\"disabled()\" [value]=\"selectValue\" (change)=\"handleClick($any($event))\">\n @if (menuItems.length === 0) {\n @if (optionsWithValues().length > 0) {\n @for (item of optionsWithValues(); track item.trackingId) {\n <fw-menu-item\n [title]=\"item.raw[titleProperty()]?.toString()\"\n [description]=\"item.raw[descriptionProperty()]\"\n [value]=\"item.value\"\n [icon]=\"item.raw[iconProperty()]\"\n [disabled]=\"$any(item.raw).disabled\"\n >\n </fw-menu-item>\n }\n } @else {\n @if (isTyping() && filterValue()) {\n <fw-menu-item\n title=\"No matches found...\"\n [disabled]=\"true\"\n >\n </fw-menu-item>\n }\n }\n }\n <div #menuContentWrapper>\n <ng-content select=\"[fw-menu-item, fw-menu-separator, fw-menu-item-group]\"></ng-content>\n </div>\n </fw-menu>\n </fw-menu-container>\n }\n </ng-template>\n</div>\n", styles: [":host{box-sizing:border-box;max-width:100%}:host>div{cursor:pointer}:host.disabled{opacity:.4;cursor:not-allowed}:host.disabled>div{pointer-events:none}\n"] }]
6836
+ }], ctorParameters: () => [{ type: i1$4.NgControl, decorators: [{
6523
6837
  type: Optional
6524
6838
  }, {
6525
6839
  type: Self
@@ -6529,46 +6843,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
6529
6843
  }], disabledClass: [{
6530
6844
  type: HostBinding,
6531
6845
  args: ['class.disabled']
6532
- }], options: [{
6533
- type: Input
6534
- }], valueProperty: [{
6535
- type: Input
6536
- }], useFullOptionAsValue: [{
6537
- type: Input
6538
- }], titleProperty: [{
6539
- type: Input
6540
- }], iconProperty: [{
6541
- type: Input
6542
- }], staticIcon: [{
6543
- type: Input
6544
- }], descriptionProperty: [{
6545
- type: Input
6546
- }], showFilter: [{
6547
- type: Input
6548
- }], showReset: [{
6549
- type: Input
6550
- }], disabled: [{
6551
- type: Input
6552
- }], errored: [{
6553
- type: Input
6554
- }], width: [{
6555
- type: Input
6556
- }], optionsWidth: [{
6557
- type: Input
6558
- }], minOptionsHeight: [{
6559
- type: Input
6560
- }], maxOptionsHeight: [{
6561
- type: Input
6562
- }], size: [{
6563
- type: Input
6564
- }], placeholder: [{
6565
- type: Input
6566
6846
  }], trigger: [{
6567
6847
  type: ViewChild,
6568
6848
  args: [CdkMenuTrigger]
6569
6849
  }], menu: [{
6570
6850
  type: ViewChild,
6571
6851
  args: [FwMenuComponent]
6852
+ }], textInput: [{
6853
+ type: ViewChild,
6854
+ args: [FwTextInputComponent]
6572
6855
  }], menuItems: [{
6573
6856
  type: ContentChildren,
6574
6857
  args: [FwMenuItemComponent, { descendants: true }]
@@ -6714,7 +6997,7 @@ class FwPaginatorAdvancedComponent {
6714
6997
  return (this.pageIndex > 0);
6715
6998
  }
6716
6999
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: FwPaginatorAdvancedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6717
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.18", type: FwPaginatorAdvancedComponent, isStandalone: true, selector: "fw-paginator-advanced", inputs: { disabled: "disabled", showNext: "showNext", showPrevious: "showPrevious", showFirst: "showFirst", showLast: "showLast", pageIndex: "pageIndex", pageSizeOptions: "pageSizeOptions", length: "length", alignment: "alignment", selectorTitle: "selectorTitle", pageSize: "pageSize" }, outputs: { page: "page" }, ngImport: i0, template: "<div [ngClass]=\"['paginator', alignment]\">\n <div class=\"pages-selector\">\n <div>\n <p class=\"vision-p2\" [ngClass]=\"disabled?'disabled':''\">{{ selectorTitle }}</p>\n &nbsp;\n <fw-select\n [disabled]=\"disabled\" width=\"80px\" placeholder=\"Size\"\n [(ngModel)]=\"pageSize\">\n <fw-menu-item\n *ngFor=\"let size of pageSizeOptions\"\n [value]=\"size.toString()\"\n [title]=\"size.toString()\"\n [selected]=\"pageSize.toString()===size.toString()\"\n [disabled]=\"disabled\"\n ></fw-menu-item>\n </fw-select>\n </div>\n <p class=\"vision-p2 record-count\" [ngClass]=\"disabled?'disabled':''\">\n {{ getRowIndexStart() + 1 }}-{{ getRowIndexEnd() + 1 }}\n of {{ length }}</p>\n <div>\n <button\n *ngIf=\"showFirst\"\n class=\"page-item page-action page-first\" [disabled]=\"!hasPreviousPage() || disabled\" (click)=\"firstPage()\">\n <fw-icon>arrow-back-collapse</fw-icon>\n </button>\n <button\n *ngIf=\"showPrevious\"\n class=\"page-item page-action page-previous\" [disabled]=\"!hasPreviousPage() || disabled\"\n (click)=\"previousPage()\">\n <fw-icon>chevron-back</fw-icon>\n </button>\n <button\n *ngIf=\"showNext\" class=\"page-item page-action page-next\" [disabled]=\"!hasNextPage() || disabled\"\n (click)=\"nextPage()\">\n <fw-icon>chevron-forward</fw-icon>\n </button>\n <button\n *ngIf=\"showLast\" class=\"page-item page-action page-last\" [disabled]=\"!hasNextPage() || disabled\"\n (click)=\"lastPage()\">\n <fw-icon>arrow-forward-collapse</fw-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: [":host .paginator{display:flex}:host .paginator button{border:none;background-color:transparent}:host .paginator .page-item{box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;align-items:center;border-radius:4px}:host .paginator .page-item:disabled{color:var(--typography-muted);cursor:not-allowed}:host .paginator .page-item:disabled h4{opacity:.4}:host .paginator .page-action fw-icon{font-size:22px;color:var(--typography-base)}:host .paginator .page-action:disabled{opacity:.4}:host .paginator .pages-list{box-sizing:border-box;display:flex;gap:4px}:host .paginator .pages-list .page-number h4{margin:0;color:var(--typography-base)}:host .paginator .pages-list .page-number:disabled h4{color:var(--slate-base)!important}:host .paginator .pages-list .page-active{background-color:var(--slate-focus)}:host .paginator .pages-list .page-active:disabled{background-color:transparent}:host .paginator.start{justify-content:flex-start}:host .paginator.center{justify-content:center}:host .paginator.end{justify-content:flex-end}:host .paginator.large .page-item{width:40px;height:40px}:host .paginator.medium .page-item{width:32px;height:32px}:host .paginator.small .page-item{width:26px;height:26px}:host .paginator.primary .page-active:not(:disabled){background-color:var(--primary-base)!important}:host .paginator.primary .page-active:not(:disabled) h4{color:var(--typography-contrast)!important}:host .paginator.secondary .page-active:not(:disabled){background-color:var(--secondary-base)!important}:host .paginator.secondary .page-active:not(:disabled) h4{color:var(--typography-contrast)!important}:host .paginator.outline .page-item{border:1px solid var(--slate-border)}:host .paginator.outline .page-number:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.outline.primary .page-active{background-color:var(--primary-hover)!important;border-color:var(--primary-border)!important}:host .paginator.outline.primary .page-active h4{color:var(--primary-base)!important}:host .paginator.outline.primary .page-active:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.outline.secondary .page-active{background-color:var(--secondary-hover)!important;border-color:var(--secondary-border)!important}:host .paginator.outline.secondary .page-active h4{color:var(--secondary-base)!important}:host .paginator.outline.secondary .page-active:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.solid .page-item{border:1px solid var(--slate-border);background-color:var(--card-background)}:host .paginator.solid .page-number:disabled{border:1px solid var(--slate-border)!important;background-color:var(--card-background)!important;opacity:.4}:host .paginator.solid .page-number:disabled h4{opacity:1}:host .paginator.circle .page-number{border-radius:999px!important}:host .paginator .pages-selector{display:flex;align-items:center;justify-content:flex-end;gap:16px}:host .paginator .pages-selector>div{display:flex;align-items:center}:host .paginator .pages-selector fw-icon{font-size:22px}:host .paginator .pages-selector .record-count{min-width:130px;text-align:center}:host .paginator .pages-selector p.disabled{color:var(--typography-light)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FwSelectMenuComponent, selector: "fw-select", inputs: ["options", "valueProperty", "useFullOptionAsValue", "titleProperty", "iconProperty", "staticIcon", "descriptionProperty", "showFilter", "showReset", "disabled", "errored", "width", "optionsWidth", "minOptionsHeight", "maxOptionsHeight", "size", "placeholder", "value"], outputs: ["change", "filterChanged"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["mouseEnterHandlerChange", "click"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FwIconComponent, selector: "fw-icon", inputs: ["size", "color"] }] }); }
7000
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.18", type: FwPaginatorAdvancedComponent, isStandalone: true, selector: "fw-paginator-advanced", inputs: { disabled: "disabled", showNext: "showNext", showPrevious: "showPrevious", showFirst: "showFirst", showLast: "showLast", pageIndex: "pageIndex", pageSizeOptions: "pageSizeOptions", length: "length", alignment: "alignment", selectorTitle: "selectorTitle", pageSize: "pageSize" }, outputs: { page: "page" }, ngImport: i0, template: "<div [ngClass]=\"['paginator', alignment]\">\n <div class=\"pages-selector\">\n <div>\n <p class=\"vision-p2\" [ngClass]=\"disabled?'disabled':''\">{{ selectorTitle }}</p>\n &nbsp;\n <fw-select\n [disabled]=\"disabled\" width=\"80px\" placeholder=\"Size\"\n [(ngModel)]=\"pageSize\">\n <fw-menu-item\n *ngFor=\"let size of pageSizeOptions\"\n [value]=\"size.toString()\"\n [title]=\"size.toString()\"\n [selected]=\"pageSize.toString()===size.toString()\"\n [disabled]=\"disabled\"\n ></fw-menu-item>\n </fw-select>\n </div>\n <p class=\"vision-p2 record-count\" [ngClass]=\"disabled?'disabled':''\">\n {{ getRowIndexStart() + 1 }}-{{ getRowIndexEnd() + 1 }}\n of {{ length }}</p>\n <div>\n <button\n *ngIf=\"showFirst\"\n class=\"page-item page-action page-first\" [disabled]=\"!hasPreviousPage() || disabled\" (click)=\"firstPage()\">\n <fw-icon>arrow-back-collapse</fw-icon>\n </button>\n <button\n *ngIf=\"showPrevious\"\n class=\"page-item page-action page-previous\" [disabled]=\"!hasPreviousPage() || disabled\"\n (click)=\"previousPage()\">\n <fw-icon>chevron-back</fw-icon>\n </button>\n <button\n *ngIf=\"showNext\" class=\"page-item page-action page-next\" [disabled]=\"!hasNextPage() || disabled\"\n (click)=\"nextPage()\">\n <fw-icon>chevron-forward</fw-icon>\n </button>\n <button\n *ngIf=\"showLast\" class=\"page-item page-action page-last\" [disabled]=\"!hasNextPage() || disabled\"\n (click)=\"lastPage()\">\n <fw-icon>arrow-forward-collapse</fw-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: [":host .paginator{display:flex}:host .paginator button{border:none;background-color:transparent}:host .paginator .page-item{box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;align-items:center;border-radius:4px}:host .paginator .page-item:disabled{color:var(--typography-muted);cursor:not-allowed}:host .paginator .page-item:disabled h4{opacity:.4}:host .paginator .page-action fw-icon{font-size:22px;color:var(--typography-base)}:host .paginator .page-action:disabled{opacity:.4}:host .paginator .pages-list{box-sizing:border-box;display:flex;gap:4px}:host .paginator .pages-list .page-number h4{margin:0;color:var(--typography-base)}:host .paginator .pages-list .page-number:disabled h4{color:var(--slate-base)!important}:host .paginator .pages-list .page-active{background-color:var(--slate-focus)}:host .paginator .pages-list .page-active:disabled{background-color:transparent}:host .paginator.start{justify-content:flex-start}:host .paginator.center{justify-content:center}:host .paginator.end{justify-content:flex-end}:host .paginator.large .page-item{width:40px;height:40px}:host .paginator.medium .page-item{width:32px;height:32px}:host .paginator.small .page-item{width:26px;height:26px}:host .paginator.primary .page-active:not(:disabled){background-color:var(--primary-base)!important}:host .paginator.primary .page-active:not(:disabled) h4{color:var(--typography-contrast)!important}:host .paginator.secondary .page-active:not(:disabled){background-color:var(--secondary-base)!important}:host .paginator.secondary .page-active:not(:disabled) h4{color:var(--typography-contrast)!important}:host .paginator.outline .page-item{border:1px solid var(--slate-border)}:host .paginator.outline .page-number:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.outline.primary .page-active{background-color:var(--primary-hover)!important;border-color:var(--primary-border)!important}:host .paginator.outline.primary .page-active h4{color:var(--primary-base)!important}:host .paginator.outline.primary .page-active:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.outline.secondary .page-active{background-color:var(--secondary-hover)!important;border-color:var(--secondary-border)!important}:host .paginator.outline.secondary .page-active h4{color:var(--secondary-base)!important}:host .paginator.outline.secondary .page-active:disabled{border:1px solid var(--slate-border)!important;background-color:transparent!important}:host .paginator.solid .page-item{border:1px solid var(--slate-border);background-color:var(--card-background)}:host .paginator.solid .page-number:disabled{border:1px solid var(--slate-border)!important;background-color:var(--card-background)!important;opacity:.4}:host .paginator.solid .page-number:disabled h4{opacity:1}:host .paginator.circle .page-number{border-radius:999px!important}:host .paginator .pages-selector{display:flex;align-items:center;justify-content:flex-end;gap:16px}:host .paginator .pages-selector>div{display:flex;align-items:center}:host .paginator .pages-selector fw-icon{font-size:22px}:host .paginator .pages-selector .record-count{min-width:130px;text-align:center}:host .paginator .pages-selector p.disabled{color:var(--typography-light)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FwSelectMenuComponent, selector: "fw-select", inputs: ["options", "valueProperty", "useFullOptionAsValue", "titleProperty", "iconProperty", "staticIcon", "descriptionProperty", "showFilter", "showReset", "disabled", "errored", "width", "optionsWidth", "minOptionsHeight", "maxOptionsHeight", "size", "placeholder", "value"], outputs: ["disabledChange", "change", "filterChanged"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["mouseEnterHandlerChange", "click"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FwIconComponent, selector: "fw-icon", inputs: ["size", "color"] }] }); }
6718
7001
  }
6719
7002
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: FwPaginatorAdvancedComponent, decorators: [{
6720
7003
  type: Component,