@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 CHANGED
@@ -1 +1,108 @@
1
1
  # o3-form[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](#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 };
@@ -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 };
@@ -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 BaseInputProps = {
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-field__feedback--error {
13
- color: var(--o3-color-use-case-error);
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
- font-weight: 500;
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
- fieldset.o3-form-field {
21
- margin: 0;
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
- fieldset.o3-form-field legend {
26
- margin: 0;
27
- padding: 0;
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 */
@@ -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 };
@@ -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 };
@@ -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 BaseInputProps = {
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
@@ -1,3 +1,4 @@
1
1
  export * from "./fieldComponents/Feedback";
2
2
  export * from "./fieldComponents/FormField";
3
3
  export * from "./fieldComponents/Form";
4
+ export * from "./CheckBox";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/o3-form",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Provides a viewport-aware tooltip for annotating or or highlighting other aspects of a product's UI",
5
5
  "keywords": [
6
6
  "form",