@jobber/components 9.13.2 → 9.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,10 @@
1
1
  import React from "react";
2
2
  import type { RefObject } from "react";
3
- import type { XOR } from "ts-xor";
4
- import type { Affix, FormFieldProps, Suffix } from "./FormFieldTypes";
5
- interface AffixLabelProps extends Affix {
3
+ import type { AffixProp, FormFieldProps } from "./FormFieldTypes";
4
+ type AffixLabelProps = AffixProp & {
6
5
  readonly labelRef: RefObject<HTMLDivElement | null>;
7
6
  readonly variation?: "prefix" | "suffix";
8
- }
7
+ };
9
8
  /**
10
9
  * @internal Reach out to UX Foundations if using this component since it is possible it might change
11
10
  */
@@ -13,8 +12,8 @@ export declare function AffixLabel({ label, variation, labelRef, }: AffixLabelPr
13
12
  /**
14
13
  * @internal Reach out to UX Foundations if using this component since it is possible it might change
15
14
  */
16
- interface AffixIconProps extends Pick<FormFieldProps, "size"> {
15
+ interface AffixIconProps extends Pick<FormFieldProps, "size" | "disabled"> {
17
16
  readonly variation?: "prefix" | "suffix";
18
17
  }
19
- export declare function AffixIcon({ icon, onClick, ariaLabel, variation, size, }: AffixIconProps & XOR<Affix, Suffix>): React.JSX.Element | null;
18
+ export declare function AffixIcon({ icon, onClick, ariaLabel, variation, size, disabled, }: AffixIconProps & AffixProp): React.JSX.Element | null;
20
19
  export {};
@@ -1,26 +1,14 @@
1
1
  import type { ChangeEvent, ReactNode, RefObject } from "react";
2
2
  import type React from "react";
3
- import type { XOR } from "ts-xor";
4
3
  import type { Clearable } from "@jobber/hooks";
5
- import type { IconNames } from "../Icon";
4
+ import type { AffixProp } from "../sharedHelpers/types";
5
+ export type { Affix, AffixProp, ClickableAffix, Suffix, } from "../sharedHelpers/types";
6
6
  export type FormFieldTypes = "text" | "password" | "number" | "time" | "textarea" | "select" | "tel" | "email";
7
7
  export type KeyBoardTypes = "text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal";
8
8
  export type AutocompleteTypes = "on" | "one-time-code" | "address-line1" | "address-line2";
9
9
  export interface FieldActionsRef {
10
10
  setValue(value: string | number): void;
11
11
  }
12
- export interface Affix {
13
- readonly label?: string;
14
- readonly icon?: IconNames;
15
- }
16
- interface BaseSuffix extends Affix {
17
- readonly icon: IconNames;
18
- onClick?(): void;
19
- }
20
- export interface Suffix extends BaseSuffix {
21
- onClick(): void;
22
- readonly ariaLabel: string;
23
- }
24
12
  export interface CommonFormFieldProps {
25
13
  /**
26
14
  * A unique identifier for the input.
@@ -141,13 +129,13 @@ export interface FormFieldProps extends CommonFormFieldProps {
141
129
  */
142
130
  readonly maxLength?: number;
143
131
  /**
144
- * Adds a prefix label and icon to the field
132
+ * Adds a prefix label and icon with an optional action to the field
145
133
  */
146
- readonly prefix?: Affix;
134
+ readonly prefix?: AffixProp;
147
135
  /**
148
136
  * Adds a suffix label and icon with an optional action to the field
149
137
  */
150
- readonly suffix?: XOR<Affix, Suffix>;
138
+ readonly suffix?: AffixProp;
151
139
  /**
152
140
  * Specifies the minimum numerical or date value that a user can type
153
141
  */
@@ -194,4 +182,3 @@ export interface FormFieldProps extends CommonFormFieldProps {
194
182
  */
195
183
  readonly pattern?: string;
196
184
  }
197
- export {};
@@ -26,24 +26,14 @@ function AffixLabel({ label, variation = "prefix", labelRef, }) {
26
26
  return null;
27
27
  return (React.createElement("div", { ref: labelRef, className: affixLabelClass }, label));
28
28
  }
29
- function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, }) {
29
+ function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, disabled, }) {
30
30
  const affixIconClass = classnames(formFieldStyles.affixIcon, {
31
31
  [formFieldStyles.suffix]: variation === "suffix",
32
32
  });
33
33
  const iconSize = size === "small" ? "small" : "base";
34
34
  if (!icon)
35
35
  return null;
36
- return (React.createElement("div", { className: affixIconClass }, onClick ? (React.createElement(Button.Button
37
- /**
38
- * We can cast the ariaLabel here as a `Suffix`
39
- * requires an ariaLabel if there is an action
40
- */
41
- , {
42
- /**
43
- * We can cast the ariaLabel here as a `Suffix`
44
- * requires an ariaLabel if there is an action
45
- */
46
- ariaLabel: ariaLabel, icon: icon, onClick: onClick, variation: "subtle", type: "tertiary", size: iconSize })) : (React.createElement(Icon.Icon, { name: icon, size: iconSize, color: "greyBlue" }))));
36
+ return (React.createElement("div", { className: affixIconClass }, onClick ? (React.createElement(Button.Button, { ariaLabel: ariaLabel, icon: icon, onClick: onClick, variation: "subtle", type: "tertiary", size: iconSize, disabled: disabled })) : (React.createElement(Icon.Icon, { name: icon, size: iconSize, color: "greyBlue" }))));
47
37
  }
