@jobber/components 6.21.0 → 6.22.0

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.
@@ -10,7 +10,6 @@ export interface ButtonFoundationProps {
10
10
  * Used for screen readers. Will override label on screen
11
11
  * reader if present.
12
12
  */
13
- readonly ariaLabel?: string;
14
13
  readonly ariaControls?: string;
15
14
  readonly ariaHaspopup?: boolean;
16
15
  readonly ariaExpanded?: boolean;
@@ -20,6 +19,7 @@ export interface ButtonFoundationProps {
20
19
  readonly id?: string;
21
20
  readonly loading?: boolean;
22
21
  readonly size?: ButtonSize;
22
+ readonly ariaLabel?: string;
23
23
  onClick?(event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>): void;
24
24
  onMouseDown?(event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>): void;
25
25
  }
@@ -35,14 +35,6 @@ interface ButtonIconProps extends ButtonNonComposableProps {
35
35
  interface ButtonLabelProps extends ButtonNonComposableProps {
36
36
  readonly label: string;
37
37
  }
38
- type BaseButtonProps = XOR<BaseActionProps, XOR<DestructiveActionProps, SubmitActionProps>> & XOR<XOR<SubmitButtonProps, BasicButtonProps>, XOR<ButtonLinkProps, ButtonAnchorProps>>;
39
- interface ButtonIconProps extends ButtonFoundationProps {
40
- readonly icon: IconNames;
41
- readonly ariaLabel: string;
42
- }
43
- interface ButtonLabelProps extends ButtonFoundationProps {
44
- readonly label: string;
45
- }
46
38
  interface ButtonAnchorProps extends ButtonFoundationProps {
47
39
  /**
48
40
  * Used to create an 'href' on an anchor tag.
@@ -82,6 +74,7 @@ interface BasicButtonProps extends ButtonFoundationProps {
82
74
  */
83
75
  readonly role?: string;
84
76
  }
77
+ type BaseButtonProps = XOR<BaseActionProps, XOR<DestructiveActionProps, SubmitActionProps>> & XOR<XOR<SubmitButtonProps, BasicButtonProps>, XOR<ButtonLinkProps, ButtonAnchorProps>>;
85
78
  export type ButtonWithChildrenProps = BaseButtonProps & {
86
79
  readonly children: React.ReactNode;
87
80
  };
@@ -12,12 +12,12 @@ require('../InputFile-cjs.js');
12
12
  require('../index-cjs.js');
13
13
  require('../_commonjsHelpers-cjs.js');
14
14
  require('axios');
15
- require('../InputValidation-cjs.js');
16
- require('framer-motion');
17
15
  require('../Text-cjs.js');
18
16
  require('../Typography-cjs.js');
19
17
  require('../Button-cjs.js');
20
18
  require('react-router-dom');
19
+ require('../InputValidation-cjs.js');
20
+ require('framer-motion');
21
21
  require('../Content-cjs.js');
22
22
  require('../ProgressBar-cjs.js');
23
23
 
@@ -10,11 +10,11 @@ import '../InputFile-es.js';
10
10
  import '../index-es.js';
11
11
  import '../_commonjsHelpers-es.js';
12
12
  import 'axios';
13
- import '../InputValidation-es.js';
14
- import 'framer-motion';
15
13
  import '../Text-es.js';
16
14
  import '../Typography-es.js';
17
15
  import '../Button-es.js';
18
16
  import 'react-router-dom';
17
+ import '../InputValidation-es.js';
18
+ import 'framer-motion';
19
19
  import '../Content-es.js';
20
20
  import '../ProgressBar-es.js';
@@ -1,5 +1,9 @@
1
- import { SyntheticEvent } from "react";
1
+ import React, { SyntheticEvent } from "react";
2
2
  import { FileError } from "react-dropzone";
3
+ import { InputFileHintText } from "./InputFileHintText";
4
+ import { InputFileDescription } from "./InputFileDescription";
5
+ import { InputFileButton } from "./InputFileButton";
6
+ import { InputFileDropzoneWrapper } from "./InputFileDropzoneWrapper";
3
7
  export interface FileUpload {
4
8
  /**
5
9
  * File Identifier
@@ -100,6 +104,10 @@ interface InputFileProps {
100
104
  * @default false
101
105
  */
102
106
  readonly allowMultiple?: boolean;
107
+ /**
108
+ * Override the default hint text with a custom value.
109
+ */
110
+ readonly hintText?: string;
103
111
  /**
104
112
  * Further description of the input.
105
113
  */
@@ -120,6 +128,10 @@ interface InputFileProps {
120
128
  */
121
129
  readonly numberOfCurrentFiles: number;
122
130
  };
131
+ /**
132
+ * Children will be rendered instead of the default content
133
+ */
134
+ readonly children?: React.ReactNode;
123
135
  /**
124
136
  * A callback that receives a file object and returns a `UploadParams` needed
125
137
  * to upload the file.
@@ -149,7 +161,13 @@ interface InputFileProps {
149
161
  */
150
162
  readonly validator?: <T extends File>(file: T) => FileError | FileError[] | null;
151
163
  }
152
- export declare function InputFile({ variation, size, buttonLabel: providedButtonLabel, allowMultiple, allowedTypes, description, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, }: InputFileProps): JSX.Element;
164
+ export declare function InputFile({ variation, size, buttonLabel: providedButtonLabel, allowMultiple, allowedTypes, description, hintText, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, children, }: InputFileProps): JSX.Element;
165
+ export declare namespace InputFile {
166
+ var Button: typeof InputFileButton;
167
+ var Description: typeof InputFileDescription;
168
+ var DropzoneWrapper: typeof InputFileDropzoneWrapper;
169
+ var HintText: typeof InputFileHintText;
170
+ }
153
171
  /**
154
172
  * Upsert a given `FileUpload` into an array of `FileUpload`s.
155
173
  * `key` is used to uniquely identify files.
@@ -0,0 +1,5 @@
1
+ import { ButtonProps } from "../Button";
2
+ interface InputFileButtonProps extends Omit<ButtonProps, "submit" | "name" | "value" | "to" | "url" | "children"> {
3
+ }
4
+ export declare function InputFileButton({ label, size, fullWidth, ...buttonProps }: InputFileButtonProps): JSX.Element;
5
+ export {};
@@ -0,0 +1,12 @@
1
+ import { ButtonSize } from "../Button";
2
+ export interface InputFileContentContextValue {
3
+ readonly fileType: string;
4
+ readonly allowMultiple: boolean;
5
+ readonly description: string | undefined;
6
+ readonly hintText: string;
7
+ readonly buttonLabel: string;
8
+ readonly size: ButtonSize;
9
+ }
10
+ declare const InputFileContentContext: import("react").Context<InputFileContentContextValue>;
11
+ declare function useInputFileContentContext(): InputFileContentContextValue;
12
+ export { InputFileContentContext, useInputFileContentContext };
@@ -0,0 +1,3 @@
1
+ import { PropsWithChildren } from "react";
2
+ import { TextProps } from "../Text";
3
+ export declare function InputFileDescription({ size, variation, children, ...textProps }: PropsWithChildren<TextProps>): JSX.Element | null;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare function InputFileDropzoneWrapper({ children, }: {
3
+ readonly children: React.ReactNode;
4
+ }): JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { PropsWithChildren } from "react";
2
+ import { TextProps } from "../Text";
3
+ export declare function InputFileHintText({ size, children, ...textProps }: PropsWithChildren<TextProps>): JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { InputFileValidationError } from "./types";
2
+ export declare function InputFileValidationErrors({ validationErrors, }: {
3
+ readonly validationErrors: InputFileValidationError[];
4
+ }): JSX.Element | null;
@@ -7,17 +7,19 @@ require('classnames');
7
7
  require('../index-cjs.js');
8
8
  require('../_commonjsHelpers-cjs.js');
9
9
  require('axios');
10
- require('../InputValidation-cjs.js');
11
- require('framer-motion');
12
10
  require('../Text-cjs.js');
13
11
  require('../Typography-cjs.js');
14
- require('../Icon-cjs.js');
15
- require('@jobber/design');
16
12
  require('../Button-cjs.js');
17
13
  require('react-router-dom');
14
+ require('../Icon-cjs.js');
15
+ require('@jobber/design');
16
+ require('../InputValidation-cjs.js');
17
+ require('framer-motion');
18
18
  require('../Content-cjs.js');
19
19
 
20
20
 
21
21
 
22
22
  exports.InputFile = InputFile.InputFile;
23
+ exports.InputFileContentContext = InputFile.InputFileContentContext;
23
24
  exports.updateFiles = InputFile.updateFiles;
25
+ exports.useInputFileContentContext = InputFile.useInputFileContentContext;
@@ -1 +1,2 @@
1
1
  export { InputFile, updateFiles, FileUpload, UploadParams } from "./InputFile";
2
+ export { InputFileContentContext, useInputFileContentContext, } from "./InputFileContentContext";
@@ -1,16 +1,16 @@
1
- export { I as InputFile, u as updateFiles } from '../InputFile-es.js';
1
+ export { I as InputFile, a as InputFileContentContext, u as updateFiles, b as useInputFileContentContext } from '../InputFile-es.js';
2
2
  import '../tslib.es6-es.js';
3
3
  import 'react';
4
4
  import 'classnames';
5
5
  import '../index-es.js';
6
6
  import '../_commonjsHelpers-es.js';
7
7
  import 'axios';
8
- import '../InputValidation-es.js';
9
- import 'framer-motion';
10
8
  import '../Text-es.js';
11
9
  import '../Typography-es.js';
12
- import '../Icon-es.js';
13
- import '@jobber/design';
14
10
  import '../Button-es.js';
15
11
  import 'react-router-dom';
12
+ import '../Icon-es.js';
13
+ import '@jobber/design';
14
+ import '../InputValidation-es.js';
15
+ import 'framer-motion';
16
16
  import '../Content-es.js';
@@ -0,0 +1,4 @@
1
+ export interface InputFileValidationError {
2
+ readonly code: string;
3
+ readonly message: string;
4
+ }
@@ -5,10 +5,10 @@ var React = require('react');
5
5
  var classnames = require('classnames');
6
6
  var index = require('./index-cjs.js');
7
7
  var axios = require('axios');
8
- var InputValidation = require('./InputValidation-cjs.js');
8
+ var Text = require('./Text-cjs.js');
9
9
  var Button = require('./Button-cjs.js');
10
+ var InputValidation = require('./InputValidation-cjs.js');
10
11
  var Content = require('./Content-cjs.js');
11
- var Typography = require('./Typography-cjs.js');
12
12
 
13
13
  var COMMON_MIME_TYPES = new Map([
14
14
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
@@ -1473,8 +1473,67 @@ function formatMimeTypes(types) {
1473
1473
  }
1474
1474
  }
1475
1475
 
1476
+ const InputFileContentContext = React.createContext({
1477
+ fileType: "File",
1478
+ allowMultiple: false,
1479
+ description: undefined,
1480
+ hintText: getDefaultHintText("File", false),
1481
+ buttonLabel: getDefaultLabel(false, "File"),
1482
+ size: "base",
1483
+ });
1484
+ function useInputFileContentContext() {
1485
+ const context = React.useContext(InputFileContentContext);
1486
+ const computedHintText = context.hintText ||
1487
+ getDefaultHintText(context.fileType, context.allowMultiple);
1488
+ const computedButtonLabel = context.buttonLabel ||
1489
+ getDefaultLabel(context.allowMultiple, context.fileType);
1490
+ return Object.assign(Object.assign({}, context), { hintText: computedHintText, buttonLabel: computedButtonLabel });
1491
+ }
1492
+ function getDefaultLabel(multiple, fileType) {
1493
+ return multiple ? `Upload ${fileType}s` : `Upload ${fileType}`;
1494
+ }
1495
+ function getDefaultHintText(fileType, multiple) {
1496
+ const fileTypeDeterminer = fileType === "Image" ? "an" : "a";
1497
+ const hintText = multiple
1498
+ ? `Select or drag ${fileType.toLowerCase()}s here to upload`
1499
+ : `Select or drag ${fileTypeDeterminer} ${fileType.toLowerCase()} here to upload`;
1500
+ return hintText;
1501
+ }
1502
+
1503
+ function InputFileHintText(_a) {
1504
+ var { size = "small", children } = _a, textProps = tslib_es6.__rest(_a, ["size", "children"]);
1505
+ const { hintText } = useInputFileContentContext();
1506
+ return (React.createElement(Text.Text, Object.assign({}, textProps, { size: size }), children || hintText));
1507
+ }
1508
+
1509
+ function InputFileDescription(_a) {
1510
+ var { size = "small", variation = "subdued", children } = _a, textProps = tslib_es6.__rest(_a, ["size", "variation", "children"]);
1511
+ const { description } = useInputFileContentContext();
1512
+ if (!children && !description) {
1513
+ return null;
1514
+ }
1515
+ return (React.createElement(Text.Text, Object.assign({ size: size, variation: variation }, textProps), children || description));
1516
+ }
1517
+
1518
+ function InputFileButton(_a) {
1519
+ var { label, size, fullWidth = false } = _a, buttonProps = tslib_es6.__rest(_a, ["label", "size", "fullWidth"]);
1520
+ const { buttonLabel: contextLabel, size: contextSize } = useInputFileContentContext();
1521
+ return (React.createElement(Button.Button, Object.assign({}, buttonProps, { label: label || contextLabel, size: size !== null && size !== void 0 ? size : contextSize, type: "secondary", fullWidth: fullWidth })));
1522
+ }
1523
+
1524
+ function InputFileDropzoneWrapper({ children, }) {
1525
+ return React.createElement("div", { className: styles.dropzoneContent }, children);
1526
+ }
1527
+
1528
+ function InputFileValidationErrors({ validationErrors, }) {
1529
+ if (validationErrors.length === 0) {
1530
+ return null;
1531
+ }
1532
+ return (React.createElement("div", { className: styles.validationErrors }, validationErrors.map(error => (React.createElement(InputValidation.InputValidation, { message: error.message, key: error.code })))));
1533
+ }
1534
+
1476
1535
  /* eslint-disable max-statements */
1477
- function InputFile({ variation = "dropzone", size = "base", buttonLabel: providedButtonLabel, allowMultiple = false, allowedTypes = "all", description, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, }) {
1536
+ function InputFile({ variation = "dropzone", size = "base", buttonLabel: providedButtonLabel, allowMultiple = false, allowedTypes = "all", description, hintText, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, children, }) {
1478
1537
  const maxFiles = (maxFilesValidation === null || maxFilesValidation === void 0 ? void 0 : maxFilesValidation.maxFiles) || 0;
1479
1538
  const numberOfCurrentFiles = (maxFilesValidation === null || maxFilesValidation === void 0 ? void 0 : maxFilesValidation.numberOfCurrentFiles) || 0;
1480
1539
  const handleValidation = React.useCallback((file) => {
@@ -1545,23 +1604,35 @@ function InputFile({ variation = "dropzone", size = "base", buttonLabel: provide
1545
1604
  });
1546
1605
  return acc;
1547
1606
  }, []);
1548
- const { buttonLabel, hintText } = getLabels(providedButtonLabel, allowMultiple, allowedTypes);
1549
1607
  const dropZone = classnames(styles.dropZoneBase, {
1550
1608
  [styles.dropZone]: variation === "dropzone",
1551
1609
  [styles.active]: isDragActive,
1552
1610
  [styles.error]: (fileRejections === null || fileRejections === void 0 ? void 0 : fileRejections.length) > 0,
1553
1611
  });
1612
+ const fileType = allowedTypes === "images" || allowedTypes === "basicImages"
1613
+ ? "Image"
1614
+ : "File";
1615
+ const contentContext = {
1616
+ fileType: fileType,
1617
+ allowMultiple,
1618
+ description,
1619
+ hintText: hintText || "",
1620
+ buttonLabel: providedButtonLabel || "",
1621
+ size,
1622
+ };
1623
+ const defaultContent = (React.createElement(React.Fragment, null,
1624
+ variation === "dropzone" && (React.createElement(InputFile.DropzoneWrapper, null,
1625
+ React.createElement(Content.Content, { spacing: "small" },
1626
+ React.createElement(InputFile.Button, { size: "small", fullWidth: false }),
1627
+ size === "base" && (React.createElement(React.Fragment, null,
1628
+ React.createElement(InputFile.HintText, null),
1629
+ React.createElement(InputFile.Description, null)))))),
1630
+ variation === "button" && React.createElement(InputFile.Button, { fullWidth: true })));
1554
1631
  return (React.createElement(React.Fragment, null,
1555
1632
  React.createElement("div", Object.assign({}, getRootProps({ className: dropZone }), { tabIndex: variation === "button" ? -1 : 0 }),
1556
- React.createElement("input", Object.assign({}, getInputProps())),
1557
- variation === "dropzone" && (React.createElement("div", { className: styles.dropzoneContent },
1558
- React.createElement(Content.Content, { spacing: "small" },
1559
- React.createElement(Button.Button, { label: buttonLabel, size: "small", type: "secondary" }),
1560
- size === "base" && (React.createElement(React.Fragment, null,
1561
- React.createElement(Typography.Typography, { size: "small" }, hintText),
1562
- description && (React.createElement(Typography.Typography, { size: "small", textColor: "textSecondary" }, description))))))),
1563
- variation === "button" && (React.createElement(Button.Button, { label: buttonLabel, size: size, type: "secondary", fullWidth: true }))),
1564
- (validationErrors === null || validationErrors === void 0 ? void 0 : validationErrors.length) > 0 && (React.createElement("div", { className: styles.validationErrors }, validationErrors.map(error => (React.createElement(InputValidation.InputValidation, { message: error.message, key: error.code })))))));
1633
+ React.createElement("input", Object.assign({}, getInputProps(), { "data-testid": "input-file-input" })),
1634
+ React.createElement(InputFileContentContext.Provider, { value: contentContext }, children || defaultContent)),
1635
+ React.createElement(InputFileValidationErrors, { validationErrors: validationErrors })));
1565
1636
  function handleDrop(acceptedFiles) {
1566
1637
  acceptedFiles.forEach(file => {
1567
1638
  uploadFile(file);
@@ -1626,19 +1697,6 @@ function createAxiosConfig({ url, httpMethod = "POST", fields = {}, file, handle
1626
1697
  onUploadProgress: handleUploadProgress,
1627
1698
  };
1628
1699
  }
1629
- function getLabels(providedButtonLabel, multiple, allowedTypes) {
1630
- const fileType = allowedTypes === "images" || allowedTypes === "basicImages"
1631
- ? "Image"
1632
- : "File";
1633
- let buttonLabel = multiple ? `Upload ${fileType}s` : `Upload ${fileType}`;
1634
- const fileTypeDeterminer = fileType === "Image" ? "an" : "a";
1635
- const hintText = multiple
1636
- ? `Select or drag ${fileType.toLowerCase()}s here to upload`
1637
- : `Select or drag ${fileTypeDeterminer} ${fileType.toLowerCase()} here to upload`;
1638
- if (providedButtonLabel)
1639
- buttonLabel = providedButtonLabel;
1640
- return { buttonLabel, hintText };
1641
- }
1642
1700
  function getFileUpload(file, key, uploadUrl) {
1643
1701
  return {
1644
1702
  key: key,
@@ -1689,6 +1747,12 @@ function updateFiles(updatedFile, files) {
1689
1747
  function generateId() {
1690
1748
  return Math.floor(Math.random() * Date.now()).toString(16);
1691
1749
  }
1750
+ InputFile.Button = InputFileButton;
1751
+ InputFile.Description = InputFileDescription;
1752
+ InputFile.DropzoneWrapper = InputFileDropzoneWrapper;
1753
+ InputFile.HintText = InputFileHintText;
1692
1754
 
1693
1755
  exports.InputFile = InputFile;
1756
+ exports.InputFileContentContext = InputFileContentContext;
1694
1757
  exports.updateFiles = updateFiles;
1758
+ exports.useInputFileContentContext = useInputFileContentContext;
@@ -1,12 +1,12 @@
1
- import { a as __awaiter, b as __generator, c as __spread } from './tslib.es6-es.js';
2
- import React, { forwardRef, useImperativeHandle, Fragment, useMemo, useRef, useReducer, useEffect, useCallback } from 'react';
1
+ import { a as __awaiter, b as __generator, c as __spread, _ as __rest } from './tslib.es6-es.js';
2
+ import React, { forwardRef, useImperativeHandle, Fragment, useMemo, useRef, useReducer, useEffect, useCallback, createContext, useContext } from 'react';
3
3
  import classnames from 'classnames';
4
4
  import { P as PropTypes } from './index-es.js';
5
5
  import axios from 'axios';
6
- import { I as InputValidation } from './InputValidation-es.js';
6
+ import { T as Text } from './Text-es.js';
7
7
  import { B as Button } from './Button-es.js';
8
+ import { I as InputValidation } from './InputValidation-es.js';
8
9
  import { C as Content } from './Content-es.js';
9
- import { T as Typography } from './Typography-es.js';
10
10
 
11
11
  var COMMON_MIME_TYPES = new Map([
12
12
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
@@ -1471,8 +1471,67 @@ function formatMimeTypes(types) {
1471
1471
  }
1472
1472
  }
1473
1473
 
1474
+ const InputFileContentContext = createContext({
1475
+ fileType: "File",
1476
+ allowMultiple: false,
1477
+ description: undefined,
1478
+ hintText: getDefaultHintText("File", false),
1479
+ buttonLabel: getDefaultLabel(false, "File"),
1480
+ size: "base",
1481
+ });
1482
+ function useInputFileContentContext() {
1483
+ const context = useContext(InputFileContentContext);
1484
+ const computedHintText = context.hintText ||
1485
+ getDefaultHintText(context.fileType, context.allowMultiple);
1486
+ const computedButtonLabel = context.buttonLabel ||
1487
+ getDefaultLabel(context.allowMultiple, context.fileType);
1488
+ return Object.assign(Object.assign({}, context), { hintText: computedHintText, buttonLabel: computedButtonLabel });
1489
+ }
1490
+ function getDefaultLabel(multiple, fileType) {
1491
+ return multiple ? `Upload ${fileType}s` : `Upload ${fileType}`;
1492
+ }
1493
+ function getDefaultHintText(fileType, multiple) {
1494
+ const fileTypeDeterminer = fileType === "Image" ? "an" : "a";
1495
+ const hintText = multiple
1496
+ ? `Select or drag ${fileType.toLowerCase()}s here to upload`
1497
+ : `Select or drag ${fileTypeDeterminer} ${fileType.toLowerCase()} here to upload`;
1498
+ return hintText;
1499
+ }
1500
+
1501
+ function InputFileHintText(_a) {
1502
+ var { size = "small", children } = _a, textProps = __rest(_a, ["size", "children"]);
1503
+ const { hintText } = useInputFileContentContext();
1504
+ return (React.createElement(Text, Object.assign({}, textProps, { size: size }), children || hintText));
1505
+ }
1506
+
1507
+ function InputFileDescription(_a) {
1508
+ var { size = "small", variation = "subdued", children } = _a, textProps = __rest(_a, ["size", "variation", "children"]);
1509
+ const { description } = useInputFileContentContext();
1510
+ if (!children && !description) {
1511
+ return null;
1512
+ }
1513
+ return (React.createElement(Text, Object.assign({ size: size, variation: variation }, textProps), children || description));
1514
+ }
1515
+
1516
+ function InputFileButton(_a) {
1517
+ var { label, size, fullWidth = false } = _a, buttonProps = __rest(_a, ["label", "size", "fullWidth"]);
1518
+ const { buttonLabel: contextLabel, size: contextSize } = useInputFileContentContext();
1519
+ return (React.createElement(Button, Object.assign({}, buttonProps, { label: label || contextLabel, size: size !== null && size !== void 0 ? size : contextSize, type: "secondary", fullWidth: fullWidth })));
1520
+ }
1521
+
1522
+ function InputFileDropzoneWrapper({ children, }) {
1523
+ return React.createElement("div", { className: styles.dropzoneContent }, children);
1524
+ }
1525
+
1526
+ function InputFileValidationErrors({ validationErrors, }) {
1527
+ if (validationErrors.length === 0) {
1528
+ return null;
1529
+ }
1530
+ return (React.createElement("div", { className: styles.validationErrors }, validationErrors.map(error => (React.createElement(InputValidation, { message: error.message, key: error.code })))));
1531
+ }
1532
+
1474
1533
  /* eslint-disable max-statements */
1475
- function InputFile({ variation = "dropzone", size = "base", buttonLabel: providedButtonLabel, allowMultiple = false, allowedTypes = "all", description, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, }) {
1534
+ function InputFile({ variation = "dropzone", size = "base", buttonLabel: providedButtonLabel, allowMultiple = false, allowedTypes = "all", description, hintText, maxFilesValidation, getUploadParams, onUploadStart, onUploadProgress, onUploadComplete, onUploadError, validator, children, }) {
1476
1535
  const maxFiles = (maxFilesValidation === null || maxFilesValidation === void 0 ? void 0 : maxFilesValidation.maxFiles) || 0;
1477
1536
  const numberOfCurrentFiles = (maxFilesValidation === null || maxFilesValidation === void 0 ? void 0 : maxFilesValidation.numberOfCurrentFiles) || 0;
1478
1537
  const handleValidation = useCallback((file) => {
@@ -1543,23 +1602,35 @@ function InputFile({ variation = "dropzone", size = "base", buttonLabel: provide
1543
1602
  });
1544
1603
  return acc;
1545
1604
  }, []);
1546
- const { buttonLabel, hintText } = getLabels(providedButtonLabel, allowMultiple, allowedTypes);
1547
1605
  const dropZone = classnames(styles.dropZoneBase, {
1548
1606
  [styles.dropZone]: variation === "dropzone",
1549
1607
  [styles.active]: isDragActive,
1550
1608
  [styles.error]: (fileRejections === null || fileRejections === void 0 ? void 0 : fileRejections.length) > 0,
1551
1609
  });
1610
+ const fileType = allowedTypes === "images" || allowedTypes === "basicImages"
1611
+ ? "Image"
1612
+ : "File";
1613
+ const contentContext = {
1614
+ fileType: fileType,
1615
+ allowMultiple,
1616
+ description,
1617
+ hintText: hintText || "",
1618
+ buttonLabel: providedButtonLabel || "",
1619
+ size,
1620
+ };
1621
+ const defaultContent = (React.createElement(React.Fragment, null,
1622
+ variation === "dropzone" && (React.createElement(InputFile.DropzoneWrapper, null,
1623
+ React.createElement(Content, { spacing: "small" },
1624
+ React.createElement(InputFile.Button, { size: "small", fullWidth: false }),
1625
+ size === "base" && (React.createElement(React.Fragment, null,
1626
+ React.createElement(InputFile.HintText, null),
1627
+ React.createElement(InputFile.Description, null)))))),
1628
+ variation === "button" && React.createElement(InputFile.Button, { fullWidth: true })));
1552
1629
  return (React.createElement(React.Fragment, null,
1553
1630
  React.createElement("div", Object.assign({}, getRootProps({ className: dropZone }), { tabIndex: variation === "button" ? -1 : 0 }),
1554
- React.createElement("input", Object.assign({}, getInputProps())),
1555
- variation === "dropzone" && (React.createElement("div", { className: styles.dropzoneContent },
1556
- React.createElement(Content, { spacing: "small" },
1557
- React.createElement(Button, { label: buttonLabel, size: "small", type: "secondary" }),
1558
- size === "base" && (React.createElement(React.Fragment, null,
1559
- React.createElement(Typography, { size: "small" }, hintText),
1560
- description && (React.createElement(Typography, { size: "small", textColor: "textSecondary" }, description))))))),
1561
- variation === "button" && (React.createElement(Button, { label: buttonLabel, size: size, type: "secondary", fullWidth: true }))),
1562
- (validationErrors === null || validationErrors === void 0 ? void 0 : validationErrors.length) > 0 && (React.createElement("div", { className: styles.validationErrors }, validationErrors.map(error => (React.createElement(InputValidation, { message: error.message, key: error.code })))))));
1631
+ React.createElement("input", Object.assign({}, getInputProps(), { "data-testid": "input-file-input" })),
1632
+ React.createElement(InputFileContentContext.Provider, { value: contentContext }, children || defaultContent)),
1633
+ React.createElement(InputFileValidationErrors, { validationErrors: validationErrors })));
1563
1634
  function handleDrop(acceptedFiles) {
1564
1635
  acceptedFiles.forEach(file => {
1565
1636
  uploadFile(file);
@@ -1624,19 +1695,6 @@ function createAxiosConfig({ url, httpMethod = "POST", fields = {}, file, handle
1624
1695
  onUploadProgress: handleUploadProgress,
1625
1696
  };
1626
1697
  }
1627
- function getLabels(providedButtonLabel, multiple, allowedTypes) {
1628
- const fileType = allowedTypes === "images" || allowedTypes === "basicImages"
1629
- ? "Image"
1630
- : "File";
1631
- let buttonLabel = multiple ? `Upload ${fileType}s` : `Upload ${fileType}`;
1632
- const fileTypeDeterminer = fileType === "Image" ? "an" : "a";
1633
- const hintText = multiple
1634
- ? `Select or drag ${fileType.toLowerCase()}s here to upload`
1635
- : `Select or drag ${fileTypeDeterminer} ${fileType.toLowerCase()} here to upload`;
1636
- if (providedButtonLabel)
1637
- buttonLabel = providedButtonLabel;
1638
- return { buttonLabel, hintText };
1639
- }
1640
1698
  function getFileUpload(file, key, uploadUrl) {
1641
1699
  return {
1642
1700
  key: key,
@@ -1687,5 +1745,9 @@ function updateFiles(updatedFile, files) {
1687
1745
  function generateId() {
1688
1746
  return Math.floor(Math.random() * Date.now()).toString(16);
1689
1747
  }
1748
+ InputFile.Button = InputFileButton;
1749
+ InputFile.Description = InputFileDescription;
1750
+ InputFile.DropzoneWrapper = InputFileDropzoneWrapper;
1751
+ InputFile.HintText = InputFileHintText;
1690
1752
 
1691
- export { InputFile as I, updateFiles as u };
1753
+ export { InputFile as I, InputFileContentContext as a, useInputFileContentContext as b, updateFiles as u };
@@ -1,9 +1,8 @@
1
1
  import { PropsWithChildren } from "react";
2
- interface TextProps {
2
+ export interface TextProps {
3
3
  readonly maxLines?: "single" | "small" | "base" | "large" | "larger" | "unlimited";
4
4
  readonly variation?: "default" | "subdued" | "success" | "error" | "warn" | "info" | "disabled";
5
5
  readonly align?: "start" | "center" | "end";
6
6
  readonly size?: "small" | "base" | "large";
7
7
  }
8
8
  export declare function Text({ variation, size, align, children, maxLines, }: PropsWithChildren<TextProps>): JSX.Element;
9
- export {};
@@ -1 +1,2 @@
1
1
  export { Text } from "./Text";
2
+ export type { TextProps } from "./Text";
package/dist/index.cjs CHANGED
@@ -259,7 +259,9 @@ exports.InputDate = InputDate_index.InputDate;
259
259
  exports.InputEmail = InputEmail.InputEmail;
260
260
  exports.validationMessage = InputEmail.validationMessage;
261
261
  exports.InputFile = InputFile.InputFile;
262
+ exports.InputFileContentContext = InputFile.InputFileContentContext;
262
263
  exports.updateFiles = InputFile.updateFiles;
264
+ exports.useInputFileContentContext = InputFile.useInputFileContentContext;
263
265
  exports.InputGroup = InputGroup.InputGroup;
264
266
  exports.InputNumber = InputNumber.InputNumber;
265
267
  exports.InputPassword = InputPassword.InputPassword;
package/dist/index.mjs CHANGED
@@ -56,7 +56,7 @@ export { I as InlineLabel } from './InlineLabel-es.js';
56
56
  export { I as InputAvatar } from './InputAvatar-es.js';
57
57
  export { InputDate } from './InputDate/index.mjs';
58
58
  export { I as InputEmail, v as validationMessage } from './InputEmail-es.js';
59
- export { I as InputFile, u as updateFiles } from './InputFile-es.js';
59
+ export { I as InputFile, a as InputFileContentContext, u as updateFiles, b as useInputFileContentContext } from './InputFile-es.js';
60
60
  export { I as InputGroup } from './InputGroup-es.js';
61
61
  export { I as InputNumber } from './InputNumber-es.js';
62
62
  export { I as InputPassword } from './InputPassword-es.js';
@@ -87,6 +87,12 @@
87
87
  "InputDate",
88
88
  "InputEmail",
89
89
  "InputFile",
90
+ "InputFile.Button",
91
+ "InputFile.Description",
92
+ "InputFile.DropzoneWrapper",
93
+ "InputFile.HintText",
94
+ "InputFileContentContext.Consumer",
95
+ "InputFileContentContext.Provider",
90
96
  "InputGroup",
91
97
  "InputNumber",
92
98
  "InputPassword",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.21.0",
3
+ "version": "6.22.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -489,5 +489,5 @@
489
489
  "> 1%",
490
490
  "IE 10"
491
491
  ],
492
- "gitHead": "28e267f721a53c3aa458cdc30ea15b9aaf11c66e"
492
+ "gitHead": "e9c763ee038899442b41548c22005d4ff2ab00db"
493
493
  }