diff --git a/packages/ui/src/lib/components/SegmentControl/Segment.svelte b/packages/ui/src/lib/components/SegmentControl/Segment.svelte new file mode 100644 index 000000000..2af14996b --- /dev/null +++ b/packages/ui/src/lib/components/SegmentControl/Segment.svelte @@ -0,0 +1,104 @@ + + + + + diff --git a/packages/ui/src/lib/components/SegmentControl/SegmentedControl.svelte b/packages/ui/src/lib/components/SegmentControl/SegmentedControl.svelte new file mode 100644 index 000000000..5fb3c962a --- /dev/null +++ b/packages/ui/src/lib/components/SegmentControl/SegmentedControl.svelte @@ -0,0 +1,55 @@ + + +
+ +
+ + diff --git a/packages/ui/src/lib/components/SegmentControl/segment.ts b/packages/ui/src/lib/components/SegmentControl/segment.ts new file mode 100644 index 000000000..00d8003a7 --- /dev/null +++ b/packages/ui/src/lib/components/SegmentControl/segment.ts @@ -0,0 +1,15 @@ +import type { Writable } from 'svelte/store'; + +export interface SegmentItem { + id: string; + index: number; + disabled: boolean; +} +export interface SegmentContext { + focusedSegmentIndex: Writable; + selectedSegmentIndex: Writable; + length: Writable; + setIndex(): number; + addSegment(segment: SegmentItem): void; + setSelected(index: number): void; +} diff --git a/packages/ui/src/lib/components/TextBox.svelte b/packages/ui/src/lib/components/TextBox.svelte new file mode 100644 index 000000000..f45ea294c --- /dev/null +++ b/packages/ui/src/lib/components/TextBox.svelte @@ -0,0 +1,59 @@ + + +
+ {#if icon && iconPosition == 'left'} + + {/if} + dispatch('input', e.currentTarget.value)} + /> + {#if icon && iconPosition == 'right'} + + {/if} +
+ + diff --git a/packages/ui/src/routes/[projectId]/navigation/BranchFilter.svelte b/packages/ui/src/routes/[projectId]/navigation/BranchFilter.svelte index 3e345bfaa..ab49713c1 100644 --- a/packages/ui/src/routes/[projectId]/navigation/BranchFilter.svelte +++ b/packages/ui/src/routes/[projectId]/navigation/BranchFilter.svelte @@ -1,11 +1,45 @@ - -
- - + + +
+ textFilter$.next(e.detail)} /> +
+ onSelect(e.detail)} wide selectedIndex={0}> + {#each options as option} + {option.name} + {/each} + +
+ + diff --git a/packages/ui/src/routes/[projectId]/navigation/Branches.svelte b/packages/ui/src/routes/[projectId]/navigation/Branches.svelte index 3c02a1708..b1a6168e8 100644 --- a/packages/ui/src/routes/[projectId]/navigation/Branches.svelte +++ b/packages/ui/src/routes/[projectId]/navigation/Branches.svelte @@ -8,6 +8,9 @@ import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings'; import SectionHeader from './SectionHeader.svelte'; import { accordion } from './accordion'; + import BranchFilter, { type TypeFilter } from './BranchFilter.svelte'; + import { BehaviorSubject, combineLatest } from 'rxjs'; + import type { CombinedBranch } from '$lib/branches/types'; const userSettings = getContext(SETTINGS_CONTEXT); @@ -15,7 +18,14 @@ export let projectId: string; export let expanded = false; + export const textFilter$ = new BehaviorSubject(undefined); + export const typeFilter$ = new BehaviorSubject('all'); + $: branches$ = branchService.branches$; + $: filteredBranches$ = combineLatest( + [branchService.branches$, typeFilter$, textFilter$], + (branches, type, search) => searchFilter(typeFilter(branches, type), search) + ); let viewport: HTMLElement; let contents: HTMLElement; @@ -24,6 +34,22 @@ const onScroll: UIEventHandler = (e) => { scrolled = e.currentTarget.scrollTop != 0; }; + + function typeFilter(branches: CombinedBranch[], type: TypeFilter): CombinedBranch[] { + switch (type) { + case 'all': + return branches; + case 'branch': + return branches.filter((b) => b.branch && !b.pr); + case 'pr': + return branches.filter((b) => b.pr); + } + } + + function searchFilter(branches: CombinedBranch[], search: string | undefined) { + if (search == undefined) return branches; + return branches.filter((b) => b.displayName.includes(search)); + } {#if expanded} @@ -50,9 +76,10 @@ style:height={`${$userSettings.vbranchExpandableHeight}px`} >
+
- {#if $branches$} - {#each $branches$ as branch} + {#if $filteredBranches$} + {#each $filteredBranches$ as branch} {/each} {/if} @@ -67,6 +94,9 @@ overflow: hidden; } .viewport { + display: flex; + flex-direction: column; + gap: var(--space-12); height: 100%; overflow-y: scroll; overscroll-behavior: none;