48
38
 
49
39
  function FormFieldDescription({ id, description, visible = true, }) {
@@ -192,7 +182,7 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
192
182
  return (React.createElement("div", { className: containerClasses },
193
183
  React.createElement("div", { className: wrapperClasses, style: wrapperInlineStyle, "data-testid": "Form-Field-Wrapper", ref: wrapperRef },
194
184
  React.createElement(FormFieldInputHorizontalWrapper, null,
195
- React.createElement(AffixIcon, Object.assign({}, prefix, { size: size })),
185
+ React.createElement(AffixIcon, Object.assign({}, prefix, { size: size, disabled: disabled })),
196
186
  React.createElement(FormFieldInputWrapperStyles, null,
197
187
  (showMiniLabel || !value) && (React.createElement(FormFieldLabel, { htmlFor: identifier, style: (prefixRef === null || prefixRef === void 0 ? void 0 : prefixRef.current) || (suffixRef === null || suffixRef === void 0 ? void 0 : suffixRef.current)
198
188
  ? labelStyle
@@ -201,7 +191,7 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
201
191
  React.createElement(FormFieldWrapperMain, null, children),
202
192
  React.createElement(AffixLabel, Object.assign({}, suffix, { labelRef: suffixRef, variation: "suffix" }))),
203
193
  React.createElement(ClearAction, { onClick: onClear, visible: showClear }),
204
- React.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size }))),
194
+ React.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size, disabled: disabled }))),
205
195
  React.createElement(FormFieldWrapperToolbar, { toolbarVisibility: toolbarVisibility, isToolbarVisible: isToolbarVisible, toolbarAnimationEnd: toolbarAnimationEnd, toolbarAnimationStart: toolbarAnimationStart, toolbar: toolbar })),
206
196
  React.createElement(FormFieldDescription, { visible: !!description && !inline, id: descriptionIdentifier, description: description }),
207
197
  React.createElement(InputValidation.InputValidation, { message: error, visible: !!error && !inline })));
@@ -24,24 +24,14 @@ function AffixLabel({ label, variation = "prefix", labelRef, }) {
24
24
  return null;
25
25
  return (React__default.createElement("div", { ref: labelRef, className: affixLabelClass }, label));
26
26
  }
27
- function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, }) {
27
+ function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, disabled, }) {
28
28
  const affixIconClass = classnames(formFieldStyles.affixIcon, {
29
29
  [formFieldStyles.suffix]: variation === "suffix",
30
30
  });
31
31
  const iconSize = size === "small" ? "small" : "base";
32
32
  if (!icon)
33
33
  return null;
34
- return (React__default.createElement("div", { className: affixIconClass }, onClick ? (React__default.createElement(Button
35
- /**
36
- * We can cast the ariaLabel here as a `Suffix`
37
- * requires an ariaLabel if there is an action
38
- */
39
- , {
40
- /**
41
- * We can cast the ariaLabel here as a `Suffix`
42
- * requires an ariaLabel if there is an action
43
- */
44
- ariaLabel: ariaLabel, icon: icon, onClick: onClick, variation: "subtle", type: "tertiary", size: iconSize })) : (React__default.createElement(Icon, { name: icon, size: iconSize, color: "greyBlue" }))));
34
+ return (React__default.createElement("div", { className: affixIconClass }, onClick ? (React__default.createElement(Button, { ariaLabel: ariaLabel, icon: icon, onClick: onClick, variation: "subtle", type: "tertiary", size: iconSize, disabled: disabled })) : (React__default.createElement(Icon, { name: icon, size: iconSize, color: "greyBlue" }))));
45
35
  }
