rxjs#switchMap TypeScript Examples

The following examples show how to use rxjs#switchMap. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: base-select.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterContentInit() {
    this.customCreatedOptions$ = combineLatest([
      this.values$,
      (
        this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
      ).pipe(
        startWith(this.contentOptions),
        switchMap((options: QueryList<OptionComponent<T>>) =>
          options.length > 0
            ? combineLatest(options.map(option => option.value$))
            : of([] as T[]),
        ),
      ),
    ]).pipe(
      map(([values, optionValues]) =>
        values.reduce<Array<SelectFilterOption<T>>>((acc, value) => {
          const included = optionValues
            .map(value => this.trackFn(value))
            .includes(this.trackFn(value));
          if (!included) {
            const label =
              this.labelFn?.(value) || coerceString(this.trackFn(value));
            if (label) {
              acc.push({
                label,
                value,
              });
            }
          }
          return acc;
        }, []),
      ),
      publishRef(),
    );
  }
Example #2
Source File: publish-list.tsx    From bext with MIT License 6 votes vote down vote up
Banner: FC<{ current: number; empty?: boolean }> = ({
  current,
  empty,
}) => {
  const nextTime = useObservableState(
    useObservable(
      (input$) =>
        input$.pipe(
          pluckFirst,
          switchMap((current) =>
            timer(0, 1000).pipe(
              map(() => current + REFRESH_DURATION - Date.now()),
            ),
          ),
        ),
      [current],
    ),
    REFRESH_DURATION,
  );

  return (
    <Separator>
      {empty ? '暂无' : ''}发布历史({' '}
      {nextTime > 0 ? `${Math.floor(nextTime / 1000)} 秒后刷新` : '刷新中'})
    </Separator>
  );
}
Example #3
Source File: auth.ts    From bext with MIT License 6 votes vote down vote up
octokit$
  .pipe(
    switchMap((octokit) =>
      octokit
        ? from(octokit.rest.users.getAuthenticated()).pipe(
            map(({ data, status }) =>
              status === 200
                ? ({ status: 'complete', user: data } as const)
                : ({ status: 'error' } as const),
            ),
            startWith({ status: 'loading' } as const),
            retry(2),
            catchError(() => of({ status: 'error' } as const)),
          )
        : of({ status: 'unauth' } as const),
    ),
  )
  .subscribe(user$);
Example #4
Source File: tree-select.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterViewInit() {
    const hasVisibleChildNodes$ = this.childNodes.changes.pipe(
      startWith(this.childNodes),
      switchMap((nodes: QueryList<TreeNodeComponent<T>>) =>
        nodes.length > 0
          ? combineLatest(nodes.map(node => node.visible$))
          : of([false]),
      ),
      map(visible => visible.some(Boolean)),
      tap(hasVisibleChildren => (this.isLeaf = !hasVisibleChildren)),
    );
    this.visible$ = combineLatest([
      this.selfVisible$,
      hasVisibleChildNodes$,
    ]).pipe(
      map(visible => visible.some(Boolean)),
      publishRef(),
    );

    this.visible$.pipe(takeUntil(this.destroy$$)).subscribe(visible => {
      this.visible = visible;
      this.cdr.markForCheck();
    });
    this.selected$.pipe(takeUntil(this.destroy$$)).subscribe(selected => {
      this.selected = selected;
      this.cdr.markForCheck();
    });

    if (this.selected) {
      requestAnimationFrame(() => {
        this.scrollToNode(this);
      });
    }
  }
Example #5
Source File: option-group.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterContentInit() {
    this.hasVisibleOption$ = this.options.changes.pipe(
      startWith(this.options),
      switchMap((options: QueryList<OptionComponent<T>>) =>
        options.length > 0
          ? combineLatest(options.map(node => node.visible$))
          : of([false]),
      ),
      map(visible => visible.some(Boolean)),
      publishRef(),
    );
  }
