@acorex/components 22.0.0-next.10 → 22.0.0-next.13

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.
@@ -3841,16 +3841,17 @@ class AXConversationService {
3841
3841
  }
3842
3842
  /**
3843
3843
  * Get available users for conversation creation
3844
- * @param query - Optional search query
3845
- * @returns List of users
3844
+ * @param filters - Optional search filters (e.g. `query`)
3845
+ * @param pagination - Pagination parameters
3846
+ * @returns Paginated list of users
3846
3847
  */
3847
- async getUsers(query) {
3848
+ async getUsers(filters, pagination = { page: 0, pageSize: 50 }) {
3848
3849
  try {
3849
- return await this.userApi.getUsers({ query });
3850
+ return await this.userApi.getUsers(pagination, filters);
3850
3851
  }
3851
3852
  catch (error) {
3852
- this.errorHandler.handle(error, 'getUsers', { query });
3853
- return [];
3853
+ this.errorHandler.handle(error, 'getUsers', { filters, pagination });
3854
+ return { items: [], total: 0, hasMore: false, page: pagination.page };
3854
3855
  }
3855
3856
  }
3856
3857
  /**
@@ -7017,7 +7018,7 @@ class AXConversationInfoBarComponent {
7017
7018
  [inputs]="getInlineComponentInputs()"
7018
7019
  />
7019
7020
  } @else {
7020
- <ax-button class="action-button" (onClick)="onInlineActionClick(action.id)">
7021
+ <ax-button class="action-button" (onClick)="onInlineActionClick(action.id)" look="ghost">
7021
7022
  <ax-icon [icon]="registry.infoBarActions.getActionIcon(action, activeConversation()!)"></ax-icon>
7022
7023
  </ax-button>
7023
7024
  }
@@ -7154,7 +7155,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
7154
7155
  [inputs]="getInlineComponentInputs()"
7155
7156
  />
7156
7157
  } @else {
7157
- <ax-button class="action-button" (onClick)="onInlineActionClick(action.id)">
7158
+ <ax-button class="action-button" (onClick)="onInlineActionClick(action.id)" look="ghost">
7158
7159
  <ax-icon [icon]="registry.infoBarActions.getActionIcon(action, activeConversation()!)"></ax-icon>
7159
7160
  </ax-button>
7160
7161
  }
@@ -10284,17 +10285,20 @@ class AXConversationNewDialogComponent extends AXBasePageComponent {
10284
10285
  this.usersList = viewChild('usersList', /* @ts-ignore */
10285
10286
  ...(ngDevMode ? [{ debugName: "usersList" }] : /* istanbul ignore next */ []));