46
36
 
47
37
  function FormFieldDescription({ id, description, visible = true, }) {
@@ -190,7 +180,7 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
190
180
  return (React__default.createElement("div", { className: containerClasses },
191
181
  React__default.createElement("div", { className: wrapperClasses, style: wrapperInlineStyle, "data-testid": "Form-Field-Wrapper", ref: wrapperRef },
192
182
  React__default.createElement(FormFieldInputHorizontalWrapper, null,
193
- React__default.createElement(AffixIcon, Object.assign({}, prefix, { size: size })),
183
+ React__default.createElement(AffixIcon, Object.assign({}, prefix, { size: size, disabled: disabled })),
194
184
  React__default.createElement(FormFieldInputWrapperStyles, null,
195
185
  (showMiniLabel || !value) && (React__default.createElement(FormFieldLabel, { htmlFor: identifier, style: (prefixRef === null || prefixRef === void 0 ? void 0 : prefixRef.current) || (suffixRef === null || suffixRef === void 0 ? void 0 : suffixRef.current)
196
186
  ? labelStyle
@@ -199,7 +189,7 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
199
189
  React__default.createElement(FormFieldWrapperMain, null, children),
200
190
  React__default.createElement(AffixLabel, Object.assign({}, suffix, { labelRef: suffixRef, variation: "suffix" }))),
201
191
  React__default.createElement(ClearAction, { onClick: onClear, visible: showClear }),
202
- React__default.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size }))),
192
+ React__default.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size, disabled: disabled }))),
203
193
  React__default.createElement(FormFieldWrapperToolbar, { toolbarVisibility: toolbarVisibility, isToolbarVisible: isToolbarVisible, toolbarAnimationEnd: toolbarAnimationEnd, toolbarAnimationStart: toolbarAnimationStart, toolbar: toolbar })),
204
194
  React__default.createElement(FormFieldDescription, { visible: !!description && !inline, id: descriptionIdentifier, description: description }),
205
195
  React__default.createElement(InputValidation, { message: error, visible: !!error && !inline })));
@@ -714,10 +714,10 @@ This is not yet implemented fully. Avoid using.
714
714
  | `onOpen` | `() => void` | No | — | Callback invoked when the menu opens. |
715
715
  | `openOnFocus` | `boolean` | No | `true` | Whether the menu should open when the input gains focus. Note: Clicking on the input will always open the menu. openO... |
716
716
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
717
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field. |
717
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field. |
718
718
  | `readOnly` | `boolean` | No | — | Whether the input is read-only (HTML standard casing). |
719
719
  | `ref` | `Ref<HTMLInputElement | HTMLTextAreaElement>` | No | — | |
720
720
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
721
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field. |
721
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field. |
722
722
  | `UNSAFE_className` | `{ menu?: string; option?: string; section?: string; action?: string; input?: string; header?: string; footer?: string; selection?: string; }` | No | — | **Use at your own risk:** Custom class names for specific elements. This should only be used as a **last resort**. Us... |
723
723
  | `UNSAFE_styles` | `{ menu?: CSSProperties; option?: CSSProperties; section?: CSSProperties; action?: CSSProperties; input?: CSSProperties; header?: CSSProperties; footer?: CSSProperties; selection?: CSSProperties; }` | No | — | **Use at your own risk:** Custom style for specific elements. This should only be used as a **last resort**. Using th... |
@@ -389,7 +389,7 @@ Use `UNSAFE_style` to apply inline custom styles to the Banner.
389
389
  | `dismissible` | `boolean` | No | `true` | Set to false to hide the dismiss button |
390
390
  | `icon` | `IconNames` | No | — | Use to override the default status Icon |
391
391
  | `onDismiss` | `() => void` | No | — | Callback to be called when the Banner is dismissed. |
392
- | `primaryAction` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | Accepts props for Button. Default action uses a 'subtle' Button |
392
+ | `primaryAction` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | Accepts props for Button. Default action uses a 'subtle' Button |
393
393
 
394
394
  #### Banner.Action
395
395
 