Example #6
Source File: multi-select.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
override ngAfterViewInit() {
    super.ngAfterViewInit();
    this.selectAllStatus$ = combineLatest([
      this.allOptions$,
      this.filterString$,
    ]).pipe(
      switchMap(([allOptions]) =>
        combineLatest([
          ...(allOptions ?? [])
            .filter(({ visible, disabled }) => visible && !disabled)
            .map(({ selected$ }) => selected$),
        ]),
      ),
      map(statuses => {
        const selected = statuses.filter(Boolean);
        return selected.length === 0
          ? SelectAllStatus.Empty
          : selected.length !== statuses.length
          ? SelectAllStatus.Indeterminate
          : SelectAllStatus.Checked;
      }),
      startWith(SelectAllStatus.Empty),
      tap(selectAllStatus => (this.selectAllStatus = selectAllStatus)),
      publishRef(),
    );
    this.hasEnabledOptions$ = combineLatest([
      this.allOptions$,
      this.filterString$,
    ]).pipe(
      map(
        ([allOptions]) =>
          !!allOptions.filter(({ visible, disabled }) => visible && !disabled)
            .length,
      ),
    );
  }
Example #7
Source File: interpreter.ts    From platyplus with MIT License 6 votes vote down vote up
visit$(
    node: ASTNode,
    value$: Observable<ObjectType>
  ): Observable<ObjectType> {
    return value$.pipe(
      switchMap(
        (value) =>
          ACTIONS[node.type]?.(this, node, value) ||
          throwError(() => new Error('Unknown node type: ' + node.type))
      )
    )
  }
Example #8
Source File: search.ts    From platyplus with MIT License 6 votes vote down vote up
search$ =
  (
    expression: string | Observable<string>,
    options: SearchOptions = {}
  ): ((data$: Observable<ObjectType>) => Observable<ObjectType>) =>
  (data$) => {
    try {
      const runtime = new Runtime()
      const interpreter = new Intercepter(runtime, options)
      runtime._interpreter = interpreter
      return (isObservable(expression) ? expression : of(expression)).pipe(
        switchMap((exp) => {
          // ? Not ideal. Find a better workaround?
          if (options.circularData && expression === '*')
            throw new Error(
              `Data schema is circular; The expression '*' is not allowed`
            )
          const node = compile(exp)
          return interpreter.visit$(node, data$)
        })
      )
    } catch (error) {
      return throwError(() => new Error(error))
    }
  }
Example #9
Source File: form-item.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterContentInit() {
    this.hasError$ = this.ngControls.changes.pipe(
      startWith(this.ngControls),
      switchMap((controls: QueryList<NgControl>) =>
        combineLatest(
          controls.map(control => this.mapControlStatus(control)),
        ).pipe(map(statuses => statuses.some(Boolean))),
      ),
    );

    this.errorCount$ = this.errors.changes.pipe(
      map(errors => errors.length),
      startWith(this.errors.length),
    );

    this.hintCount$ = this.hints.changes.pipe(
      map(hints => hints.length),
      startWith(this.hints.length),
    );
  }
Example #10
Source File: back-top.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
isDisplayed$ = combineLatest([
    this.target$$.asObservable().pipe(
      map(target => this.getTarget(target)),
      switchMap(target =>
        fromEvent(target, 'scroll').pipe(
          // use default scheduler
          throttleTime(50, undefined, { leading: true, trailing: true }),
          map(() => this.getTargetScrollTop(target)),
        ),
      ),
    ),
    this.visibilityHeight$$,
  ]).pipe(
    map(([scrollTop, visibilityHeight]) => scrollTop >= visibilityHeight),
    distinctUntilChanged(),
  );
Example #11
Source File: suggestion-group.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterContentInit() {
    this.hasVisibleSuggestion$ = this.suggestions.changes.pipe(
      startWith(this.suggestions),
      switchMap((options: QueryList<SuggestionComponent>) =>
        options.length > 0
          ? combineLatest(options.map(node => node.visible$))
          : of([false]),
      ),
      map(visible => visible.some(Boolean)),
      publishRef(),
    );
  }
