PluginFieldsSelect
A dropdown for selecting Tracker fields within a plugin. Accepts a flat list of fields with category metadata and automatically groups them into collapsible sections. Supports search, multiple selection, apply/reset buttons, and a loading state.
Basic usage
import {PluginFieldsSelect} from '@weavix/tracker-components';
import type {PluginFieldsSelectField} from '@weavix/tracker-components';
const fields: PluginFieldsSelectField[] = [
{id: 'summary', name: 'Summary', category: {id: '1', display: 'System fields'}},
{id: 'description', name: 'Description', category: {id: '1', display: 'System fields'}},
{id: 'sprint', name: 'Sprint', category: {id: '2', display: 'Custom fields'}},
];
<PluginFieldsSelect
open={true}
fields={fields}
onOpenChange={(open) => console.log(open)}
onItemSelect={(item) => console.log('selected', item)}
onItemDeselect={(item) => console.log('deselected', item)}
/>;
Example 1 — Initial global fields loading only
Loads all global fields once when mounted. Search works on the client side using the already loaded list.
import React, {useEffect, useState} from 'react';
import {PluginFieldsSelect} from '@weavix/tracker-components';
import type {PluginFieldsSelectField, TrackerSelectItem} from '@weavix/tracker-components';
interface Props {
trackerApi: TrackerApi;
onSubmit: (selected: TrackerSelectItem[]) => void;
}
export const GlobalFieldsSelect: React.FC<Props> = ({trackerApi, onSubmit}) => {
const [fields, setFields] = useState<PluginFieldsSelectField[]>([]);
const [loading, setLoading] = useState(true);
const [open, setOpen] = useState(false);
const [selectedItems, setSelectedItems] = useState<TrackerSelectItem[]>([]);
useEffect(() => {
trackerApi.v3
.get['/fields']()
.then((result) => setFields(result.data))
.finally(() => setLoading(false));
}, [trackerApi]);
return (
<PluginFieldsSelect
open={open}
fields={fields}
loading={loading}
selectedItems={selectedItems}
onOpenChange={setOpen}
onItemSelect={(item) => setSelectedItems((prev) => [...prev, item])}
onItemDeselect={(item) =>
setSelectedItems((prev) => prev.filter((s) => s.id !== item.id))
}
onSubmit={() => onSubmit(selectedItems)}
expandSystemGroup
/>
);
};
Example 2 — Global suggest on user input
Uses initial loading for the initial list and switches to the suggest endpoint when text is entered.
import React, {useEffect, useState} from 'react';
import {PluginFieldsSelect} from '@weavix/tracker-components';
import type {PluginFieldsSelectField, TrackerSelectItem} from '@weavix/tracker-components';
export const GlobalFieldsSelectWithSuggest: React.FC<Props> = ({trackerApi, onSubmit}) => {
const [initialFields, setInitialFields] = useState<PluginFieldsSelectField[]>([]);
const [fields, setFields] = useState<PluginFieldsSelectField[]>([]);
const [loading, setLoading] = useState(true);
const [open, setOpen] = useState(false);
const [selectedItems, setSelectedItems] = useState<TrackerSelectItem[]>([]);
useEffect(() => {
trackerApi.v3
.get['/fields']()
.then((result) => {
setInitialFields(result.data);
setFields(result.data);
})
.finally(() => setLoading(false));
}, [trackerApi]);
const handleSearchChange = async (text: string) => {
// Suggest returns an empty response for empty input —
// revert to the initial list when search is cleared
if (!text) {
setFields(initialFields);
return;
}
const result = await trackerApi.v3.post['/fields/_suggest']({
bodyParams: {input: text, readOnly: true, localFields: false, extended: true},
});
setFields(result.data);
};
return (
<PluginFieldsSelect
open={open}
fields={fields}
loading={loading}
selectedItems={selectedItems}
onOpenChange={setOpen}
onSearchChange={handleSearchChange}
onItemSelect={(item) => setSelectedItems((prev) => [...prev, item])}
onItemDeselect={(item) =>
setSelectedItems((prev) => prev.filter((s) => s.id !== item.id))
}
onSubmit={() => onSubmit(selectedItems)}
expandGroupsOnSearch
/>
);
};
Example 3 — Global + local fields for specific queues
Extends Example 2 by adding queue-specific fields. If queueKeys is empty — only global suggest is used, since localFields: true with an empty queues array causes a request error.
import React, {useEffect, useState} from 'react';
import {PluginFieldsSelect} from '@weavix/tracker-components';
import type {PluginFieldsSelectField, TrackerSelectItem} from '@weavix/tracker-components';
interface Props {
trackerApi: TrackerApi;
/** You must pass at least one queue key when using local fields */
queueKeys: string[];
onSubmit: (selected: TrackerSelectItem[]) => void;
}
export const LocalFieldsSelectWithSuggest: React.FC<Props> = ({
trackerApi,
queueKeys,
onSubmit,
}) => {
const [initialFields, setInitialFields] = useState<PluginFieldsSelectField[]>([]);
const [fields, setFields] = useState<PluginFieldsSelectField[]>([]);
const [loading, setLoading] = useState(true);
const [open, setOpen] = useState(false);
const [selectedItems, setSelectedItems] = useState<TrackerSelectItem[]>([]);
useEffect(() => {
trackerApi.v3
.get['/fields']()
.then((result) => {
setInitialFields(result.data);
setFields(result.data);
})
.finally(() => setLoading(false));
}, [trackerApi]);
const handleSearchChange = async (text: string) => {
if (!text) {
setFields(initialFields);
return;
}
const hasQueues = queueKeys.length > 0;
const result = await trackerApi.v3.post['/fields/_suggest']({
bodyParams: {
input: text,
readOnly: true,
localFields: hasQueues,
extended: true,
...(hasQueues && {queues: queueKeys}),
},
});
setFields(result.data);
};
return (
<PluginFieldsSelect
open={open}
fields={fields}
loading={loading}
selectedItems={selectedItems}
onOpenChange={setOpen}
onSearchChange={handleSearchChange}
onItemSelect={(item) => setSelectedItems((prev) => [...prev, item])}
onItemDeselect={(item) =>
setSelectedItems((prev) => prev.filter((s) => s.id !== item.id))
}
onSubmit={() => onSubmit(selectedItems)}
expandGroupsOnSearch
/>
);
};
Main props
|
Prop |
Type |
Default |
Description |
|
|
|
— |
Flat list of fields to display |
|
|
|
— |
Whether the dropdown is open |
|
|
|
— |
Callback when the open state changes |
|
|
|
— |
Currently selected items |
|
|
|
|
Loading state — shows spinner |
|
|
|
— |
Callback when an item is selected |
|
|
|
— |
Callback when an item is deselected |
|
|
|
— |
Callback when the apply button is clicked |
|
|
|
— |
Callback when the reset button is clicked |
|
|
|
— |
Callback when search text changes |
|
|
|
|
Show search field |
|
|
|
|
Show apply button |
|
|
|
|
Show reset button |
|
|
|
— |
Apply button text |
|
|
|
— |
Reset button text |
|
|
|
|
Expand groups when typing in the search field |
|
|
|
|
Expand the system fields group (id= |
|
|
|
|
Single selection mode — closes the list after selection |
|
|
|
|
Hide checkboxes next to items |
|
|
|
|
Show meta line under the item name |
|
|
|
— |
IDs of items to display as unavailable |
|
|
|
— |
Additional content below the item list |
|
|
|
— |
Additional CSS class for the root element |