@financial-times/o3-form 0.1.0 → 0.3.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.
- package/README.md +107 -0
- package/cjs/CheckBox.d.ts +8 -0
- package/cjs/CheckBox.js +53 -0
- package/cjs/TextInput.d.ts +6 -0
- package/cjs/TextInput.js +45 -0
- package/cjs/index-BP51ZwQo.d.ts +34 -0
- package/cjs/index.d.ts +3 -31
- package/cjs/index.js +1 -0
- package/css/main.css +165 -14
- package/css/whitelabel.css +9 -0
- package/esm/CheckBox.d.ts +8 -0
- package/esm/CheckBox.js +53 -0
- package/esm/TextInput.d.ts +6 -0
- package/esm/TextInput.js +45 -0
- package/esm/index-BP51ZwQo.d.ts +34 -0
- package/esm/index.d.ts +3 -31
- package/esm/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,108 @@
|
|
|
1
1
|
# o3-form[](#licence)
|
|
2
|
+
|
|
3
|
+
Provides components to construct forms.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
o3-form provides UI form elements with consistent labelling, descriptions, and error styles and interfaces.
|
|
8
|
+
|
|
9
|
+
## Components
|
|
10
|
+
|
|
11
|
+
### Text Input
|
|
12
|
+
|
|
13
|
+
A standard text input for collecting text values.
|
|
14
|
+
label: 'Full name',
|
|
15
|
+
description: 'Your full name as printed on your driving license',
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<TextInput label='Full name'
|
|
19
|
+
disabled={false}
|
|
20
|
+
description='Your full name as printed on your driving license'
|
|
21
|
+
/>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**HTML**
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
<div data-o3-brand="whitelabel">
|
|
28
|
+
<div class="o3-form-field">
|
|
29
|
+
<label for="my-input-field">Full name</label>
|
|
30
|
+
<span
|
|
31
|
+
class="o3-form-input-description"
|
|
32
|
+
>
|
|
33
|
+
Your full name as printed on your driving license
|
|
34
|
+
</span>
|
|
35
|
+
<input id="my-input-field" class="o3-form o3-form-text-input" type="text" />
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Short text input
|
|
41
|
+
|
|
42
|
+
The size and max length of the text input can be limited with the `length` property.
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
|
|
46
|
+
<TextInput label="Security code"
|
|
47
|
+
description="3 digit security code as printed on the back of your credit card."
|
|
48
|
+
length={3} />;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**HTML**
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<div class="o3-form-field">
|
|
55
|
+
<label for="my-input-field">Security Code</label>
|
|
56
|
+
<span
|
|
57
|
+
class="o3-form-input-description"
|
|
58
|
+
>
|
|
59
|
+
3 digit security code as printed on the back of your credit card.
|
|
60
|
+
</span>
|
|
61
|
+
<input
|
|
62
|
+
id="my-input-field"
|
|
63
|
+
class="o3-form o3-form-text-input o3-form-text-input--short-3"
|
|
64
|
+
maxlength="3"
|
|
65
|
+
type="text"
|
|
66
|
+
/>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This will provide a text box 3 characters wide and only allow 3 characters to be typed.
|
|
70
|
+
|
|
71
|
+
If you prefer to limit the length without styling, use the `maxLength` attribute instead.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<TextInput label="Security code"
|
|
75
|
+
description="3 digit security code as printed on the back of your credit card."
|
|
76
|
+
feedback={args.feedback}
|
|
77
|
+
attributes={{
|
|
78
|
+
maxLength: 3
|
|
79
|
+
}} />;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**HTML**
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<div class="o3-form-field">
|
|
86
|
+
<label for="my-input-field">Security Code</label>
|
|
87
|
+
<span
|
|
88
|
+
class="o3-form-input-description"
|
|
89
|
+
>
|
|
90
|
+
3 digit security code as printed on the back of your credit card.
|
|
91
|
+
</span>
|
|
92
|
+
<input
|
|
93
|
+
id="my-input-field"
|
|
94
|
+
class="o3-form o3-form-text-input"
|
|
95
|
+
maxlength="3"
|
|
96
|
+
type="text"
|
|
97
|
+
/>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Contact
|
|
101
|
+
|
|
102
|
+
If you have any questions or comments about this component, or need help using it, please either [raise an issue](https://github.com/Financial-Times/o3-editorial-typography/issues), visit [#origami-support](https://financialtimes.slack.com/messages/origami-support/) or email [Origami Support](mailto:origami-support@ft.com).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Licence
|
|
107
|
+
|
|
108
|
+
This software is published by the Financial Times under the [MIT licence](http://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { C as CheckBoxProps, b as FormFieldsetProps } from './index-BP51ZwQo.js';
|
|
3
|
+
|
|
4
|
+
declare const CheckBoxItem: (props: CheckBoxProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare const CheckBox: (props: CheckBoxProps) => react_jsx_runtime.JSX.Element;
|
|
6
|
+
declare const CheckBoxGroup: (props: FormFieldsetProps) => react_jsx_runtime.JSX.Element;
|
|
7
|
+
|
|
8
|
+
export { CheckBox, CheckBoxGroup, CheckBoxItem };
|
package/cjs/CheckBox.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _jsxruntime = require('react/jsx-runtime');
|
|
2
|
+
var _react = require('react');
|
|
3
|
+
var _FormField = require('./fieldComponents/FormField');
|
|
4
|
+
const CheckBoxItem = (props) => {
|
|
5
|
+
let { inputId, attributes, optional, error } = props;
|
|
6
|
+
const classNames = ["o3-form-input__checkbox-input", "o3-visually-hidden"];
|
|
7
|
+
if (error) {
|
|
8
|
+
classNames.push("o3-form-input-error");
|
|
9
|
+
}
|
|
10
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "o3-form-input__checkbox", children: [
|
|
11
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
12
|
+
"input",
|
|
13
|
+
{
|
|
14
|
+
...attributes,
|
|
15
|
+
type: "checkbox",
|
|
16
|
+
id: inputId,
|
|
17
|
+
className: classNames.join(" "),
|
|
18
|
+
required: !optional,
|
|
19
|
+
"aria-required": !optional
|
|
20
|
+
}
|
|
21
|
+
),
|
|
22
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: inputId, className: "o3-form-input__checkbox-label", children: props.checkboxLabel })
|
|
23
|
+
] });
|
|
24
|
+
};
|
|
25
|
+
const CheckBox = (props) => {
|
|
26
|
+
const newProps = {
|
|
27
|
+
...props,
|
|
28
|
+
labelId: props.inputId,
|
|
29
|
+
descriptionId: props.inputId
|
|
30
|
+
};
|
|
31
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _FormField.LabeledFormField, { ...newProps, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CheckBoxItem, { ...newProps, children: " " }) });
|
|
32
|
+
};
|
|
33
|
+
const CheckBoxGroup = (props) => {
|
|
34
|
+
const { children, ...restProps } = props;
|
|
35
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _FormField.FormFieldset, { ...restProps, children: children.map((child) => {
|
|
36
|
+
const hasError = _optionalChain([props, 'access', _ => _.feedback, 'optionalAccess', _2 => _2.errorElementIds, 'optionalAccess', _3 => _3.includes, 'call', _4 => _4(
|
|
37
|
+
child.props.inputId
|
|
38
|
+
)]);
|
|
39
|
+
return /* @__PURE__ */ _react.createElement.call(void 0,
|
|
40
|
+
CheckBoxItem,
|
|
41
|
+
{
|
|
42
|
+
...child.props,
|
|
43
|
+
error: hasError,
|
|
44
|
+
key: child.props.inputId
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}) });
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
exports.CheckBox = CheckBox; exports.CheckBoxGroup = CheckBoxGroup; exports.CheckBoxItem = CheckBoxItem;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { T as TextInputProps } from './index-BP51ZwQo.js';
|
|
3
|
+
|
|
4
|
+
declare const TextInput: ({ label, feedback, description, disabled, length, attributes, inputId, optional, }: TextInputProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { TextInput };
|
package/cjs/TextInput.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _jsxruntime = require('react/jsx-runtime');
|
|
2
|
+
require('../../main.css');
|
|
3
|
+
var _FormField = require('./fieldComponents/FormField');
|
|
4
|
+
const TextInput = ({
|
|
5
|
+
label,
|
|
6
|
+
feedback,
|
|
7
|
+
description,
|
|
8
|
+
disabled,
|
|
9
|
+
length,
|
|
10
|
+
attributes,
|
|
11
|
+
inputId,
|
|
12
|
+
optional
|
|
13
|
+
}) => {
|
|
14
|
+
const inputClasses = ["o3-form", "o3-form-text-input"];
|
|
15
|
+
if (feedback && feedback.type === "error") {
|
|
16
|
+
inputClasses.push("o3-form-text-input--error");
|
|
17
|
+
}
|
|
18
|
+
if (length) {
|
|
19
|
+
inputClasses.push(`o3-form-text-input--short-${length}`);
|
|
20
|
+
}
|
|
21
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
22
|
+
_FormField.LabeledFormField,
|
|
23
|
+
{
|
|
24
|
+
label,
|
|
25
|
+
feedback,
|
|
26
|
+
description,
|
|
27
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
28
|
+
"input",
|
|
29
|
+
{
|
|
30
|
+
...attributes,
|
|
31
|
+
id: inputId,
|
|
32
|
+
disabled,
|
|
33
|
+
className: inputClasses.join(" "),
|
|
34
|
+
required: optional,
|
|
35
|
+
"aria-required": optional,
|
|
36
|
+
maxLength: length,
|
|
37
|
+
type: "text"
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
exports.TextInput = TextInput;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type BaseInputProps = {
|
|
2
|
+
inputId?: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
optional?: boolean;
|
|
6
|
+
error?: boolean;
|
|
7
|
+
attributes?: JSX.IntrinsicElements['input'];
|
|
8
|
+
};
|
|
9
|
+
interface TextInputProps extends FormFieldProps {
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
length?: 2 | 3 | 4 | 5;
|
|
12
|
+
feedback?: FeedbackProps;
|
|
13
|
+
}
|
|
14
|
+
interface CheckBoxProps extends BaseInputProps {
|
|
15
|
+
inputId: string;
|
|
16
|
+
checkboxLabel: string;
|
|
17
|
+
}
|
|
18
|
+
interface FormFieldsetProps {
|
|
19
|
+
label: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
children: JSX.Element | JSX.Element[];
|
|
22
|
+
feedback?: FeedbackProps;
|
|
23
|
+
}
|
|
24
|
+
interface FormFieldProps extends BaseInputProps {
|
|
25
|
+
feedback?: FeedbackProps;
|
|
26
|
+
children: JSX.Element & JSX.IntrinsicElements['input'];
|
|
27
|
+
}
|
|
28
|
+
type FeedbackProps = {
|
|
29
|
+
errorElementIds?: string[];
|
|
30
|
+
message: string;
|
|
31
|
+
type: 'error';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type { CheckBoxProps as C, FeedbackProps as F, TextInputProps as T, FormFieldProps as a, FormFieldsetProps as b };
|
package/cjs/index.d.ts
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { F as FeedbackProps, a as FormFieldProps, b as FormFieldsetProps } from './index-BP51ZwQo.js';
|
|
3
|
+
export { CheckBox, CheckBoxGroup, CheckBoxItem } from './CheckBox.js';
|
|
2
4
|
|
|
3
|
-
type
|
|
4
|
-
inputId?: string;
|
|
5
|
-
label?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
optional?: boolean;
|
|
8
|
-
error?: string;
|
|
9
|
-
attributes?: JSX.IntrinsicElements['input'];
|
|
10
|
-
};
|
|
11
|
-
interface FormFieldProps extends BaseInputProps {
|
|
12
|
-
feedback?: FeedBackProps;
|
|
13
|
-
children: JSX.Element & JSX.IntrinsicElements['input'];
|
|
14
|
-
}
|
|
15
|
-
interface FormFieldsetProps {
|
|
16
|
-
label: string;
|
|
17
|
-
description?: string;
|
|
18
|
-
error?: string;
|
|
19
|
-
children: JSX.Element | JSX.Element[];
|
|
20
|
-
feedback?: FeedBackProps;
|
|
21
|
-
}
|
|
22
|
-
interface FormFieldsetProps {
|
|
23
|
-
label: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
error?: string;
|
|
26
|
-
children: JSX.Element | JSX.Element[];
|
|
27
|
-
}
|
|
28
|
-
type FeedBackProps = {
|
|
29
|
-
message: string;
|
|
30
|
-
type: 'error';
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
declare const Feedback: ({ message, type }: FeedBackProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare const Feedback: ({ message, type }: FeedbackProps) => react_jsx_runtime.JSX.Element;
|
|
34
6
|
|
|
35
7
|
declare const LabeledFormField: ({ inputId, label, description, feedback, children, optional, }: FormFieldProps) => react_jsx_runtime.JSX.Element;
|
|
36
8
|
declare const TitledFormField: ({ label, description, feedback, children, optional, }: FormFieldProps) => react_jsx_runtime.JSX.Element;
|
package/cjs/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }var _Feedback = require('./fieldComponents/Feedback'); _createStarExport(_Feedback);
|
|
2
2
|
var _FormField = require('./fieldComponents/FormField'); _createStarExport(_FormField);
|
|
3
3
|
var _Form = require('./fieldComponents/Form'); _createStarExport(_Form);
|
|
4
|
+
var _CheckBox = require('./CheckBox'); _createStarExport(_CheckBox);
|
package/css/main.css
CHANGED
|
@@ -7,32 +7,183 @@
|
|
|
7
7
|
.o3-form-field {
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-direction: column;
|
|
10
|
+
font-family: var(--o3-font-family-metric);
|
|
10
11
|
gap: var(--o3-spacing-3xs);
|
|
11
12
|
}
|
|
12
|
-
.o3-form-
|
|
13
|
-
|
|
13
|
+
.o3-form-field:where(fieldset) {
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
border: 0;
|
|
17
|
+
}
|
|
18
|
+
.o3-form-field :is(.o3-form-field__label, .o3-form-field__title, .o3-form-field__legend) {
|
|
14
19
|
font-size: var(--o3-font-size-metric2-0);
|
|
20
|
+
line-height: var(--o3-font-lineheight-metric2-0);
|
|
21
|
+
font-weight: var(--o3-font-weight-medium);
|
|
22
|
+
color: var(--o3-color-use-case-body-text);
|
|
15
23
|
}
|
|
16
|
-
.o3-form-field__title {
|
|
24
|
+
.o3-form-field :is(.o3-form-field__label, .o3-form-field__title, .o3-form-field__legend):has(~ .o3-form-input__checkbox > input:not(:required))::after {
|
|
25
|
+
content: "(optional)";
|
|
26
|
+
margin-left: var(--o3-spacing-3xs);
|
|
27
|
+
color: var(--o3-color-use-case-muted-text);
|
|
28
|
+
font-weight: var(--o3-font-weight-regular);
|
|
29
|
+
}
|
|
30
|
+
.o3-form-field .o3-form-field__legend {
|
|
31
|
+
padding: 0 0 var(--o3-spacing-5xs) 0;
|
|
32
|
+
}
|
|
33
|
+
.o3-form-field .o3-form-input__description {
|
|
17
34
|
font-size: var(--o3-font-size-metric2-0);
|
|
18
|
-
|
|
35
|
+
line-height: var(--o3-font-lineheight-metric2-0);
|
|
36
|
+
font-weight: var(--o3-font-weight-regular);
|
|
37
|
+
color: var(--o3-color-palette-black-60);
|
|
19
38
|
}
|
|
20
|
-
|
|
21
|
-
margin:
|
|
22
|
-
padding: 0;
|
|
23
|
-
border: 0;
|
|
39
|
+
.o3-form-field :is(.o3-form-field__label + .o3-form-input__description, .o3-form-field__title + .o3-form-input__description) {
|
|
40
|
+
margin-top: calc(-1 * var(--o3-spacing-4xs));
|
|
24
41
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
.o3-form-field__feedback--error {
|
|
43
|
+
color: var(--o3-color-use-case-error);
|
|
44
|
+
font-size: var(--o3-font-size-metric2-0);
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
/* src/css/components/feedback.css */
|
|
31
|
-
[class^=o3-form-feedback__] {
|
|
32
|
-
margin-top: var(--o3-spacing-3xs);
|
|
33
|
-
}
|
|
34
48
|
.o3-form-feedback__error {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
font-size: var(--o3-font-size-metric2-0);
|
|
52
|
+
line-height: var(--o3-font-lineheight-metric2-0);
|
|
35
53
|
color: var(--o3-color-palette-crimson);
|
|
36
54
|
}
|
|
55
|
+
.o3-form-feedback__error-message {
|
|
56
|
+
margin-left: var(--o3-spacing-5xs);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* src/css/components/text-input.css */
|
|
60
|
+
.o3-form-text-input {
|
|
61
|
+
border: var(--_o3-form-text-input-border);
|
|
62
|
+
padding: var(--o3-spacing-3xs) var(--o3-spacing-2xs);
|
|
63
|
+
background-color: var(--_o3-form-text-input-background-color);
|
|
64
|
+
border-radius: var(--_o3-form-text-input-border-radius);
|
|
65
|
+
max-width: var(--_o3-form-text-input-max-width);
|
|
66
|
+
}
|
|
67
|
+
.o3-form-text-input--short-2 {
|
|
68
|
+
--_o3-form-text-input-max-width: 1.5em;
|
|
69
|
+
}
|
|
70
|
+
.o3-form-text-input--short-3 {
|
|
71
|
+
--_o3-form-text-input-max-width: 2.5em;
|
|
72
|
+
}
|
|
73
|
+
.o3-form-text-input--short-4 {
|
|
74
|
+
--_o3-form-text-input-max-width: 3.5em;
|
|
75
|
+
}
|
|
76
|
+
.o3-form-text-input--short-5 {
|
|
77
|
+
--_o3-form-text-input-max-width: 4.5em;
|
|
78
|
+
}
|
|
79
|
+
.o3-form-text-input--error {
|
|
80
|
+
border: var(--_o3-form-text-input-border-error);
|
|
81
|
+
background-color: var(--_o3-form-text-input-background-color-error);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* src/css/components/checkbox.css */
|
|
85
|
+
.o3-form-input__checkbox-input + label::before {
|
|
86
|
+
content: "";
|
|
87
|
+
display: inline-block;
|
|
88
|
+
width: var(--o3-spacing-s);
|
|
89
|
+
height: var(--o3-spacing-s);
|
|
90
|
+
margin-right: var(--o3-spacing-3xs);
|
|
91
|
+
border: 2px solid var(--o3-color-palette-black-50);
|
|
92
|
+
border-radius: var(--o3-spacing-5xs);
|
|
93
|
+
box-sizing: border-box;
|
|
94
|
+
}
|
|
95
|
+
.o3-form-input__checkbox-input:hover + label::before {
|
|
96
|
+
border-color: var(--o3-color-palette-black-40);
|
|
97
|
+
}
|
|
98
|
+
.o3-form-input__checkbox-input:active + label::before {
|
|
99
|
+
border-color: var(--o3-color-palette-black-30);
|
|
100
|
+
}
|
|
101
|
+
.o3-form-input__checkbox-input:checked + label::after {
|
|
102
|
+
position: absolute;
|
|
103
|
+
content: "";
|
|
104
|
+
width: var(--o3-spacing-s);
|
|
105
|
+
height: var(--o3-spacing-s);
|
|
106
|
+
background-color: var(--o3-color-palette-white);
|
|
107
|
+
-webkit-mask-image: var(--o3-icons-ft-icon-tick);
|
|
108
|
+
mask-image: var(--o3-icons-ft-icon-tick);
|
|
109
|
+
-webkit-mask-repeat: no-repeat;
|
|
110
|
+
mask-repeat: no-repeat;
|
|
111
|
+
-webkit-mask-size: contain;
|
|
112
|
+
mask-size: contain;
|
|
113
|
+
}
|
|
114
|
+
.o3-form-input__checkbox-input:checked + label::before {
|
|
115
|
+
background-color: var(--o3-color-palette-black-50);
|
|
116
|
+
}
|
|
117
|
+
.o3-form-input__checkbox-input:checked:hover + label::before {
|
|
118
|
+
background-color: var(--o3-color-palette-black-40);
|
|
119
|
+
}
|
|
120
|
+
.o3-form-input__checkbox-input:checked:active + label::before {
|
|
121
|
+
background-color: var(--o3-color-palette-black-30);
|
|
122
|
+
}
|
|
123
|
+
.o3-form-input__checkbox-input:disabled + label::before {
|
|
124
|
+
border-color: var(--o3-color-palette-black-30);
|
|
125
|
+
}
|
|
126
|
+
.o3-form-input__checkbox-input:disabled + label {
|
|
127
|
+
color: var(--o3-color-palette-black-30);
|
|
128
|
+
}
|
|
129
|
+
.o3-form-input__checkbox-input:checked:disabled + label::before {
|
|
130
|
+
background-color: var(--o3-color-palette-black-30);
|
|
131
|
+
}
|
|
132
|
+
.o3-form-input__checkbox-input.o3-form-input-error + label::before {
|
|
133
|
+
border-color: var(--o3-color-use-case-error);
|
|
134
|
+
background-color: var(--o3-color-use-case-error-background);
|
|
135
|
+
}
|
|
136
|
+
.o3-form-input__checkbox-input.o3-form-input-error:checked + label::before {
|
|
137
|
+
border-color: var(--o3-color-use-case-error);
|
|
138
|
+
background-color: var(--o3-color-use-case-error-background);
|
|
139
|
+
}
|
|
140
|
+
.o3-form-input__checkbox-input.o3-form-input-error:checked + label::after {
|
|
141
|
+
background-color: var(--o3-color-use-case-error);
|
|
142
|
+
}
|
|
143
|
+
.o3-form-input__checkbox-input:indeterminate + label::before {
|
|
144
|
+
border-color: var(--o3-color-palette-black-50);
|
|
145
|
+
background-color: var(--o3-color-palette-black-50);
|
|
146
|
+
}
|
|
147
|
+
.o3-form-input__checkbox-input:indeterminate + label::after {
|
|
148
|
+
position: absolute;
|
|
149
|
+
content: "";
|
|
150
|
+
width: var(--o3-spacing-s);
|
|
151
|
+
height: var(--o3-spacing-s);
|
|
152
|
+
background-color: var(--o3-color-palette-white);
|
|
153
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='5' y='10' width='14' height='4' rx='2' fill='%23CC0000'/%3E%3C/svg%3E%0A");
|
|
154
|
+
mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='5' y='10' width='14' height='4' rx='2' fill='%23CC0000'/%3E%3C/svg%3E%0A");
|
|
155
|
+
-webkit-mask-repeat: no-repeat;
|
|
156
|
+
mask-repeat: no-repeat;
|
|
157
|
+
-webkit-mask-size: contain;
|
|
158
|
+
mask-size: contain;
|
|
159
|
+
}
|
|
160
|
+
.o3-form-input__checkbox-input:indeterminate:hover + label::before {
|
|
161
|
+
border-color: var(--o3-color-palette-black-40);
|
|
162
|
+
background-color: var(--o3-color-palette-black-40);
|
|
163
|
+
}
|
|
164
|
+
.o3-form-input__checkbox-input:indeterminate:active + label::before,
|
|
165
|
+
.o3-form-input__checkbox-input:indeterminate:disabled + label::before {
|
|
166
|
+
border-color: var(--o3-color-palette-black-30);
|
|
167
|
+
background-color: var(--o3-color-palette-black-30);
|
|
168
|
+
}
|
|
169
|
+
.o3-form-input__checkbox-input.o3-form-input-error:indeterminate + label::before {
|
|
170
|
+
border-color: var(--o3-color-use-case-error);
|
|
171
|
+
background-color: var(--o3-color-use-case-error-background);
|
|
172
|
+
}
|
|
173
|
+
.o3-form-input__checkbox-input.o3-form-input-error:indeterminate + label::after {
|
|
174
|
+
background-color: var(--o3-color-use-case-error);
|
|
175
|
+
}
|
|
176
|
+
.o3-form-input__checkbox-label {
|
|
177
|
+
display: flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
font-size: var(--o3-font-size-metric2-0);
|
|
180
|
+
line-height: var(--o3-font-lineheight-metric2-0);
|
|
181
|
+
font-weight: var(--o3-font-weight-regular);
|
|
182
|
+
color: var(--o3-color-use-case-body-text);
|
|
183
|
+
}
|
|
184
|
+
.o3-form-input__checkbox-label:focus-visible {
|
|
185
|
+
padding: var(--o3-spacing-5xs);
|
|
186
|
+
margin: calc(-1 * var(--o3-spacing-5xs)) 0 calc(-1 * var(--o3-spacing-5xs)) calc(-1 * var(--o3-spacing-5xs));
|
|
187
|
+
}
|
|
37
188
|
|
|
38
189
|
/* main.css */
|
package/css/whitelabel.css
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
@import "@financial-times/o3-foundation/css/whitelabel.css";
|
|
2
2
|
@import "./main.css";
|
|
3
3
|
|
|
4
|
+
/* src/css/tokens/whitelabel/o3-form/_variables.css */
|
|
5
|
+
[data-o3-brand=whitelabel] .o3-form {
|
|
6
|
+
--_o3-form-text-input-border: 2px solid var(--o3-color-palette-black-30);
|
|
7
|
+
--_o3-form-text-input-border-error: 2px solid var(--o3-color-use-case-alert-text);
|
|
8
|
+
--_o3-form-text-input-background-color: var(--o3-color-palette-white);
|
|
9
|
+
--_o3-form-text-input-background-color-error: rgba(204, 0, 0, 0.06);
|
|
10
|
+
--_o3-form-text-input-border-radius: 0.375rem;
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
/* src/css/brands/whitelabel.css */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { C as CheckBoxProps, b as FormFieldsetProps } from './index-BP51ZwQo.js';
|
|
3
|
+
|
|
4
|
+
declare const CheckBoxItem: (props: CheckBoxProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare const CheckBox: (props: CheckBoxProps) => react_jsx_runtime.JSX.Element;
|
|
6
|
+
declare const CheckBoxGroup: (props: FormFieldsetProps) => react_jsx_runtime.JSX.Element;
|
|
7
|
+
|
|
8
|
+
export { CheckBox, CheckBoxGroup, CheckBoxItem };
|
package/esm/CheckBox.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createElement } from "react";
|
|
3
|
+
import { LabeledFormField, FormFieldset } from "./fieldComponents/FormField";
|
|
4
|
+
const CheckBoxItem = (props) => {
|
|
5
|
+
let { inputId, attributes, optional, error } = props;
|
|
6
|
+
const classNames = ["o3-form-input__checkbox-input", "o3-visually-hidden"];
|
|
7
|
+
if (error) {
|
|
8
|
+
classNames.push("o3-form-input-error");
|
|
9
|
+
}
|
|
10
|
+
return /* @__PURE__ */ jsxs("div", { className: "o3-form-input__checkbox", children: [
|
|
11
|
+
/* @__PURE__ */ jsx(
|
|
12
|
+
"input",
|
|
13
|
+
{
|
|
14
|
+
...attributes,
|
|
15
|
+
type: "checkbox",
|
|
16
|
+
id: inputId,
|
|
17
|
+
className: classNames.join(" "),
|
|
18
|
+
required: !optional,
|
|
19
|
+
"aria-required": !optional
|
|
20
|
+
}
|
|
21
|
+
),
|
|
22
|
+
/* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "o3-form-input__checkbox-label", children: props.checkboxLabel })
|
|
23
|
+
] });
|
|
24
|
+
};
|
|
25
|
+
const CheckBox = (props) => {
|
|
26
|
+
const newProps = {
|
|
27
|
+
...props,
|
|
28
|
+
labelId: props.inputId,
|
|
29
|
+
descriptionId: props.inputId
|
|
30
|
+
};
|
|
31
|
+
return /* @__PURE__ */ jsx(LabeledFormField, { ...newProps, children: /* @__PURE__ */ jsx(CheckBoxItem, { ...newProps, children: " " }) });
|
|
32
|
+
};
|
|
33
|
+
const CheckBoxGroup = (props) => {
|
|
34
|
+
const { children, ...restProps } = props;
|
|
35
|
+
return /* @__PURE__ */ jsx(FormFieldset, { ...restProps, children: children.map((child) => {
|
|
36
|
+
const hasError = props.feedback?.errorElementIds?.includes(
|
|
37
|
+
child.props.inputId
|
|
38
|
+
);
|
|
39
|
+
return /* @__PURE__ */ createElement(
|
|
40
|
+
CheckBoxItem,
|
|
41
|
+
{
|
|
42
|
+
...child.props,
|
|
43
|
+
error: hasError,
|
|
44
|
+
key: child.props.inputId
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}) });
|
|
48
|
+
};
|
|
49
|
+
export {
|
|
50
|
+
CheckBox,
|
|
51
|
+
CheckBoxGroup,
|
|
52
|
+
CheckBoxItem
|
|
53
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { T as TextInputProps } from './index-BP51ZwQo.js';
|
|
3
|
+
|
|
4
|
+
declare const TextInput: ({ label, feedback, description, disabled, length, attributes, inputId, optional, }: TextInputProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { TextInput };
|
package/esm/TextInput.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import "../../main.css";
|
|
3
|
+
import { LabeledFormField } from "./fieldComponents/FormField";
|
|
4
|
+
const TextInput = ({
|
|
5
|
+
label,
|
|
6
|
+
feedback,
|
|
7
|
+
description,
|
|
8
|
+
disabled,
|
|
9
|
+
length,
|
|
10
|
+
attributes,
|
|
11
|
+
inputId,
|
|
12
|
+
optional
|
|
13
|
+
}) => {
|
|
14
|
+
const inputClasses = ["o3-form", "o3-form-text-input"];
|
|
15
|
+
if (feedback && feedback.type === "error") {
|
|
16
|
+
inputClasses.push("o3-form-text-input--error");
|
|
17
|
+
}
|
|
18
|
+
if (length) {
|
|
19
|
+
inputClasses.push(`o3-form-text-input--short-${length}`);
|
|
20
|
+
}
|
|
21
|
+
return /* @__PURE__ */ jsx(
|
|
22
|
+
LabeledFormField,
|
|
23
|
+
{
|
|
24
|
+
label,
|
|
25
|
+
feedback,
|
|
26
|
+
description,
|
|
27
|
+
children: /* @__PURE__ */ jsx(
|
|
28
|
+
"input",
|
|
29
|
+
{
|
|
30
|
+
...attributes,
|
|
31
|
+
id: inputId,
|
|
32
|
+
disabled,
|
|
33
|
+
className: inputClasses.join(" "),
|
|
34
|
+
required: optional,
|
|
35
|
+
"aria-required": optional,
|
|
36
|
+
maxLength: length,
|
|
37
|
+
type: "text"
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
TextInput
|
|
45
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type BaseInputProps = {
|
|
2
|
+
inputId?: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
optional?: boolean;
|
|
6
|
+
error?: boolean;
|
|
7
|
+
attributes?: JSX.IntrinsicElements['input'];
|
|
8
|
+
};
|
|
9
|
+
interface TextInputProps extends FormFieldProps {
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
length?: 2 | 3 | 4 | 5;
|
|
12
|
+
feedback?: FeedbackProps;
|
|
13
|
+
}
|
|
14
|
+
interface CheckBoxProps extends BaseInputProps {
|
|
15
|
+
inputId: string;
|
|
16
|
+
checkboxLabel: string;
|
|
17
|
+
}
|
|
18
|
+
interface FormFieldsetProps {
|
|
19
|
+
label: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
children: JSX.Element | JSX.Element[];
|
|
22
|
+
feedback?: FeedbackProps;
|
|
23
|
+
}
|
|
24
|
+
interface FormFieldProps extends BaseInputProps {
|
|
25
|
+
feedback?: FeedbackProps;
|
|
26
|
+
children: JSX.Element & JSX.IntrinsicElements['input'];
|
|
27
|
+
}
|
|
28
|
+
type FeedbackProps = {
|
|
29
|
+
errorElementIds?: string[];
|
|
30
|
+
message: string;
|
|
31
|
+
type: 'error';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type { CheckBoxProps as C, FeedbackProps as F, TextInputProps as T, FormFieldProps as a, FormFieldsetProps as b };
|
package/esm/index.d.ts
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { F as FeedbackProps, a as FormFieldProps, b as FormFieldsetProps } from './index-BP51ZwQo.js';
|
|
3
|
+
export { CheckBox, CheckBoxGroup, CheckBoxItem } from './CheckBox.js';
|
|
2
4
|
|
|
3
|
-
type
|
|
4
|
-
inputId?: string;
|
|
5
|
-
label?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
optional?: boolean;
|
|
8
|
-
error?: string;
|
|
9
|
-
attributes?: JSX.IntrinsicElements['input'];
|
|
10
|
-
};
|
|
11
|
-
interface FormFieldProps extends BaseInputProps {
|
|
12
|
-
feedback?: FeedBackProps;
|
|
13
|
-
children: JSX.Element & JSX.IntrinsicElements['input'];
|
|
14
|
-
}
|
|
15
|
-
interface FormFieldsetProps {
|
|
16
|
-
label: string;
|
|
17
|
-
description?: string;
|
|
18
|
-
error?: string;
|
|
19
|
-
children: JSX.Element | JSX.Element[];
|
|
20
|
-
feedback?: FeedBackProps;
|
|
21
|
-
}
|
|
22
|
-
interface FormFieldsetProps {
|
|
23
|
-
label: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
error?: string;
|
|
26
|
-
children: JSX.Element | JSX.Element[];
|
|
27
|
-
}
|
|
28
|
-
type FeedBackProps = {
|
|
29
|
-
message: string;
|
|
30
|
-
type: 'error';
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
declare const Feedback: ({ message, type }: FeedBackProps) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare const Feedback: ({ message, type }: FeedbackProps) => react_jsx_runtime.JSX.Element;
|
|
34
6
|
|
|
35
7
|
declare const LabeledFormField: ({ inputId, label, description, feedback, children, optional, }: FormFieldProps) => react_jsx_runtime.JSX.Element;
|
|
36
8
|
declare const TitledFormField: ({ label, description, feedback, children, optional, }: FormFieldProps) => react_jsx_runtime.JSX.Element;
|
package/esm/index.js
CHANGED