Example #12
Source File: suggestion.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
constructor(
    private readonly cdr: ChangeDetectorRef,
    @Inject(forwardRef(() => AutocompleteComponent))
    autocomplete: any, // FIXME: workaround temporarily
  ) {
    this.autocomplete = autocomplete;
    this.selected$ = combineLatest([
      this.autocomplete.directive$$.pipe(
        switchMap(directive => directive.inputValue$),
      ),
      this.value$$,
    ]).pipe(
      map(([inputValue, selfValue]) => inputValue === selfValue),
      tap(selected => {
        this.selected = selected;
      }),
      publishRef(),
    );
    this.visible$ = combineLatest([
      this.autocomplete.directive$$.pipe(
        switchMap(directive => directive.filterFn$),
      ),
      this.autocomplete.directive$$.pipe(
        switchMap(directive => directive.inputValue$),
      ),
      this.value$$,
    ]).pipe(
      map(([filterFn, filterString, suggestion]) =>
        filterFn(filterString, suggestion),
      ),
      tap(visible => {
        this.visible = visible;
      }),
      publishRef(),
    );
  }
Example #13
Source File: autocomplete.component.ts    From alauda-ui with MIT License 6 votes vote down vote up
ngAfterContentInit() {
    this.hasVisibleSuggestion$ = this.suggestions.changes.pipe(
      startWith(this.suggestions),
      switchMap((suggestions: QueryList<SuggestionComponent>) =>
        suggestions.length > 0
          ? combineLatest(suggestions.map(suggestion => suggestion.visible$))
          : of([] as boolean[]),
      ),
      map(visible => visible.some(Boolean)),
      withLatestFrom(this.directive$$),
      map(([hasVisibleSuggestion, directive]) => {
        if (hasVisibleSuggestion && directive.defaultFirstSuggestion) {
          directive.autoFocusFirstSuggestion();
        }
        return hasVisibleSuggestion;
      }),
      distinctUntilChanged(),
      debounceTime(0),
      tap(() => this.cdr.markForCheck()),
      publishRef(),
    );

    this.hasContent$ = combineLatest([
      this.hasVisibleSuggestion$,
      this.placeholder.changes.pipe(
        startWith(this.placeholder),
        map(
          (list: QueryList<AutocompletePlaceholderComponent>) => !!list.length,
        ),
      ),
    ]).pipe(
      map(
        ([hasVisibleSuggestion, hasPlaceholder]) =>
          hasVisibleSuggestion || hasPlaceholder,
      ),
    );
  }
Example #14
Source File: app-shell.component.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
private installRouteActivateListener(): void {
    this._routeActivate$
      .pipe(
        switchMap(() => Beans.get(ContextService).observe$<OutletContext>(OUTLET_CONTEXT)),
        takeUntil(this._destroy$),
      )
      .subscribe(outletContext => {
        const context = outletContext?.name ?? 'n/a';
        console.debug(`[AppShellComponent::router-outlet:onactivate] [app=${this.appSymbolicName}, location=${window.location.href}, outletContext=${context}]]`);
      });
  }
Example #15
Source File: wowup-protocol.service.ts    From WowUp with GNU General Public License v3.0 6 votes vote down vote up
public initialize() {
    this._electronService.customProtocol$
      .pipe(
        tap((prt) => console.log("WowUpProtocolService", prt)),
        filter((prt) => getProtocol(prt) === APP_PROTOCOL_NAME && this.isInstallAction(prt)),
        switchMap((prt) => this.onInstallProtocol(prt)),
        catchError((e) => {
          console.error(e);
          return of(undefined);
        })
      )
      .subscribe();
  }
