# Indeterminate

**Category:** Base Components/Collections/Picker

## Design

### Examples

### Items indeterminate status

```tsx
import { Avatar, EmptyState, Page } from '@wix/design-system';
import React from 'react';
import { queryContacts } from '@wix/ambassador-contacts-v4-contact/http';
import {
  Filter,
  OffsetQuery,
  PickerContent,
  PickerContentComponentProps,
  PickerModal,
  PickerModalOpenButton,
  PickerSelection,
  stringsArrayFilter,
  usePickerContent,
} from '@wix/patterns';
import { usePickerModal } from '@wix/patterns/essentials';
import {
  useEnvironment,
  useErrorMonitor,
  useHttpClient,
} from '@wix/fe-essentials/react';
import { Contact } from '@wix/ambassador-contacts-v4-contact/types';

type ContactsFilters = {
  level: Filter<string[]>;
};

function PickerModalIndeterminate() {
  const environment = useEnvironment();
  const httpClient = useHttpClient();
  const errorMonitor = useErrorMonitor();

  const selection = React.useRef<PickerSelection<Contact>>({});

  // Usually we will extract this component to a separate file and use dynamic import when passing it as `pickerContentComponent`
  const pickerContentComponent = async () => ({
    default: function ContactsPicker(
      props: PickerContentComponentProps<Contact, ContactsFilters>,
    ) {
      const state = usePickerContent({
        fetchErrorMessage: ({ err }) => String(err),
        modalState: props.modalState,
        filters: {
          level: stringsArrayFilter(props.modalState.filters.level),
        },
        initialSelect: selection.current,
      });

      return (
        <PickerContent
          state={state}
          renderItem={(contact) => ({
            subtitle: contact.level,
            image: <Avatar size="size60" shape="square" name={contact.name} />,
          })}
          renderEmptyState={() => (
            <EmptyState title="You don’t have any contacts that support this action." />
          )}
          {...props}
        />
      );
    },
  });

  const state = usePickerModal<Contact, ContactsFilters>({
    queryName: 'PickerModalIndeterminate',
    fetchInitialProps: () => {
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit: 25, offset: 0 }, filter: {} },
          }),
        )
        .then(({ data: { contacts = [] } }) => {
          selection.current = {
            partiallySelectedIds: contacts
              .slice(3, 6)
              .map((c) => c.id as string),
          };
        });
    },
    fetchData: (query: OffsetQuery<ContactsFilters>) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit, offset }, filter: filters },
            search,
          }),
        )
        .then(({ data: { contacts, pagingMetadata } }) => ({
          items: contacts as Contact[],
          total: pagingMetadata?.total,
        }));
    },
    limit: 100,
    pickerContentComponent,
    onSelect: (_contacts, { values, defaultStatus }) => {
      selection.current = {
        values,
        defaultStatus,
      };
    },
  });

  return (
    <Page>
      <Page.Header
        title="Picker Modal Example"
        actionsBar={
          <>
            <PickerModalOpenButton state={state}>
              Select Contacts
            </PickerModalOpenButton>

            <PickerModal
              title="Select Contacts"
              state={state}
              multiple
              renderError={({ err }) => <EmptyState title={String(err)} />}
            />
          </>
        }
      />
    </Page>
  );
}
```

---

### All indeterminate

```tsx
import { Avatar, EmptyState, Page } from '@wix/design-system';
import React from 'react';
import { queryContacts } from '@wix/ambassador-contacts-v4-contact/http';
import {
  Filter,
  OffsetQuery,
  PickerContent,
  PickerContentComponentProps,
  PickerModal,
  PickerModalOpenButton,
  PickerSelection,
  stringsArrayFilter,
  usePickerContent,
} from '@wix/patterns';
import { usePickerModal } from '@wix/patterns/essentials';
import {
  useEnvironment,
  useErrorMonitor,
  useHttpClient,
} from '@wix/fe-essentials/react';
import { Contact } from '@wix/ambassador-contacts-v4-contact/types';

type ContactsFilters = {
  level: Filter<string[]>;
};

function PickerModalAllIndeterminate() {
  const environment = useEnvironment();
  const httpClient = useHttpClient();
  const errorMonitor = useErrorMonitor();

  const selection = React.useRef<PickerSelection<Contact>>({
    defaultStatus: 'indeterminate',
  });

  // Usually we will extract this component to a separate file and use dynamic import when passing it as `pickerContentComponent`
  const pickerContentComponent = async () => ({
    default: function ContactsPicker(
      props: PickerContentComponentProps<Contact, ContactsFilters>,
    ) {
      const state = usePickerContent({
        fetchErrorMessage: ({ err }) => String(err),
        modalState: props.modalState,
        filters: {
          level: stringsArrayFilter(props.modalState.filters.level),
        },
        initialSelect: selection.current,
      });

      return (
        <PickerContent
          state={state}
          renderItem={(contact) => ({
            subtitle: contact.level,
            image: <Avatar size="size60" shape="square" name={contact.name} />,
          })}
          renderEmptyState={() => (
            <EmptyState title="You don’t have any contacts that support this action." />
          )}
          {...props}
        />
      );
    },
  });

  const state = usePickerModal<Contact, ContactsFilters>({
    queryName: 'PickerModalAllIndeterminate',
    fetchInitialProps: () => {
      return httpClient.request(
        queryContacts({
          query: { paging: { limit: 25, offset: 0 }, filter: {} },
        }),
      );
    },
    fetchData: (query: OffsetQuery<ContactsFilters>) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit, offset }, filter: filters },
            search,
          }),
        )
        .then(({ data: { contacts, pagingMetadata } }) => ({
          items: contacts as Contact[],
          total: pagingMetadata?.total,
        }));
    },
    limit: 100,
    pickerContentComponent,
    onSelect: (_contacts, { values, defaultStatus }) => {
      selection.current = {
        values: values.map(({ value, status }) => ({
          value,
          status: status.isIndeterminate
            ? 'indeterminate'
            : status.isChecked
            ? 'checked'
            : 'unchecked', // reset non-indeterminate to regular checked->unchecked mode
        })),
        defaultStatus,
      };
    },
  });

  return (
    <Page>
      <Page.Header
        title="Picker Modal Example"
        actionsBar={
          <>
            <PickerModalOpenButton state={state}>
              Select Contacts
            </PickerModalOpenButton>

            <PickerModal
              title="Select Contacts"
              state={state}
              multiple
              renderError={({ err }) => <EmptyState title={String(err)} />}
            />
          </>
        }
      />
    </Page>
  );
}
```

