@@ -29,49 +29,64 @@ const VFolderRelayResolver = ({
2929 ) ;
3030} ;
3131
32+ // V2 VFolder mock shape: `id`, `status`, `metadata { name }`. The component
33+ // derives local UUIDs (used for `valuePropName='row_id'`) via `toLocalId(id)`
34+ // at render time, so stories no longer need to provide a separate `row_id`.
3235const sampleVFolders = [
3336 {
3437 node : {
35- id : 'VkZvbGRlck5vZGU6MTIzNDU2Nzg5MA==' ,
36- name : 'my-project-data' ,
37- row_id : 'abcd1234-5678-90ef-ghij-klmnopqrstuv' ,
38+ id : 'VkZvbGRlcjphYmNkMTIzNC01Njc4LTkwZWYtZ2hpai1rbG1ub3BxcnN0dXY=' ,
39+ status : 'READY' ,
40+ metadata : {
41+ name : 'my-project-data' ,
42+ } ,
3843 } ,
3944 } ,
4045 {
4146 node : {
42- id : 'VkZvbGRlck5vZGU6MDk4NzY1NDMyMQ==' ,
43- name : 'shared-datasets' ,
44- row_id : 'wxyz9876-5432-10ab-cdef-ghijklmnopqr' ,
47+ id : 'VkZvbGRlcjp3eHl6OTg3Ni01NDMyLTEwYWItY2RlZi1naGlqa2xtbm9wcXI=' ,
48+ status : 'READY' ,
49+ metadata : {
50+ name : 'shared-datasets' ,
51+ } ,
4552 } ,
4653 } ,
4754 {
4855 node : {
49- id : 'VkZvbGRlck5vZGU6MTExMTExMTExMQ==' ,
50- name : 'model-checkpoints' ,
51- row_id : 'aaaa1111-2222-3333-4444-555566667777' ,
56+ id : 'VkZvbGRlcjphYWFhMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NjY2Njc3Nzc=' ,
57+ status : 'READY' ,
58+ metadata : {
59+ name : 'model-checkpoints' ,
60+ } ,
5261 } ,
5362 } ,
5463 {
5564 node : {
56- id : 'VkZvbGRlck5vZGU6MjIyMjIyMjIyMg==' ,
57- name : 'training-logs' ,
58- row_id : 'bbbb2222-3333-4444-5555-666677778888' ,
65+ id : 'VkZvbGRlcjpiYmJiMjIyMi0zMzMzLTQ0NDQtNTU1NS02NjY2Nzc3Nzg4ODg=' ,
66+ status : 'READY' ,
67+ metadata : {
68+ name : 'training-logs' ,
69+ } ,
5970 } ,
6071 } ,
6172 {
6273 node : {
63- id : 'VkZvbGRlck5vZGU6MzMzMzMzMzMzMw==' ,
64- name : 'test-results' ,
65- row_id : 'cccc3333-4444-5555-6666-777788889999' ,
74+ id : 'VkZvbGRlcjpjY2NjMzMzMy00NDQ0LTU1NTUtNjY2Ni03Nzc3ODg4ODk5OTk=' ,
75+ status : 'READY' ,
76+ metadata : {
77+ name : 'test-results' ,
78+ } ,
6679 } ,
6780 } ,
6881] ;
6982
7083const sampleManyVFolders = Array . from ( { length : 15 } , ( _ , i ) => ( {
7184 node : {
72- id : `VkZvbGRlck5vZGU6${ i + 1000000000 } ` ,
73- name : `vfolder-${ i + 1 } ` ,
74- row_id : `${ i . toString ( ) . padStart ( 8 , '0' ) } -aaaa-bbbb-cccc-ddddeeeefffff` ,
85+ id : `VkZvbGRlcjowMDAwMDAwMC1hYWFhLWJiYmItY2NjYy1kZGRkZWVlZWZmZmY=-${ i } ` ,
86+ status : 'READY' ,
87+ metadata : {
88+ name : `vfolder-${ i + 1 } ` ,
89+ } ,
7590 } ,
7691} ) ) ;
7792
@@ -106,24 +121,24 @@ const meta: Meta<typeof BAIVFolderSelect> = {
106121
107122| Name | Type | Default | Description |
108123|------|------|---------|-------------|
109- | \`currentProjectId\` | \`string\` | - | Project ID to scope vfolder selection |
124+ | \`currentProjectId\` | \`string\` | - | Project ID to scope vfolder selection. When set, the paginated query uses \`projectVfolders\`; otherwise \`myVfolders\`. |
110125| \`onClickVFolder\` | \`(value: string) => void\` | - | Callback when vfolder name is clicked |
111- | \`filter\` | \`string\ ` | - | Additional filter string for vfolder query |
126+ | \`filter\` | \`VFolderFilter \\| null\ ` | - | Additional structured filter merged into the paginated query (AND-combined with internal filters) |
112127| \`valuePropName\` | \`'id' \\| 'row_id'\` | \`'id'\` | Which field to use as option value |
113128| \`excludeDeleted\` | \`boolean\` | \`false\` | Exclude deleted or deleting vfolders |
114129| \`ref\` | \`React.Ref<BAIVFolderSelectRef>\` | - | Ref exposing \`refetch()\` method |
115130
116131## Features
117- - Fetches vfolders from two GraphQL queries:
118- - \`BAIVFolderSelectValueQuery\`: Fetch selected vfolder labels
119- - \`BAIVFolderSelectPaginatedQuery\`: Fetch paginated available vfolders
132+ - Strawberry V2 GraphQL queries:
133+ - \`BAIVFolderSelectValueQuery\`: Resolves preselected vfolders by id via aliased \`vfolderV2(vfolderId:)\` lookups (up to 10 slots)
134+ - \`BAIVFolderSelectPaginatedQuery\`: Paginated \`myVfolders\` / \`projectVfolders\` depending on \`currentProjectId\`
120135- Pagination support with \`useLazyPaginatedQuery\` hook
121- - Search functionality with debounced loading state
136+ - Search functionality with debounced loading state, using \`VFolderFilter.name.iContains\`
122137- Infinite scroll via \`endReached\` callback
123138- Total count footer with loading indicator
124139- Custom label/option rendering with ID display (truncated)
125140- Clickable vfolder names when \`onClickVFolder\` is provided
126- - Automatic filtering of deleted vfolders when \`excludeDeleted\` is true
141+ - Automatic filtering of deleted vfolders via \`VFolderOperationStatusFilter\` when \`excludeDeleted\` is true
127142- Project scoping through \`currentProjectId\` prop
128143- Optimistic UI updates for smooth user experience
129144- Exposed \`refetch()\` method via ref
@@ -133,23 +148,15 @@ const meta: Meta<typeof BAIVFolderSelect> = {
133148### Value Query (for selected items)
134149\`\`\`graphql
135150query BAIVFolderSelectValueQuery(
136- $selectedFilter: String
137- $skipSelectedVFolder : Boolean!
138- $scopeId: ScopeField
151+ $id0: UUID!
152+ $include0 : Boolean!
153+ # ... up to $id9 / $include9
139154) {
140- vfolder_nodes(
141- scope_id: $scopeId
142- filter: $selectedFilter
143- permission: "read_attribute"
144- ) @skip(if: $skipSelectedVFolder) {
145- edges {
146- node {
147- name
148- id
149- row_id
150- }
151- }
155+ v0: vfolderV2(vfolderId: $id0) @include(if: $include0) {
156+ id
157+ metadata { name }
152158 }
159+ # ... v1..v9
153160}
154161\`\`\`
155162
@@ -158,26 +165,25 @@ query BAIVFolderSelectValueQuery(
158165query BAIVFolderSelectPaginatedQuery(
159166 $offset: Int!
160167 $limit: Int!
161- $scopeId: ScopeField
162- $filter: String
163- $permission: VFolderPermissionValueField
168+ $projectId: UUID
169+ $filter: VFolderFilter
170+ $orderBy: [VFolderOrderBy!]
171+ $useProject: Boolean!
164172) {
165- vfolder_nodes(
166- scope_id: $scopeId
173+ myVfolders(offset: $offset, limit: $limit, filter: $filter, orderBy: $orderBy)
174+ @skip(if: $useProject) {
175+ count
176+ edges { node { id metadata { name } } }
177+ }
178+ projectVfolders(
179+ projectId: $projectId
167180 offset: $offset
168- first : $limit
181+ limit : $limit
169182 filter: $filter
170- permission: $permission
171- order: "-created_at"
172- ) {
183+ orderBy: $orderBy
184+ ) @include(if: $useProject) {
173185 count
174- edges {
175- node {
176- id
177- name
178- row_id
179- }
180- }
186+ edges { node { id metadata { name } } }
181187 }
182188}
183189\`\`\`
@@ -190,16 +196,16 @@ query BAIVFolderSelectPaginatedQuery(
190196 onChange={(value) => console.log(value)}
191197/>
192198
193- // With project scoping
199+ // With project scoping (uses projectVfolders)
194200<BAIVFolderSelect
195201 currentProjectId="project-123"
196202 excludeDeleted
197203 onChange={(value) => console.log(value)}
198204/>
199205
200- // With clickable names
206+ // With structured filter
201207<BAIVFolderSelect
202- onClickVFolder={(id) => window.open(\`/vfolder/\${id}\`) }
208+ filter={{ name: { iContains: 'test' } } }
203209 onChange={(value) => console.log(value)}
204210/>
205211
@@ -230,11 +236,11 @@ For all other props, refer to [BAISelect](/?path=/docs/components-input-baiselec
230236 description : 'Callback when vfolder name is clicked' ,
231237 } ,
232238 filter : {
233- control : { type : 'text' } ,
239+ control : false ,
234240 description :
235- 'Additional filter string for vfolder query (e.g., " name ilike \'% test%\'" )' ,
241+ 'Additional VFolderFilter merged into the paginated query (e.g., `{ name: { iContains: " test" } }` )' ,
236242 table : {
237- type : { summary : 'string ' } ,
243+ type : { summary : 'VFolderFilter | null ' } ,
238244 } ,
239245 } ,
240246 valuePropName : {
@@ -308,7 +314,11 @@ export const Default: Story = {
308314 < VFolderRelayResolver
309315 mockResolvers = { {
310316 Query : ( ) => ( {
311- vfolder_nodes : {
317+ myVfolders : {
318+ count : 5 ,
319+ edges : sampleVFolders ,
320+ } ,
321+ projectVfolders : {
312322 count : 5 ,
313323 edges : sampleVFolders ,
314324 } ,
@@ -338,7 +348,11 @@ export const Empty: Story = {
338348 < VFolderRelayResolver
339349 mockResolvers = { {
340350 Query : ( ) => ( {
341- vfolder_nodes : {
351+ myVfolders : {
352+ count : 0 ,
353+ edges : [ ] ,
354+ } ,
355+ projectVfolders : {
342356 count : 0 ,
343357 edges : [ ] ,
344358 } ,
@@ -370,7 +384,11 @@ export const ManyVFolders: Story = {
370384 < VFolderRelayResolver
371385 mockResolvers = { {
372386 Query : ( ) => ( {
373- vfolder_nodes : {
387+ myVfolders : {
388+ count : 15 ,
389+ edges : sampleManyVFolders ,
390+ } ,
391+ projectVfolders : {
374392 count : 15 ,
375393 edges : sampleManyVFolders ,
376394 } ,
@@ -402,7 +420,11 @@ export const WithClickableNames: Story = {
402420 < VFolderRelayResolver
403421 mockResolvers = { {
404422 Query : ( ) => ( {
405- vfolder_nodes : {
423+ myVfolders : {
424+ count : 5 ,
425+ edges : sampleVFolders ,
426+ } ,
427+ projectVfolders : {
406428 count : 5 ,
407429 edges : sampleVFolders ,
408430 } ,
@@ -439,7 +461,11 @@ export const WithRowId: Story = {
439461 < VFolderRelayResolver
440462 mockResolvers = { {
441463 Query : ( ) => ( {
442- vfolder_nodes : {
464+ myVfolders : {
465+ count : 5 ,
466+ edges : sampleVFolders ,
467+ } ,
468+ projectVfolders : {
443469 count : 5 ,
444470 edges : sampleVFolders ,
445471 } ,
0 commit comments