Example #16
Source File: options-addon-section.component.ts    From WowUp with GNU General Public License v3.0 6 votes vote down vote up
public constructor(
    private _addonProviderService: AddonProviderFactory,
    private _sensitiveStorageService: SensitiveStorageService,
    private _translateService: TranslateService,
    private _dialogFactory: DialogFactory,
    private _linkService: LinkService
  ) {
    this._addonProviderService.addonProviderChange$.subscribe(() => {
      this.loadProviderStates();
    });

    this.preferenceForm.valueChanges
      .pipe(
        takeUntil(this.destroy$),
        debounceTime(300),
        switchMap((ch) => {
          const tasks: Observable<any>[] = [];
          if (typeof ch?.cfV2ApiKey === "string") {
            tasks.push(from(this._sensitiveStorageService.setAsync(PREF_CF2_API_KEY, ch.cfV2ApiKey)));
          }
          if (typeof ch?.ghPersonalAccessToken === "string") {
            tasks.push(
              from(this._sensitiveStorageService.setAsync(PREF_GITHUB_PERSONAL_ACCESS_TOKEN, ch.ghPersonalAccessToken))
            );
          }
          return combineLatest(tasks);
        }),
        catchError((e) => {
          console.error(e);
          return of(undefined);
        })
      )
      .subscribe();
  }
Example #17
Source File: options-addon-section.component.ts    From WowUp with GNU General Public License v3.0 6 votes vote down vote up
private onWagoEnable(option: MatListOption) {
    const providerName: AddonProviderType = option.value;
    const title: string = this._translateService.instant("DIALOGS.PERMISSIONS.WAGO.TOGGLE_LABEL");
    const message: string = this._translateService.instant("DIALOGS.PERMISSIONS.WAGO.DESCRIPTION", {
      termsUrl: AppConfig.wago.termsUrl,
      dataUrl: AppConfig.wago.dataConsentUrl,
    });

    const dialogRef = this._dialogFactory.getConfirmDialog(title, message);
    dialogRef
      .afterClosed()
      .pipe(
        first(),
        switchMap((result) => {
          if (result) {
            return from(this._addonProviderService.setProviderEnabled(providerName, option.selected));
          } else {
            option.selected = !option.selected;
          }
          return of(undefined);
        }),
        catchError((err) => {
          console.error(err);
          return of(undefined);
        })
      )
      .subscribe();
  }
Example #18
Source File: context-service.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
   * Observes the names of context values registered at any level in the context tree.
   *
   * @return An Observable that emits the names of context values registered at any level in the context tree.
   *         Upon subscription, it emits the names of context values currently registered, and then it emits whenever
   *         some value is registered or unregistered from a context. The Observable never completes.
   */
  public names$(): Observable<Set<string>> {
    if (Beans.get(IS_PLATFORM_HOST)) {
      return concat(of(new Set<string>()), NEVER);
    }

    return this._contextTreeChange$
      .pipe(
        startWith(undefined as void),
        switchMap(() => this.lookupContextNames$()),
      );
  }
Example #19
Source File: context-service.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
public observe$<T>(name: string, options?: ContextLookupOptions): Observable<T | T[] | null> {
    if (Beans.get(IS_PLATFORM_HOST)) {
      return concat(of(options?.collect ? [] : null), NEVER);
    }

    return this._contextTreeChange$
      .pipe(
        filter(event => event.name === name),
        startWith(undefined as void),
        switchMap(() => this.lookupContextValue$<T>(name, options)),
      );
  }