@@ -441,8 +441,8 @@ Use `UNSAFE_style` to apply inline custom styles to the Banner.
441
441
 
442
442
  | Prop | Type | Required | Default | Description |
443
443
  |------|------|----------|---------|-------------|
444
- | `backgroundColor` | `"disabled" | "icon" | "event" | "invoice" | "job" | "quote" | "request" | "task" | "text" | "visit" | "warning" | "success" | "base-grey--100" | "base-grey--200" | "base-grey--300" | ... 275 more ... | "client--onSurface"` | No | — | Sets the background color of the icon. |
445
- | `color` | `"disabled" | "icon" | "task" | "text" | "warning" | "success" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
444
+ | `backgroundColor` | `"disabled" | "success" | "warning" | "icon" | "base-grey--100" | "base-grey--200" | "base-grey--300" | "base-grey--400" | "base-grey--500" | "base-grey--600" | "base-grey--700" | ... 279 more ... | "client--onSurface"` | No | — | Sets the background color of the icon. |
445
+ | `color` | `"disabled" | "success" | "warning" | "icon" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | "destructive" | ... 34 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
446
446
  | `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
447
447
  | `name` | `IconNames` | No | — | The icon to show. |
448
448
  | `size` | `"base" | "large" | "small"` | No | `base` | Changes the size to small or large. |
@@ -206,9 +206,9 @@ defaults to respecting theme/modes.
206
206
  | `alignItems` | `AlignItems` | No | — | This feature is well established and works across many devices and browser versions. It’s been available across brows... |
207
207
  | `alignSelf` | `AlignSelf` | No | — | This feature is well established and works across many devices and browser versions. It’s been available across brows... |
208
208
  | `as` | `"article" | "aside" | "div" | "main" | "section" | "span"` | No | `div` | |
209
- | `background` | `"disabled" | "icon" | "event" | "invoice" | "job" | "quote" | "request" | "task" | "text" | "visit" | "warning" | "success" | "base-grey--100" | "base-grey--200" | "base-grey--300" | ... 275 more ... | "client--onSurface"` | No | — | |
209
+ | `background` | `"disabled" | "success" | "warning" | "icon" | "base-grey--100" | "base-grey--200" | "base-grey--300" | "base-grey--400" | "base-grey--500" | "base-grey--600" | "base-grey--700" | ... 279 more ... | "client--onSurface"` | No | — | |
210
210
  | `border` | `"base" | "thick" | "thicker" | "thickest" | BoxBorderWidth` | No | — | |
211
- | `borderColor` | `"disabled" | "icon" | "event" | "invoice" | "job" | "quote" | "request" | "task" | "text" | "visit" | "warning" | "success" | "base-grey--100" | "base-grey--200" | "base-grey--300" | ... 275 more ... | "client--onSurface"` | No | — | |
211
+ | `borderColor` | `"disabled" | "success" | "warning" | "icon" | "base-grey--100" | "base-grey--200" | "base-grey--300" | "base-grey--400" | "base-grey--500" | "base-grey--600" | "base-grey--700" | ... 279 more ... | "client--onSurface"` | No | — | |
212
212
  | `direction` | `FlexDirection` | No | — | |
213
213
  | `gap` | `"base" | "extravagant" | "large" | "larger" | "largest" | "minuscule" | "slim" | "small" | "smaller" | "smallest"` | No | — | |
214
214
  | `height` | `BoxDimension` | No | `auto` | |
@@ -553,7 +553,7 @@ objects that will define the sorting options for the column.
553
553
  | Prop | Type | Required | Default | Description |
554
554
  |------|------|----------|---------|-------------|
555
555
  | `message` | `string` | Yes | — | The message that shows when the DataList is empty. |
556
- | `action` | `ReactElement<{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }, string | JSXElementConstructor<...>>` | No | — | The action that shows when the DataList is empty. This only accepts a Button component. Adding a non-Button componen... |
556
+ | `action` | `ReactElement<{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }, string | JSXElementConstructor<...>>` | No | — | The action that shows when the DataList is empty. This only accepts a Button component. Adding a non-Button componen... |
557
557
  | `customRender` | `(emptyState: Omit<DataListEmptyStateProps, "customRender">) => ReactNode` | No | — | Custom render function for the empty state. If provided, this function will be used to render the empty state instea... |
558
558
  | `type` | `"empty" | "filtered"` | No | — | Determine the type of empty state to show. By default, it will show the "empty" state when there is no data. If you ... |
559
559
 
@@ -930,10 +930,10 @@ verify the result rather than expecting an exact match.
930
930
  |------|------|----------|---------|-------------|
931
931
  | `align` | `DialogActionsAlign` | No | `right` | Layout for the right-hand action group. |
932
932
  | `className` | `string` | No | — | Class name applied to the part's root element. |
933
- | `primary` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Primary action (right). |
934
- | `secondary` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Secondary action (right, subtle). |
933
+ | `primary` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Primary action (right). |
934
+ | `secondary` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Secondary action (right, subtle). |
935
935
  | `style` | `CSSProperties` | No | — | Inline styles applied to the part's root element. |
936
- | `tertiary` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Tertiary/destructive action (left). |
936
+ | `tertiary` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 35 more ... | (({ ...; } | ... 35 more ... | ReactElement<...>) & ({ ...; } | ....` | No | — | Tertiary/destructive action (left). |
937
937
 
