# Sample Property Definitions

When building custom components, you can make use of the Component Manager `props` to make your custom component configurable in the UI Designer. Below you can find some sample property definition that you can adopt in your custom component.

### Common Properties

{% code overflow="wrap" %}

```typescript
export interface BaseProp {
  category?: string;
  helpText?: ((item: RequiredItem<never>) => string) | string;
  hidden?: boolean;
  label: string;
  preventMultiEdit?: boolean;
  required?:
    | ((item: RequiredItem<never>, context: PropertyContext) => boolean)
    | boolean;
  type: string;
}
```

{% endcode %}

### Text

{% code overflow="wrap" %}

```typescript
{
  label: "Gap",
  type: "string",
  placeholder: "e.g. 8px",
  helpText: "The flex gap to be added between the child components. e.g. 8px", // markdown can be used here
  category: "Flex",
  required: true
}
```

{% endcode %}

> Dynamic help text sample

{% code overflow="wrap" %}

```typescript
        helpText: (item: RequiredItem<'ActionButton'>) => {
          const key =
            item.props.hotKey ||
            (item.props.text.type === 'text' && item.props.text.value?.length
              ? item.props.text.value.charAt(0)
              : '<Hot Key>');

          return `A shortcut key to be mapped for this button click event. User can use Ctrl+Shift+${key} or Cmd+Shift+${key} as a keyboard shortcut instead of a mouse click on this button.`;
        },
```

{% endcode %}

### Number (slider)

```typescript
{
  label: "FlexGrow",
  type: "number",
  min: 0,
  max: 12,
  step: 1,
  category: "Flex",
  required: true
}
```

### Boolean

```typescript
{
  label: "Full Width",
  type: "boolean",
  helpText: "If checked, the button will take up the full width of its container."
}
```

### Boolean Expression

```typescript
{
  label: 'Updatable',
  type: 'booleanExpression',
  category: 'Data',
}
```

### Expression

{% code overflow="wrap" %}

```typescript
{
    label: 'BG Image',
    type: 'expression',
    returnType: async (item, context) => 'string', // Return type must return one of the following 'string' | 'boolean' | 'number' | 'date' | 'yn' | 'tf' | 'array' | 'object' | 'any'
    required: true,
}
```

{% endcode %}

### Color Expression

```typescript
{
  label: "Header BG Color",
  type: "ColorExpression",
  category: "Look & Feel",
  helpText: `Use one of the following values for a gray background with darkmode support.

divider
background.default
action.selected
primary.main
primary.dark
primary.light

Similar to how primary palette is used above, you can also use one of the following palette secondary, success, warning, error.
`
}
```

### Select

> Use toOptions function to auto create display labels based on the value
>
> import { toOptions } from 'cloudio';

{% code overflow="wrap" %}

```typescript
{
  label: 'Align Content',
  type: 'select',
  options: toOptions([
    'auto',
    'baseline',
    'center',
    'end',
    'flex-end',
    'flex-start',
    'inherit',
    'initial',
    'normal',
    'revert',
    'self-end',
    'self-start',
    'start',
    'stretch',
    'unset',
  ]),
  category: 'Flex',
  required: true,
}
```

{% endcode %}

> Manually specify both value & display labels

```typescript
{
  label: "Component",
  type: "select",
  options: { "span": "Span", "div": "Div", "img": "Image" }
}
```

### View Attribute Chooser

{% code overflow="wrap" %}

```typescript
{
  label: 'View Attribute',
  type: 'ViewAttributeChooser',
  required: true,
  category: 'Data',
  aliasType: 'STORE',
  getAttributeDataTypes: () => ['String'], // FieldType[] | 'ALL' where FieldType is "Date" | "DateTime" | "Attachment" | "Boolean" | "Decimal" | "Double" | "Email" | "EncryptedString" | "Integer" | "JSON" | "Percent" | "Phone" | "Reference" | "String" | "Textarea" | "URL" | "UserID" | "YN" | "TF"
  preventMultiEdit: true,
}
```

{% endcode %}

### Margin

{% code overflow="wrap" %}

```typescript
{
  label: "Margin",
  type: "margin",
  category: "Spacing"
}
```

{% endcode %}

### Controller Function

{% code overflow="wrap" %}

```typescript
{
  label: 'On Change',
  type: 'controllerFunction',
  category: 'Controllers',
}
```

{% endcode %}

### DataSource Alias Chooser

{% code overflow="wrap" %}

```typescript
{
    label: 'Data Store Alias',
    type: 'DataSourceAliasChooser',
    category: 'Select Options',
    allowedTypes: ['CloudDataStore', 'ReadOnlyDataStore'], // "CloudDataStore" | "DataStore" | "LocalDataStore" | "ReadOnlyDataStore" | "TransientDataStore"
    helpText:
      'Only ReadOnlyDataStore allowed. Use Query Select action to query it externally.',
    required: (item: RequiredItem<'Select'>) =>
      isEmpty(item.props.optionValues),
}
```

{% endcode %}

### Attribute Chooser

{% code overflow="wrap" %}

```typescript
{
  label: 'Value Attribute',
  type: 'ComboAttributeChooser',
  aliasType: 'LOV',
  category: 'Select Options',
  getAttributeDataTypes: () => 'ALL',
  required: (item: RequiredItem<'Select'>) =>
    !!item.props.comboDatasourceAlias,
}
```

{% endcode %}

### Options

{% code overflow="wrap" %}

```typescript
{
  type: 'options',
  label: 'Option Values',
  category: 'Select Options',
  helpText:
    'If the options are fixed, then you can specify here instead of providing a Data Store Alias below. e.g. B:Blue, G:Green, Yellow, Red',
}
```

{% endcode %}