Example #20
Source File: plugin.ts    From platyplus with MIT License 5 votes vote down vote up
options: SearchOptions<{ systemFields: boolean; deleted: boolean }> = {
  getField: (value, key: string | number, options) => {
    if (!options.systemFields && typeof key === 'string' && key.startsWith('_'))
      return of(null)

    if (isRxDocument(value)) {
      const document: RxDocument = value
      // TODO combineLatest as per getIdentity
      return document.deleted$.pipe(
        switchMap((deleted) => {
          if (!options.deleted && deleted) return of(null)
          if (typeof key === 'number') return of(value[key] ?? null)
          const definition = value.collection.schema.jsonSchema.properties[key]
          if (definition) {
            if (definition.ref) {
              return document
                .get$(key)
                .pipe(switchMap(() => document.populate(key)))
            } else {
              return document.get$(key)
            }
          } else return of(value[key] ?? null)
        })
      )
    } else return of(value[key] ?? null)
  },

  getIdentity: (value, { systemFields }) => {
    if (isRxDocument(value)) {
      const document: RxDocument = value
      return combineLatest([document.deleted$, document.$]).pipe(
        map(([deleted, value]) => {
          if (!options.deleted && deleted) return of(null)
          else {
            if (systemFields) return value
            else return trimSystemFields(value)
          }
        })
      )
    } else return of(value)
  },
  circularData: true,
  systemFields: false,
  deleted: false
}
Example #21
Source File: select.tsx    From platyplus with MIT License 5 votes vote down vote up
DocumentSelectField: FieldComponent = ({
  role,
  tableinfo,
  document,
  name,
  edit,
  editable,
  property
}) => {
  // TODO async - see https://rsuitejs.com/components/select-picker/#Async
  const refTable = useTableInfo(
    relationshipTableId(tableinfo, property.relationship)
  )
  const [data, setData] = useState<ContentsDocument>(null)
  const collection = useContentsCollection(refTable, role)
  useEffect(() => {
    // ? use rxdb-utils view? -> document[name].$.subscribe...
    if (collection && document && name in document) {
      const subscription = document
        .get$(name)
        .pipe(
          filter((id) => {
            if (id) return true
            else {
              setData(null)
              return false
            }
          }),
          switchMap((id) => collection.findOne(id).$)
        )
        .subscribe((refDocument) => {
          setData(refDocument)
        })
      return () => subscription.unsubscribe()
    }
  }, [document, name, tableinfo.id, role, collection])

  const options = useOptions(refTable, role)

  return editable && edit ? (
    <FieldControl
      style={{ minWidth: 300 }}
      name={name}
      readOnly={!edit}
      data={options}
      cleanable={edit}
      accepter={SelectPicker}
    />
  ) : data ? (
    <DocumentComponentWrapper
      tableinfo={refTable}
      role={role}
      document={data}
      componentName="tag"
      edit={false}
    />
  ) : null
}
Example #22
Source File: wrapper.tsx    From platyplus with MIT License 5 votes vote down vote up
CollectionField: CollectionFieldComponent = ({
  document,
  name,
  property,
  role,
  edit,
  editable,
  tableinfo,
  accepter: Accepter,
  component = 'label'
}) => {
  const refTable = shiftedTable(tableinfo, property.relationship)
  const refCollection = useContentsCollection(refTable, role)

  const [data, setData] = useState<ContentsDocument[]>([])
  useEffect(() => {
    // ? use rxdb-utils view? -> document[name].$.subscribe...
    if (refCollection && name in document) {
      const subscription = document
        .get$(name)
        .pipe(
          filter((values) => values),
          switchMap((values) => refCollection.findByIds$(values))
        )
        .subscribe((mapDocs: Map<string, ContentsDocument>) => {
          setData([...mapDocs.values()])
        })
      return () => subscription.unsubscribe()
    }
  }, [document, name, refCollection, property])

  const options = useOptions(refTable, role)

  return editable && edit ? (
    <FieldControl
      tableinfo={tableinfo}
      role={role}
      style={{ minWidth: 300 }}
      name={name}
      readOnly={!edit}
      data={options}
      initial={data}
      cleanable={edit}
      accepter={Accepter}
    />
  ) : (
    <CollectionComponentWrapper
      tableinfo={refTable}
      role={role}
      data={data}
      componentName={component}
      edit={false}
    />
  )
}
Example #23
Source File: index.ts    From platyplus with MIT License 5 votes vote down vote up
createRxHasura = async (
  name: string,
  url: string,
  password?: string
): Promise<Database> => {
  addRxPlugin(RxDBReplicationGraphQLPlugin)
  addRxPlugin(RxDBAjvValidatePlugin)
  addRxPlugin(RxHasuraPlugin)
  addPouchPlugin(require('rxdb/plugins/migration'))
  addRxPlugin(require('rxdb/plugins/leader-election'))
  addRxPlugin(require('rxdb/plugins/update'))
  addPouchPlugin(require('rxdb/plugins/query-builder'))

  if (process.env.NODE_ENV === 'development')
    addPouchPlugin(require('rxdb/plugins/dev-mode'))

  // * IMPORTANT: Do not use addRxPlugin to add pouchdb adapter, instead use addPouchPlugin
  if (persist) addPouchPlugin(require('pouchdb-adapter-idb'))
  else addPouchPlugin(require('pouchdb-adapter-memory'))

  const settings: RxDatabaseCreator = {
    name,
    password,
    multiInstance: false, // ! Causes errors when set to true. See notice in https://rxdb.info/leader-election.html
    eventReduce: true, // <- eventReduce (optional, default: true))
    options: {
      url
    },
    storage: getRxStoragePouch(persist ? 'idb' : 'memory')
  }

  const db = (await createRxDatabase<DatabaseCollections>(
    settings
  )) as unknown as Database

  debug('db', `created: ${settings.name}`)
  if (process.env.NODE_ENV === 'development' || process.env.DEBUG)
    window['db'] = db // write to window for debugging

  // * When being connected, browse the roles and create table info accordingly
  db.isAuthenticated$
    .pipe(
      distinctUntilChanged(),
      filter((status) => status),
      switchMap(() => db.isConfigReady$)
    )
    .subscribe(async (ready) => {
      debug('db', 'first time authenticated. Is ready?', ready)
      if (ready) addTableInfoCollection(db)
      else await initConfigCollections(db)
    })

  db.isReady$
    .pipe(
      filter((ready) => ready && !!db.collections[TABLE_INFO_TABLE]),
      switchMap(() => db.collections[TABLE_INFO_TABLE].find().$)
    )
    .subscribe((tables) => createContentsCollections(db, tables))

  // * runs when db becomes leader
  db.waitForLeadership().then(() => {
    debug('db', 'took the leadership')
  })

  return db
}
Example #24
Source File: publish-list.tsx    From bext with MIT License 5 votes vote down vote up
PublishList: FC = () => (
  <div className="py-3">
    {useObservableState(
      useObservable(() =>
        user$.pipe(
          switchMap(({ status, user }) => {
            switch (status) {
              case 'loading':
                return of(<Spinner />);
              case 'complete':
                const octokit = octokit$.getValue()!;
                return timer(0, REFRESH_DURATION).pipe(
                  switchMap(() =>
                    from(
                      octokit.paginate(octokit.search.issuesAndPullRequests, {
                        q: `is:pr author:${user?.login} repo:${packageJson.metaRepository.owner}/${packageJson.metaRepository.repo}`,
                        sort: 'created',
                        order: 'desc',
                      }),
                    ).pipe(
                      map((items) => (
                        <>
                          <Banner current={Date.now()} empty={!items.length} />
                          {items.length ? (
                            <List
                              items={items}
                              onRenderCell={(item) => <PrItem item={item!} />}
                            />
                          ) : null}
                        </>
                      )),
                      retry(2),
                      catchError(() =>
                        of(<div className="text-center">出错了...</div>),
                      ),
                    ),
                  ),
                );
              default:
                return of(
                  <div className="text-center">
                    <LoginLink /> 后查看发布历史
                  </div>,
                );
            }
          }),
          startWith(<Spinner />),
        ),
      ),
    ) || null}
  </div>
)
Example #25
Source File: rxjsResourceStub.ts    From slickgrid-universal with MIT License 5 votes vote down vote up
switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>> {
    return switchMap(project);
  }