938
938
  #### Dialog.Body
939
939
 
@@ -281,6 +281,6 @@ window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
281
281
  |------|------|----------|---------|-------------|
282
282
  | `id` | `number | string` | Yes | — | A unique identifier for the option. |
283
283
  | `label` | `string` | Yes | — | The value to be visually displayed in the FilterPicker options list. |
284
- | `customRender` | `(option: Pick<FilterPickerOptionProps, "prefix" | "label" | "id"> & { isSelected: boolean; defaultContent: ReactElement<unknown, string | JSXElementConstructor<any>>; }) => ReactNode` | No | — | Advanced: A custom render prop to completely control how this option is rendered. The function receives the option's ... |
284
+ | `customRender` | `(option: Pick<FilterPickerOptionProps, "prefix" | "id" | "label"> & { isSelected: boolean; defaultContent: ReactElement<unknown, string | JSXElementConstructor<any>>; }) => ReactNode` | No | — | Advanced: A custom render prop to completely control how this option is rendered. The function receives the option's ... |
285
285
  | `onClick` | `(option: FilterPickerOptionProps) => void` | No | — | Callback function invoked when the option is clicked. |
286
286
  | `prefix` | `ReactNode` | No | — | An optional component to be displayed before the label. |
@@ -192,6 +192,7 @@ export function IconSizesExample() {
192
192
 
193
193
  | Icon | `Name` |
194
194
  | :--- | :----------------- |
195
+ | | `arrow` |
195
196
  | | `arrowDown` |
196
197
  | | `arrowLeft` |
197
198
  | | `arrowRight` |
@@ -244,22 +245,23 @@ export function IconSizesExample() {
244
245
 
245
246
  ### Forms
246
247
 
247
- | Icon | `Name` |
248
- | :--- | :------------- |
249
- | | `checkbox` |
250
- | | `checklist` |
251
- | | `edit` |
252
- | | `editDisabled` |
253
- | | `radioButton` |
254
- | | `star` |
255
- | | `starHalf` |
256
- | | `starFill` |
257
- | | `text` |
258
- | | `textBox` |
259
- | | `textField` |
260
- | | `toggle` |
261
- | | `dropdown` |
262
- | | `trash` |
248
+ | Icon | `Name` |
249
+ | :--- | :---------------- |
250
+ | | `checkbox` |
251
+ | | `checklist` |
252
+ | | `digestChecklist` |
253
+ | | `edit` |
254
+ | | `editDisabled` |
255
+ | | `radioButton` |
256
+ | | `star` |
257
+ | | `starHalf` |
258
+ | | `starFill` |
259
+ | | `text` |
260
+ | | `textBox` |
261
+ | | `textField` |
262
+ | | `toggle` |
263
+ | | `dropdown` |
264
+ | | `trash` |
263
265
 
264
266
  ### Status and support
265
267
 
@@ -346,6 +348,8 @@ export function IconSizesExample() {
346
348
  | | `contactlessPayment` |
347
349
  | | `cheque` |
348
350
  | | `cash` |
351
+ | | `coin` |
352
+ | | `handDollarSign` |
349
353
 
350
354
  ### Work
351
355
 
@@ -479,6 +483,7 @@ export function IconSizesExample() {
479
483
  | | `phoneEnd` |
480
484
  | | `phoneIncoming` |
481
485
  | | `phoneOutgoing` |
486
+ | | `pieChart` |
482
487
  | | `pinned` |
483
488
  | | `presentation` |
484
489
  | | `priceTag` |
@@ -620,7 +625,7 @@ necessary.
620
625
  | Prop | Type | Required | Default | Description |
621
626
  |------|------|----------|---------|-------------|
622
627
  | `name` | `IconNames` | Yes | — | The icon to show. |
623
- | `color` | `"disabled" | "icon" | "task" | "text" | "warning" | "success" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
628
+ | `color` | `"disabled" | "success" | "warning" | "icon" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | "destructive" | ... 34 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
624
629
  | `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
625
630
  | `size` | `"base" | "large" | "small"` | No | `base` | Changes the size to small or large. |
626
631
  | `testID` | `string` | No | — | Used to locate this view in end-to-end tests |
@@ -68,12 +68,12 @@ If you are not worried about email address validation, consider using
68
68
  | `onPointerUp` | `(event: PointerEvent<HTMLInputElement>) => void` | No | — | Pointer up event handler. |
69
69
  | `pattern` | `string` | No | — | Validation pattern (regex) for the input. |
70
70
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
71
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field. |
71
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field. |
72
72
  | `readOnly` | `boolean` | No | — | Whether the input is read-only (HTML standard casing). |
73
73
  | `ref` | `Ref<HTMLInputElement>` | No | — | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (... |
74
74
  | `required` | `boolean` | No | — | Whether the input is required before form submission. |
75
75
  | `role` | `string` | No | — | Role attribute for accessibility. |
76
76
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
77
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field. |
77
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field. |
78
78
  | `tabIndex` | `number` | No | — | Tab index for keyboard navigation. |
79
79
  | `value` | `string` | No | — | The current value of the input. |
@@ -80,11 +80,11 @@ edits the input.
80
80
  | `onPointerUp` | `(event: PointerEvent<HTMLInputElement>) => void` | No | — | Pointer up event handler. |
81
81
  | `pattern` | `string` | No | `(***) ***-****` | A pattern to specify the format to display the phone number in. For example if you want to display the format for [De... |
82
82
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
83
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field. |
83
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field. |
84
84
  | `readOnly` | `boolean` | No | — | Whether the input is read-only (HTML standard casing). |
85
85
  | `ref` | `Ref<HTMLInputElement>` | No | — | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (... |
86
86
  | `required` | `boolean` | No | — | Whether the input is required before form submission. |
87
87
  | `role` | `string` | No | — | Role attribute for accessibility. |
88
88
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
89
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field. |
89
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field. |
90
90
  | `tabIndex` | `number` | No | — | Tab index for keyboard navigation. |
@@ -86,6 +86,10 @@ and align the input with
86
86
  With clearer guidance around the purpose of inputs, the user is able to better
87
87
  focus on the task at hand.
88
88
 
89
+ Either affix can be given an `onClick` to make it an action, which renders the
90
+ affix icon as a button. An actioned affix requires both an `icon` and an
91
+ `ariaLabel` to name the button — affix labels are not actionable.
92
+
89
93
  ```tsx
90
94
  import React, { useState } from "react";
91
95
  import type { InputTextProps } from "@jobber/components/InputText";
@@ -128,7 +132,11 @@ export function InputTextPrefixSuffixExample(
128
132
  />
129
133
  <InputText
130
134
  placeholder="Search"
131
- prefix={{ icon: "search" }}
135
+ prefix={{
136
+ icon: "search",
137
+ ariaLabel: "submit search",
138
+ onClick: () => alert("This could submit a search"),
139
+ }}
132
140
  value={search}
133
141
  onChange={handleSearchChange}
134
142
  suffix={{
@@ -354,7 +362,7 @@ export function InputTextKeyboardExample(
354
362
  | `onPointerUp` | `(event: PointerEvent<HTMLInputElement | HTMLTextAreaElement>) => void` | No | — | Pointer up event handler. |
355
363
  | `pattern` | `string` | No | — | Validation pattern (regex) for the input. |
356
364
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
357
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field. |
365
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field. |
358
366
  | `readOnly` | `boolean` | No | — | Whether the input is read-only (HTML standard casing). |
359
367
  | `ref` | `Ref<HTMLInputElement | HTMLTextAreaElement>` | No | — | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (... |
360
368
  | `required` | `boolean` | No | — | Whether the input is required before form submission. |
@@ -362,7 +370,7 @@ export function InputTextKeyboardExample(
362
370
  | `rows` | `RowRange | number` | No | — | Specifies the visible height of a long answer form field. Can be in the form of a single number to set a static heigh... |
363
371
  | `showMiniLabel` | `boolean` | No | `true` | When false, the placeholder text only serves as a standard placeholder and disappears when the user types, instead of... |
364
372
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
365
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field. |
373
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field. |
366
374
  | `tabIndex` | `number` | No | — | Tab index for keyboard navigation. |
367
375
  | `toolbar` | `ReactNode` | No | — | Toolbar to render content below the input. |
368
376
  | `toolbarVisibility` | `"always" | "while-editing"` | No | — | Determines the visibility of the toolbar. |
@@ -82,12 +82,12 @@ as a mini label while editing or once a value is set.
82
82
  | `onPointerUp` | `(event: PointerEvent<HTMLInputElement>) => void` | No | — | Pointer up event handler. |
83
83
  | `pattern` | `string` | No | — | Validation pattern (regex) for the input. |
84
84
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
85
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field. |
85
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field. |
86
86
  | `readOnly` | `boolean` | No | — | Whether the input is read-only (HTML standard casing). |
87
87
  | `required` | `boolean` | No | — | Whether the input is required before form submission. |
88
88
  | `role` | `string` | No | — | Role attribute for accessibility. |
89
89
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
90
90
  | `step` | `number` | No | `60` | Granularity of the time input, in seconds. Matches the native HTML `step` attribute. Defaults to `60` so the input di... |
91
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field. |
91
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field. |
92
92
  | `tabIndex` | `number` | No | — | Tab index for keyboard navigation. |
93
93
  | `value` | `Date` | No | — | Set the component to the given value. |
@@ -230,11 +230,11 @@ dropdown content is stylable; the closed value alignment is not.
230
230
  | `onFocus` | `(event: FocusEvent<HTMLSelectElement, Element>) => void` | No | — | Focus event handler. |
231
231
  | `pattern` | `string` | No | — | Validation pattern (regex) for the input. |
232
232
  | `placeholder` | `string` | No | — | Text that appears inside the input when empty and floats above the value as a mini label once the user enters a value... |
233
- | `prefix` | `Affix` | No | — | Adds a prefix label and icon to the field |
233
+ | `prefix` | `AffixProp` | No | — | Adds a prefix label and icon with an optional action to the field |
234
234
  | `required` | `boolean` | No | — | Whether the input is required before form submission. |
235
235
  | `role` | `string` | No | — | Role attribute for accessibility. |
236
236
  | `size` | `"large" | "small"` | No | — | Adjusts the interface to either have small or large spacing. |
237
- | `suffix` | `{ onClick: () => void; readonly ariaLabel: string; readonly icon: IconNames; readonly label?: string; } | { onClick?: never; ariaLabel?: never; readonly label?: string; readonly icon?: IconNames; }` | No | — | Adds a suffix label and icon with an optional action to the field |
237
+ | `suffix` | `AffixProp` | No | — | Adds a suffix label and icon with an optional action to the field |
238
238
  | `tabIndex` | `number` | No | — | Tab index for keyboard navigation. |
239
239
  | `UNSAFE_experimentalStyles` | `boolean` | No | — | Opt-in to the customizable select UI (Chromium 123+). When true, the component will apply the custom select styles De... |
240
240
  | `value` | `number | string` | No | — | |
@@ -506,7 +506,7 @@ and should not be used for new implementations.
506
506
  | Prop | Type | Required | Default | Description |
507
507
  |------|------|----------|---------|-------------|
508
508
  | `name` | `IconNames` | Yes | — | The icon to show. |
509
- | `color` | `"disabled" | "icon" | "task" | "text" | "warning" | "success" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
509
+ | `color` | `"disabled" | "success" | "warning" | "icon" | "blue" | "green" | "yellow" | "red" | "grey" | "white" | "greyBlue" | "lightBlue" | "orange" | "navy" | "interactive" | "destructive" | ... 34 more ... | "brandHighlight"` | No | — | Determines the color of the icon. Some icons have a default system colour like quotes, jobs, and invoices. Others tha... |
510
510
  | `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
511
511
  | `size` | `"base" | "large" | "small"` | No | `base` | Changes the size to small or large. |
512
512
  | `testID` | `string` | No | — | Used to locate this view in end-to-end tests |
@@ -295,9 +295,9 @@ screen.getByRole("dialog", { name: /Billing Settings/i });
295
295
  | `dismissible` | `boolean` | No | `true` | |
296
296
  | `onRequestClose` | `() => void` | No | — | |
297
297
  | `open` | `boolean` | No | `false` | |
298
- | `primaryAction` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
299
- | `secondaryAction` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
298
+ | `primaryAction` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
299
+ | `secondaryAction` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
300
300
  | `size` | `"fullScreen" | "large" | "small"` | No | — | |
301
- | `tertiaryAction` | `{ onClick?: never; external?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
301
+ | `tertiaryAction` | `{ external?: never; onClick?: never; readonly name?: string; submit: never; readonly type?: ButtonType; readonly value?: string; readonly disabled?: boolean; readonly loading?: boolean; ... 17 more ...; readonly children?: never; } | ... 34 more ... | { ...; }` | No | — | |
302
302
  | `title` | `string` | No | `false` | |
303
303
  | `version` | `1` | No | — | |
@@ -1,6 +1,5 @@
1
1
  import type { AriaAttributes, ReactNode } from "react";
2
2
  import type React from "react";
3
- import type { XOR } from "ts-xor";
4
3
  import type { Clearable } from "@jobber/hooks";
5
4
  import type { IconNames } from "../Icon";
6
5
  export interface CommonAtlantisProps {
@@ -182,15 +181,20 @@ export interface HTMLInputBaseProps extends AriaInputProps {
182
181
  export interface Affix {
183
182
  readonly label?: string;
184
183
  readonly icon?: IconNames;
184
+ readonly ariaLabel?: never;
185
+ readonly onClick?: never;
185
186
  }
186
- interface BaseSuffix extends Affix {
187
+ export interface ClickableAffix {
188
+ readonly label?: string;
187
189
  readonly icon: IconNames;
188
- onClick?(): void;
189
- }
190
- export interface Suffix extends BaseSuffix {
191
- onClick(): void;
192
190
  readonly ariaLabel: string;
191
+ onClick(): void;
193
192
  }
193
+ export type AffixProp = Affix | ClickableAffix;
194
+ /**
195
+ * @deprecated Use {@link ClickableAffix}.
196
+ */
197
+ export type Suffix = ClickableAffix;
194
198
  /**
195
199
  * Common props shared across all rebuilt input components.
196
200
  * These are Atlantis-specific features not part of standard HTML inputs.
@@ -232,13 +236,13 @@ export interface RebuiltInputCommonProps {
232
236
  */
233
237
  readonly align?: "center" | "right";
234
238
  /**
235
- * Adds a prefix label and icon to the field.
239
+ * Adds a prefix label and icon with an optional action to the field.
236
240
  */
237
- readonly prefix?: Affix;
241
+ readonly prefix?: AffixProp;
238
242
  /**
239
243
  * Adds a suffix label and icon with an optional action to the field.
240
244
  */
241
- readonly suffix?: XOR<Affix, Suffix>;
245
+ readonly suffix?: AffixProp;
242
246
  /**
243
247
  * Further description of the input, can be used for a hint.
244
248
  */
@@ -249,4 +253,3 @@ export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;
249
253
  export type CommonAllowedElements = "section" | "p" | "article" | "ul" | "li" | "div" | "span" | "dl" | "dd" | "dt";
250
254
  export type Spaces = "none" | "minuscule" | "slim" | "smallest" | "smaller" | "small" | "base" | "large" | "larger" | "largest" | "extravagant";
251
255
  export type GapSpacing = Spaces | (string & NonNullable<unknown>);
252
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "9.13.2",
3
+ "version": "9.14.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -495,7 +495,7 @@
495
495
  "devDependencies": {
496
496
  "@apollo/client": "^3.7.10",
497
497
  "@csstools/postcss-global-data": "^1.0.3",
498
- "@jobber/design": "0.112.0",
498
+ "@jobber/design": "0.113.0",
499
499
  "@jobber/hooks": "2.21.1",
500
500
  "@rollup/plugin-alias": "^5.1.0",
501
501
  "@rollup/plugin-commonjs": "^25.0.7",
@@ -547,5 +547,5 @@
547
547
  "> 1%",
548
548
  "IE 10"
549
549
  ],
550
- "gitHead": "e730613f3ba3851d31e78cbae08a8b832a1605d5"
550
+ "gitHead": "a4a24e9df170032a2d37c2b72e855d95281fafcd"
551
551
  }