10286
10287
  this.usersListDataSource = new AXDataSource({
10287
- pageSize: 100,
10288
+ pageSize: 10,
10288
10289
  key: 'id',
10289
10290
  load: async (e) => {
10290
- if (this.availableUsers().length === 0) {
10291
- const users = await this.conversationService.getUsers();
10292
- this.availableUsers.set(users);
10293
- }
10294
- const filtered = this.filteredUsers();
10291
+ const query = this.searchQuery().trim();
10292
+ const filters = query ? { query } : undefined;
10293
+ const page = e.take > 0 ? Math.floor(e.skip / e.take) : 0;
10294
+ const result = await this.conversationService.getUsers(filters, {
10295
+ page,
10296
+ pageSize: e.take,
10297
+ });
10298
+ this.mergeUsersCache(result.items);
10295
10299
  return {
10296
- items: filtered.slice(e.skip, e.skip + e.take),
10297
- total: filtered.length,
10300
+ items: result.items,
10301
+ total: result.total ?? result.items.length,
10298
10302
  };
10299
10303
  },
10300
10304
  byKey: (key) => Promise.resolve(this.availableUsers().find((u) => u.id === key) ?? null),
@@ -10329,14 +10333,16 @@ class AXConversationNewDialogComponent extends AXBasePageComponent {
10329
10333
  return null;
10330
10334
  return item.data ?? null;
10331
10335
  }
10332
- filteredUsers() {
10333
- const q = this.searchQuery().toLowerCase().trim();
10334
- if (!q)
10335
- return this.availableUsers();
10336
- return this.availableUsers().filter((u) => {
10337
- const name = u.name.toLowerCase();
10338
- const desc = (u.description ?? '').toLowerCase();
10339
- return name.includes(q) || desc.includes(q);
10336
+ mergeUsersCache(users) {
10337
+ if (users.length === 0) {
10338
+ return;
10339
+ }
10340
+ this.availableUsers.update((existing) => {
10341
+ const byId = new Map(existing.map((user) => [user.id, user]));
10342
+ for (const user of users) {
10343
+ byId.set(user.id, user);
10344
+ }
10345
+ return Array.from(byId.values());
10340
10346
  });
10341
10347
  }
10342
10348
  async onCreateConversation() {
@@ -10386,6 +10392,14 @@ class AXConversationNewDialogComponent extends AXBasePageComponent {
10386
10392
  @if (showUserPickerStep()) {
10387
10393
  <div class="form-field form-field--grow">
10388
10394
  <div class="users-list-wrap">
10395
+ <div class="users-list-search">
10396
+ <ax-search-box
10397
+ [value]="searchQuery()"
10398
+ (valueChange)="onSearchChange($event)"
10399
+ [disabled]="creating()"
10400
+ [placeholder]="'@acorex:chat.placeholders.search-users' | translate | async"
10401
+ ></ax-search-box>
10402
+ </div>
10389
10403
  <ax-list
10390
10404
  #usersList
10391
10405
  class="users-list"
@@ -10395,23 +10409,12 @@ class AXConversationNewDialogComponent extends AXBasePageComponent {
10395
10409
  [disabled]="creating()"
10396
10410
  [valueField]="'id'"
10397
10411
  [textField]="'name'"
10398
- [itemHeight]="52"
10412
+ [itemHeight]="60"
10399
10413
  [ngModel]="selectedUserIds()"
10400
10414
  (ngModelChange)="onSelectedUsersChange($event ?? [])"
10401
10415
  [emptyTemplate]="usersListEmptyTpl()"
10402
10416
  [itemTemplate]="userItemTpl"
10403
- >
10404
- <ax-header class="users-list-header">
10405
- <div class="users-list-header-inner">
10406
- <ax-search-box
10407
- [value]="searchQuery()"
10408
- (valueChange)="onSearchChange($event)"
10409
- [disabled]="creating()"
10410
- [placeholder]="'@acorex:chat.placeholders.search-users' | translate | async"
10411
- ></ax-search-box>
10412
- </div>
10413
- </ax-header>
10414
- </ax-list>
10417
+ ></ax-list>
10415
10418
  </div>
10416
10419
  </div>
10417
10420
  }
@@ -10503,7 +10506,7 @@ class AXConversationNewDialogComponent extends AXBasePageComponent {
10503
10506
  </div>
10504
10507
  }
10505
10508
  </ng-template>
10506
- `, isInline: true, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.group-details-step{flex:1;min-height:0;padding:.5rem .75rem;display:flex;flex-direction:column;gap:.75rem}.form-field{display:flex;flex-direction:column;gap:.35rem}.field-label{font-size:.875rem;font-weight:500;color:var(--ax-text-secondary, #6b7280)}.title-input{height:2.25rem;border-radius:.5rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface));padding:0 .7rem;color:rgb(var(--ax-sys-color-on-surface));font:inherit}.title-input:focus{outline:2px solid rgba(var(--ax-sys-color-primary-500),.25);outline-offset:0}.users-list-wrap{height:min(50vh,36rem);overflow:hidden}.users-list{display:block;height:100%}.users-list-header{display:block;position:sticky;top:0;z-index:1;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.users-list-header-inner{padding:.5rem .75rem}.user-item-content{display:flex;align-items:center;gap:.75rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.125rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface))}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXConversationAvatarPickerComponent, selector: "ax-conversation-avatar-picker", inputs: ["showClearButton", "avatarUrl"], outputs: ["avatarUrlChange", "onFileSelected"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }] }); }
10509
+ `, isInline: true, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.group-details-step{flex:1;min-height:0;padding:.5rem .75rem;display:flex;flex-direction:column;gap:.75rem}.form-field{display:flex;flex-direction:column;gap:.35rem}.field-label{font-size:.875rem;font-weight:500;color:var(--ax-text-secondary, #6b7280)}.title-input{height:2.25rem;border-radius:.5rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface));padding:0 .7rem;color:rgb(var(--ax-sys-color-on-surface));font:inherit}.title-input:focus{outline:2px solid rgba(var(--ax-sys-color-primary-500),.25);outline-offset:0}.users-list-wrap{display:flex;flex-direction:column;height:min(50vh,36rem);overflow:hidden}.users-list-search{flex:0 0 auto;padding:.5rem .75rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}.users-list{display:block;flex:1 1 auto;min-height:0}.user-item-content{display:flex;align-items:center;gap:.75rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.125rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface))}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXConversationAvatarPickerComponent, selector: "ax-conversation-avatar-picker", inputs: ["showClearButton", "avatarUrl"], outputs: ["avatarUrlChange", "onFileSelected"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }] }); }
10507
10510
  }
10508
10511
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationNewDialogComponent, decorators: [{
10509
10512
  type: Component,
@@ -10523,6 +10526,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10523
10526
  @if (showUserPickerStep()) {
10524
10527
  <div class="form-field form-field--grow">
10525
10528
  <div class="users-list-wrap">
10529
+ <div class="users-list-search">
10530
+ <ax-search-box
10531
+ [value]="searchQuery()"
10532
+ (valueChange)="onSearchChange($event)"
10533
+ [disabled]="creating()"
10534
+ [placeholder]="'@acorex:chat.placeholders.search-users' | translate | async"
10535
+ ></ax-search-box>
10536
+ </div>
10526
10537
  <ax-list
10527
10538
  #usersList
10528
10539
  class="users-list"
@@ -10532,23 +10543,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10532
10543
  [disabled]="creating()"
10533
10544
  [valueField]="'id'"
10534
10545
  [textField]="'name'"
10535
- [itemHeight]="52"
10546
+ [itemHeight]="60"
10536
10547
  [ngModel]="selectedUserIds()"
10537
10548
  (ngModelChange)="onSelectedUsersChange($event ?? [])"
10538
10549
  [emptyTemplate]="usersListEmptyTpl()"
10539
10550
  [itemTemplate]="userItemTpl"
10540
- >
10541
- <ax-header class="users-list-header">
10542
- <div class="users-list-header-inner">
10543
- <ax-search-box
10544
- [value]="searchQuery()"
10545
- (valueChange)="onSearchChange($event)"
10546
- [disabled]="creating()"
10547
- [placeholder]="'@acorex:chat.placeholders.search-users' | translate | async"
10548
- ></ax-search-box>
10549
- </div>
10550
- </ax-header>
10551
- </ax-list>
10551
+ ></ax-list>
10552
10552
  </div>
10553
10553
  </div>
10554
10554
  }
@@ -10640,7 +10640,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10640
10640
  </div>
10641
10641
  }
10642
10642
  </ng-template>
10643
- `, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.group-details-step{flex:1;min-height:0;padding:.5rem .75rem;display:flex;flex-direction:column;gap:.75rem}.form-field{display:flex;flex-direction:column;gap:.35rem}.field-label{font-size:.875rem;font-weight:500;color:var(--ax-text-secondary, #6b7280)}.title-input{height:2.25rem;border-radius:.5rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface));padding:0 .7rem;color:rgb(var(--ax-sys-color-on-surface));font:inherit}.title-input:focus{outline:2px solid rgba(var(--ax-sys-color-primary-500),.25);outline-offset:0}.users-list-wrap{height:min(50vh,36rem);overflow:hidden}.users-list{display:block;height:100%}.users-list-header{display:block;position:sticky;top:0;z-index:1;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.users-list-header-inner{padding:.5rem .75rem}.user-item-content{display:flex;align-items:center;gap:.75rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.125rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface))}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}\n"] }]
10643
+ `, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.group-details-step{flex:1;min-height:0;padding:.5rem .75rem;display:flex;flex-direction:column;gap:.75rem}.form-field{display:flex;flex-direction:column;gap:.35rem}.field-label{font-size:.875rem;font-weight:500;color:var(--ax-text-secondary, #6b7280)}.title-input{height:2.25rem;border-radius:.5rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface));padding:0 .7rem;color:rgb(var(--ax-sys-color-on-surface));font:inherit}.title-input:focus{outline:2px solid rgba(var(--ax-sys-color-primary-500),.25);outline-offset:0}.users-list-wrap{display:flex;flex-direction:column;height:min(50vh,36rem);overflow:hidden}.users-list-search{flex:0 0 auto;padding:.5rem .75rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}.users-list{display:block;flex:1 1 auto;min-height:0}.user-item-content{display:flex;align-items:center;gap:.75rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.125rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:500;color:rgb(var(--ax-sys-color-on-surface))}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}\n"] }]
10644
10644
  }], propDecorators: { __popup__: [{ type: i0.Input, args: [{ isSignal: true, alias: "__popup__", required: false }] }], usersListEmptyTpl: [{ type: i0.ViewChild, args: ['usersListEmpty', { isSignal: true }] }], usersList: [{ type: i0.ViewChild, args: ['usersList', { isSignal: true }] }] } });
10645
10645
 
10646
10646
  var newConversationDialog_component = /*#__PURE__*/Object.freeze({
@@ -11305,14 +11305,47 @@ var sharedStorage = /*#__PURE__*/Object.freeze({
11305
11305
  });
11306
11306
 
11307
11307
  /**
11308
- * Extra seed data so sidebar and message-list pagination can be exercised in the demo.
11308
+ * Extra seed data so sidebar, message-list, and user-picker pagination can be exercised in the demo.
11309
11309
  */
11310
11310
  const AX_CONVERSATION_MIN_CONVERSATIONS_FOR_PAGINATION = 200;
11311
11311
  const AX_CONVERSATION_MIN_MESSAGES_CONV_1 = 500;
11312
+ const AX_CONVERSATION_MIN_USERS_FOR_PAGINATION = 50;
11313
+ /**
11314
+ * Append demo users when the participant list is too small for the new-conversation picker (page size 10).
11315
+ */
11316
+ async function ensureUsersPaginationDemoData() {
11317
+ const users = Array.from(axConversationSharedStorage.participants.values()).filter((user) => user.id !== axConversationSharedStorage.currentUserId);
11318
+ if (users.length >= AX_CONVERSATION_MIN_USERS_FOR_PAGINATION) {
11319
+ return;
11320
+ }
11321
+ const toCreate = AX_CONVERSATION_MIN_USERS_FOR_PAGINATION - users.length;
11322
+ const statuses = ['online', 'offline', 'away'];
11323
+ const titles = ['Developer', 'Designer', 'Manager', 'Analyst', 'Engineer', 'QA', 'DevOps', 'Support'];
11324
+ for (let i = 0; i < toCreate; i++) {
11325
+ const index = users.length + i + 1;
11326
+ const participant = {
11327
+ id: `user-pag-${index}`,
11328
+ name: `Demo User ${String(index).padStart(2, '0')}`,
11329
+ description: `${titles[i % titles.length]} · Pagination demo`,
11330
+ avatar: `https://i.pravatar.cc/150?img=${(index % 70) + 1}`,
11331
+ status: statuses[i % statuses.length],
11332
+ lastSeen: new Date(Date.now() - i * 300_000),
11333
+ profile: {
11334
+ bio: `Mock user #${index} for new-conversation list pagination`,
11335
+ email: `demo.user.${index}@example.com`,
11336
+ title: titles[i % titles.length],
11337
+ },
11338
+ metadata: { tags: ['demo', 'pagination'] },
11339
+ };
11340
+ axConversationSharedStorage.participants.set(participant.id, participant);
11341
+ await axConversationIndexedDbStorage.putParticipant(participant);
11342
+ }
11343
+ }
11312
11344
  /**
11313
11345
  * Append demo chats/messages when the DB is too small for default page sizes (30 / 50).
11314
11346
  */
11315
11347
  async function ensurePaginationDemoData() {
11348
+ await ensureUsersPaginationDemoData();
11316
11349
  const conversationCount = axConversationSharedStorage.conversations.size;
11317
11350
  const conv1Messages = axConversationSharedStorage.messagesByConversation.get('conv-1')?.length ?? 0;
11318
11351
  if (conversationCount >= AX_CONVERSATION_MIN_CONVERSATIONS_FOR_PAGINATION && conv1Messages >= AX_CONVERSATION_MIN_MESSAGES_CONV_1) {
@@ -12266,20 +12299,23 @@ class AXConversationIndexedDbUserApi extends AXConversationUserApi {
12266
12299
  // =====================
12267
12300
  // User Discovery
12268
12301
  // =====================
12269
- async getUsers(filters) {
12302
+ async getUsers(pagination = { page: 0, pageSize: 50 }, filters) {
12270
12303
  const users = Array.from(axConversationSharedStorage.participants.values());
12271
- const filtered = users.filter((u) => u.id !== axConversationSharedStorage.currentUserId);
12272
- if (!filters?.query)
12273
- return filtered;
12274
- const q = filters.query.toLowerCase();
12275
- return filtered.filter((u) => {
12276
- const name = u.name.toLowerCase();
12277
- const desc = (u.description ?? '').toLowerCase();
12278
- return name.includes(q) || desc.includes(q);
12279
- });
12304
+ let filtered = users.filter((u) => u.id !== axConversationSharedStorage.currentUserId);
12305
+ if (filters?.query) {
12306
+ const q = filters.query.toLowerCase();
12307
+ filtered = filtered.filter((u) => {
12308
+ const name = u.name.toLowerCase();
12309
+ const desc = (u.description ?? '').toLowerCase();
12310
+ return name.includes(q) || desc.includes(q);
12311
+ });
12312
+ }
12313
+ filtered.sort((a, b) => a.name.localeCompare(b.name));
12314
+ return paginateChatOldestFirst(filtered, pagination);
12280
12315
  }
12281
12316
  async searchUsers(query) {
12282
- return this.getUsers({ query });
12317
+ const result = await this.getUsers({ page: 0, pageSize: 1000 }, { query });
12318
+ return result.items;
12283
12319
  }
12284
12320
  async getUserById(userId) {
12285
12321
  const user = axConversationSharedStorage.participants.get(userId);