Example #26
Source File: rxjs.resource.ts    From slickgrid-universal with MIT License 5 votes vote down vote up
/** Projects each source value to an Observable which is merged in the output Observable, emitting values only from the most recently projected Observable. */
  switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>> {
    return switchMap(project);
  }
Example #27
Source File: toc-container.directive.ts    From alauda-ui with MIT License 5 votes vote down vote up
ngAfterContentInit() {
    const actived$ = this._scrollTop$
      .pipe(
        startWith(this.scrollTop),
        debounceTime(200),
        map(scrollTop =>
          this._contents.reduce(
            this.isScrollEnd
              ? this.getMaxContent.bind(this)
              : this.getMinContent(scrollTop),
          ),
        ),
        map(actived => actived.auiTocContent),
      )
      .pipe(
        tap(actived => {
          this._contents.forEach(content => {
            content.active = actived === content.auiTocContent;
          });
          this.cdr.detectChanges();
        }),
      );

    const scrollTween$ = this._scrollTo$.pipe(
      switchMap(name => {
        const target = this._contents.find(
          content => content.auiTocContent === name,
        );

        if (!target) {
          return EMPTY;
        }
        const destination = this.getOffsetTop(target.nativeElement);

        const start = performance.now();
        const source = this.scrollTop;
        const duration = 500;

        return of(0).pipe(
          observeOn(animationFrameScheduler),
          repeat(),
          map(() => (performance.now() - start) / duration),
          takeWhile(t => t < 1),
          endWith(1),
          map(t => t * t * t),
          map(t => source * (1 - t) + destination * t),
        );
      }),
      takeUntil(this._onDestroy$),
    );

    this._subs.push(
      actived$.subscribe(this.activedChange),
      scrollTween$.subscribe(tweenValue => {
        this.scrollTop = tweenValue;
      }),
    );
  }
Example #28
Source File: select.component.ts    From alauda-ui with MIT License 5 votes vote down vote up
override ngAfterContentInit() {
    super.ngAfterContentInit();

    this.selectedOption$ = combineLatest([
      (
        this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
      ).pipe(
        startWith(this.contentOptions),
        switchMap(options =>
          combineLatest(options.map(option => option.selected$)).pipe(
            startWith(null as void),
            map(() => options.find(option => option.selected)),
            distinctUntilChanged(),
            switchMap(option =>
              option
                ? combineLatest([
                    option.value$,
                    option.label$,
                    option.labelContext$,
                  ]).pipe(
                    map(([value, label, labelContext]) => ({
                      value,
                      label,
                      labelContext,
                    })),
                  )
                : of(null as void),
            ),
          ),
        ),
      ),
      this.model$,
    ]).pipe(
      map(([option, value]) =>
        option
          ? {
              label:
                option.label ||
                this.labelFn?.(option.value) ||
                coerceString(this.trackFn(option.value)),
              // https://github.com/angular/angular/issues/24515
              labelContext: {
                ...(option.labelContext as Record<string, unknown>),
              },
            }
          : {
              label: this.labelFn?.(value) || coerceString(this.trackFn(value)),
            },
      ),
      publishRef(),
    );

    this.hasSelected$ = this.selectedOption$.pipe(
      map(({ label }) => !!label),
      publishRef(),
    );
  }
Example #29
Source File: multi-select.component.ts    From alauda-ui with MIT License 5 votes vote down vote up
override ngAfterContentInit() {
    super.ngAfterContentInit();

    this.selectedOptions$ = combineLatest([
      this.model$,
      (
        this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
      ).pipe(
        startWith(this.contentOptions),
        switchMap((options: QueryList<OptionComponent<T>>) =>
          options.length > 0
            ? combineLatest(
                options.map(option =>
                  combineLatest([
                    option.value$,
                    option.label$,
                    option.labelContext$,
                    option.disabled$,
                  ]).pipe(
                    map(([value, label, labelContext, disabled]) => ({
                      value,
                      label,
                      labelContext,
                      disabled,
                    })),
                  ),
                ),
              )
            : of([] as Array<SelectFilterOption<T>>),
        ),
      ),
    ]).pipe(
      map(([values, options]) =>
        values
          .map(value => {
            const option = options.find(
              option => this.trackFn(option.value) === this.trackFn(value),
            );
            return option
              ? {
                  label:
                    option.label || coerceString(this.trackFn(option.value)),
                  labelContext: option.labelContext,
                  value: option.value,
                  disabled: option.disabled,
                }
              : {
                  label:
                    this.labelFn?.(value) || coerceString(this.trackFn(value)),
                  value,
                };
          })
          // sort disabled options as first
          .sort((a, b) => {
            if (a.disabled) {
              return -1;
            }

            if (b.disabled) {
              return 1;
            }

            return 0;
          }),
      ),
      publishRef(),
    );
  }