@spark-web/field 1.0.3 → 2.0.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.
- package/README.md +1 -1
- package/dist/declarations/src/context.d.ts +7 -3
- package/dist/declarations/src/index.d.ts +2 -2
- package/dist/spark-web-field.cjs.dev.js +37 -27
- package/dist/spark-web-field.cjs.prod.js +37 -27
- package/dist/spark-web-field.esm.js +37 -28
- package/package.json +13 -10
- package/CHANGELOG.md +0 -79
- package/src/Field.tsx +0 -214
- package/src/context.ts +0 -24
- package/src/index.ts +0 -7
package/README.md
CHANGED
|
@@ -140,4 +140,4 @@ Mark the field as disabled by passing true to the disabled prop.
|
|
|
140
140
|
| tone? | 'critical' \| 'neutral' \| 'positive' | 'neutral' | Provide a tone to influence elements of the field, and its input. |
|
|
141
141
|
|
|
142
142
|
[data-attribute-map]:
|
|
143
|
-
https://
|
|
143
|
+
https://github.com/brighte-labs/spark-web/blob/e7f6f4285b4cfd876312cc89fbdd094039aa239a/packages/utils/src/internal/buildDataAttributes.ts#L1
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
export declare type
|
|
3
|
-
'aria-describedby'?: string;
|
|
4
|
-
id: string;
|
|
2
|
+
export declare type FieldState = {
|
|
5
3
|
disabled: boolean;
|
|
6
4
|
invalid: boolean;
|
|
7
5
|
};
|
|
6
|
+
export declare type InputPropsDerivedFromField = {
|
|
7
|
+
'aria-describedby'?: string;
|
|
8
|
+
'aria-invalid': true | undefined;
|
|
9
|
+
id: string;
|
|
10
|
+
};
|
|
11
|
+
export declare type FieldContextType = [FieldState, InputPropsDerivedFromField];
|
|
8
12
|
export declare const FieldContext: import("react").Context<FieldContextType | null>;
|
|
9
13
|
export declare const FieldContextProvider: import("react").Provider<FieldContextType | null>;
|
|
10
14
|
export declare const FIELD_CONTEXT_ERROR_MESSAGE = "Input components must be inside a `Field`.";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useFieldContext } from './context';
|
|
1
|
+
export { FieldContextProvider, useFieldContext } from './context';
|
|
2
2
|
export { Field, FieldMessage, useFieldIds } from './Field';
|
|
3
|
-
export type { FieldContextType } from './context';
|
|
3
|
+
export type { FieldContextType, FieldState, InputPropsDerivedFromField, } from './context';
|
|
4
4
|
export type { FieldProps, Tone } from './Field';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
|
-
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
6
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
7
|
+
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
8
8
|
var css = require('@emotion/css');
|
|
9
9
|
var a11y = require('@spark-web/a11y');
|
|
10
10
|
var box = require('@spark-web/box');
|
|
@@ -12,7 +12,6 @@ var icon = require('@spark-web/icon');
|
|
|
12
12
|
var stack = require('@spark-web/stack');
|
|
13
13
|
var text = require('@spark-web/text');
|
|
14
14
|
var theme = require('@spark-web/theme');
|
|
15
|
-
var internal = require('@spark-web/utils/internal');
|
|
16
15
|
var jsxRuntime = require('react/jsx-runtime');
|
|
17
16
|
|
|
18
17
|
var FieldContext = /*#__PURE__*/react.createContext(null);
|
|
@@ -56,12 +55,15 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
56
55
|
messageId = _useFieldIds.messageId; // field context
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
id: inputId,
|
|
58
|
+
var invalid = Boolean(message && tone === 'critical');
|
|
59
|
+
var fieldContext = [{
|
|
62
60
|
disabled: disabled,
|
|
63
|
-
invalid:
|
|
64
|
-
}
|
|
61
|
+
invalid: invalid
|
|
62
|
+
}, {
|
|
63
|
+
'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
|
|
64
|
+
'aria-invalid': invalid || undefined,
|
|
65
|
+
id: inputId
|
|
66
|
+
}]; // label prep
|
|
65
67
|
|
|
66
68
|
var hiddenLabel = /*#__PURE__*/jsxRuntime.jsxs(a11y.VisuallyHidden, {
|
|
67
69
|
as: "label",
|
|
@@ -75,35 +77,31 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
75
77
|
as: "label",
|
|
76
78
|
htmlFor: inputId,
|
|
77
79
|
children: /*#__PURE__*/jsxRuntime.jsxs(text.Text, {
|
|
78
|
-
inline: true,
|
|
79
80
|
tone: disabled ? 'disabled' : 'neutral',
|
|
80
|
-
weight: "
|
|
81
|
+
weight: "semibold",
|
|
81
82
|
children: [label, ' ', secondaryLabel && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
82
83
|
inline: true,
|
|
83
84
|
tone: disabled ? 'disabled' : 'muted',
|
|
85
|
+
weight: "regular",
|
|
84
86
|
children: secondaryLabel
|
|
85
87
|
})]
|
|
86
88
|
})
|
|
87
89
|
}),
|
|
88
90
|
'reserve-space': /*#__PURE__*/jsxRuntime.jsxs(react.Fragment, {
|
|
89
91
|
children: [hiddenLabel, /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
90
|
-
inline: true,
|
|
91
92
|
"aria-hidden": true,
|
|
92
93
|
children: "\xA0"
|
|
93
94
|
})]
|
|
94
95
|
})
|
|
95
96
|
};
|
|
97
|
+
var LabelWrapper = labelVisibility === 'hidden' ? react.Fragment : FieldLabelWrapper;
|
|
96
98
|
return /*#__PURE__*/jsxRuntime.jsx(FieldContextProvider, {
|
|
97
99
|
value: fieldContext,
|
|
98
|
-
children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
children: [/*#__PURE__*/jsxRuntime.jsxs(
|
|
103
|
-
display: "flex",
|
|
104
|
-
alignItems: "center",
|
|
105
|
-
justifyContent: "spaceBetween",
|
|
106
|
-
gap: "large",
|
|
100
|
+
children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, {
|
|
101
|
+
ref: forwardedRef,
|
|
102
|
+
data: data,
|
|
103
|
+
gap: "medium",
|
|
104
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs(LabelWrapper, {
|
|
107
105
|
children: [labelElement[labelVisibility], adornment]
|
|
108
106
|
}), description && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
109
107
|
tone: "muted",
|
|
@@ -115,7 +113,7 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
115
113
|
id: messageId,
|
|
116
114
|
message: message
|
|
117
115
|
})]
|
|
118
|
-
})
|
|
116
|
+
})
|
|
119
117
|
});
|
|
120
118
|
});
|
|
121
119
|
Field.displayName = 'Field'; // Utils
|
|
@@ -133,6 +131,17 @@ function useFieldIds(id) {
|
|
|
133
131
|
} // Styled components
|
|
134
132
|
// ------------------------------
|
|
135
133
|
|
|
134
|
+
function FieldLabelWrapper(_ref2) {
|
|
135
|
+
var children = _ref2.children;
|
|
136
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
137
|
+
display: "flex",
|
|
138
|
+
alignItems: "center",
|
|
139
|
+
justifyContent: "spaceBetween",
|
|
140
|
+
gap: "large",
|
|
141
|
+
children: children
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
136
145
|
var messageToneMap = {
|
|
137
146
|
critical: 'critical',
|
|
138
147
|
neutral: 'muted',
|
|
@@ -144,10 +153,10 @@ var messageIconMap = {
|
|
|
144
153
|
neutral: null,
|
|
145
154
|
positive: icon.CheckCircleIcon
|
|
146
155
|
};
|
|
147
|
-
var FieldMessage = function FieldMessage(
|
|
148
|
-
var message =
|
|
149
|
-
id =
|
|
150
|
-
tone =
|
|
156
|
+
var FieldMessage = function FieldMessage(_ref3) {
|
|
157
|
+
var message = _ref3.message,
|
|
158
|
+
id = _ref3.id,
|
|
159
|
+
tone = _ref3.tone;
|
|
151
160
|
var textTone = messageToneMap[tone];
|
|
152
161
|
var Icon = messageIconMap[tone];
|
|
153
162
|
return /*#__PURE__*/jsxRuntime.jsxs(box.Box, {
|
|
@@ -167,9 +176,9 @@ var FieldMessage = function FieldMessage(_ref2) {
|
|
|
167
176
|
});
|
|
168
177
|
};
|
|
169
178
|
|
|
170
|
-
function IndicatorContainer(
|
|
171
|
-
var children =
|
|
172
|
-
props = _objectWithoutProperties(
|
|
179
|
+
function IndicatorContainer(_ref4) {
|
|
180
|
+
var children = _ref4.children,
|
|
181
|
+
props = _objectWithoutProperties(_ref4, _excluded);
|
|
173
182
|
|
|
174
183
|
var _useTheme = theme.useTheme(),
|
|
175
184
|
typography = _useTheme.typography,
|
|
@@ -199,6 +208,7 @@ function IndicatorContainer(_ref3) {
|
|
|
199
208
|
}
|
|
200
209
|
|
|
201
210
|
exports.Field = Field;
|
|
211
|
+
exports.FieldContextProvider = FieldContextProvider;
|
|
202
212
|
exports.FieldMessage = FieldMessage;
|
|
203
213
|
exports.useFieldContext = useFieldContext;
|
|
204
214
|
exports.useFieldIds = useFieldIds;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
|
-
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
6
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
7
|
+
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
8
8
|
var css = require('@emotion/css');
|
|
9
9
|
var a11y = require('@spark-web/a11y');
|
|
10
10
|
var box = require('@spark-web/box');
|
|
@@ -12,7 +12,6 @@ var icon = require('@spark-web/icon');
|
|
|
12
12
|
var stack = require('@spark-web/stack');
|
|
13
13
|
var text = require('@spark-web/text');
|
|
14
14
|
var theme = require('@spark-web/theme');
|
|
15
|
-
var internal = require('@spark-web/utils/internal');
|
|
16
15
|
var jsxRuntime = require('react/jsx-runtime');
|
|
17
16
|
|
|
18
17
|
var FieldContext = /*#__PURE__*/react.createContext(null);
|
|
@@ -56,12 +55,15 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
56
55
|
messageId = _useFieldIds.messageId; // field context
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
id: inputId,
|
|
58
|
+
var invalid = Boolean(message && tone === 'critical');
|
|
59
|
+
var fieldContext = [{
|
|
62
60
|
disabled: disabled,
|
|
63
|
-
invalid:
|
|
64
|
-
}
|
|
61
|
+
invalid: invalid
|
|
62
|
+
}, {
|
|
63
|
+
'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
|
|
64
|
+
'aria-invalid': invalid || undefined,
|
|
65
|
+
id: inputId
|
|
66
|
+
}]; // label prep
|
|
65
67
|
|
|
66
68
|
var hiddenLabel = /*#__PURE__*/jsxRuntime.jsxs(a11y.VisuallyHidden, {
|
|
67
69
|
as: "label",
|
|
@@ -75,35 +77,31 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
75
77
|
as: "label",
|
|
76
78
|
htmlFor: inputId,
|
|
77
79
|
children: /*#__PURE__*/jsxRuntime.jsxs(text.Text, {
|
|
78
|
-
inline: true,
|
|
79
80
|
tone: disabled ? 'disabled' : 'neutral',
|
|
80
|
-
weight: "
|
|
81
|
+
weight: "semibold",
|
|
81
82
|
children: [label, ' ', secondaryLabel && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
82
83
|
inline: true,
|
|
83
84
|
tone: disabled ? 'disabled' : 'muted',
|
|
85
|
+
weight: "regular",
|
|
84
86
|
children: secondaryLabel
|
|
85
87
|
})]
|
|
86
88
|
})
|
|
87
89
|
}),
|
|
88
90
|
'reserve-space': /*#__PURE__*/jsxRuntime.jsxs(react.Fragment, {
|
|
89
91
|
children: [hiddenLabel, /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
90
|
-
inline: true,
|
|
91
92
|
"aria-hidden": true,
|
|
92
93
|
children: "\xA0"
|
|
93
94
|
})]
|
|
94
95
|
})
|
|
95
96
|
};
|
|
97
|
+
var LabelWrapper = labelVisibility === 'hidden' ? react.Fragment : FieldLabelWrapper;
|
|
96
98
|
return /*#__PURE__*/jsxRuntime.jsx(FieldContextProvider, {
|
|
97
99
|
value: fieldContext,
|
|
98
|
-
children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
children: [/*#__PURE__*/jsxRuntime.jsxs(
|
|
103
|
-
display: "flex",
|
|
104
|
-
alignItems: "center",
|
|
105
|
-
justifyContent: "spaceBetween",
|
|
106
|
-
gap: "large",
|
|
100
|
+
children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, {
|
|
101
|
+
ref: forwardedRef,
|
|
102
|
+
data: data,
|
|
103
|
+
gap: "medium",
|
|
104
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs(LabelWrapper, {
|
|
107
105
|
children: [labelElement[labelVisibility], adornment]
|
|
108
106
|
}), description && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
|
|
109
107
|
tone: "muted",
|
|
@@ -115,7 +113,7 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
|
115
113
|
id: messageId,
|
|
116
114
|
message: message
|
|
117
115
|
})]
|
|
118
|
-
})
|
|
116
|
+
})
|
|
119
117
|
});
|
|
120
118
|
});
|
|
121
119
|
Field.displayName = 'Field'; // Utils
|
|
@@ -133,6 +131,17 @@ function useFieldIds(id) {
|
|
|
133
131
|
} // Styled components
|
|
134
132
|
// ------------------------------
|
|
135
133
|
|
|
134
|
+
function FieldLabelWrapper(_ref2) {
|
|
135
|
+
var children = _ref2.children;
|
|
136
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
137
|
+
display: "flex",
|
|
138
|
+
alignItems: "center",
|
|
139
|
+
justifyContent: "spaceBetween",
|
|
140
|
+
gap: "large",
|
|
141
|
+
children: children
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
136
145
|
var messageToneMap = {
|
|
137
146
|
critical: 'critical',
|
|
138
147
|
neutral: 'muted',
|
|
@@ -144,10 +153,10 @@ var messageIconMap = {
|
|
|
144
153
|
neutral: null,
|
|
145
154
|
positive: icon.CheckCircleIcon
|
|
146
155
|
};
|
|
147
|
-
var FieldMessage = function FieldMessage(
|
|
148
|
-
var message =
|
|
149
|
-
id =
|
|
150
|
-
tone =
|
|
156
|
+
var FieldMessage = function FieldMessage(_ref3) {
|
|
157
|
+
var message = _ref3.message,
|
|
158
|
+
id = _ref3.id,
|
|
159
|
+
tone = _ref3.tone;
|
|
151
160
|
var textTone = messageToneMap[tone];
|
|
152
161
|
var Icon = messageIconMap[tone];
|
|
153
162
|
return /*#__PURE__*/jsxRuntime.jsxs(box.Box, {
|
|
@@ -167,9 +176,9 @@ var FieldMessage = function FieldMessage(_ref2) {
|
|
|
167
176
|
});
|
|
168
177
|
};
|
|
169
178
|
|
|
170
|
-
function IndicatorContainer(
|
|
171
|
-
var children =
|
|
172
|
-
props = _objectWithoutProperties(
|
|
179
|
+
function IndicatorContainer(_ref4) {
|
|
180
|
+
var children = _ref4.children,
|
|
181
|
+
props = _objectWithoutProperties(_ref4, _excluded);
|
|
173
182
|
|
|
174
183
|
var _useTheme = theme.useTheme(),
|
|
175
184
|
typography = _useTheme.typography,
|
|
@@ -199,6 +208,7 @@ function IndicatorContainer(_ref3) {
|
|
|
199
208
|
}
|
|
200
209
|
|
|
201
210
|
exports.Field = Field;
|
|
211
|
+
exports.FieldContextProvider = FieldContextProvider;
|
|
202
212
|
exports.FieldMessage = FieldMessage;
|
|
203
213
|
exports.useFieldContext = useFieldContext;
|
|
204
214
|
exports.useFieldIds = useFieldIds;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createContext, useContext, forwardRef, Fragment } from 'react';
|
|
2
|
-
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
|
|
3
2
|
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
|
3
|
+
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
|
|
4
4
|
import { css } from '@emotion/css';
|
|
5
5
|
import { mergeIds, useId, composeId, VisuallyHidden } from '@spark-web/a11y';
|
|
6
6
|
import { Box } from '@spark-web/box';
|
|
@@ -8,7 +8,6 @@ import { ExclamationCircleIcon, CheckCircleIcon } from '@spark-web/icon';
|
|
|
8
8
|
import { Stack } from '@spark-web/stack';
|
|
9
9
|
import { Text } from '@spark-web/text';
|
|
10
10
|
import { useTheme } from '@spark-web/theme';
|
|
11
|
-
import { buildDataAttributes } from '@spark-web/utils/internal';
|
|
12
11
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
13
12
|
|
|
14
13
|
var FieldContext = /*#__PURE__*/createContext(null);
|
|
@@ -52,12 +51,15 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
|
52
51
|
messageId = _useFieldIds.messageId; // field context
|
|
53
52
|
|
|
54
53
|
|
|
55
|
-
var
|
|
56
|
-
|
|
57
|
-
id: inputId,
|
|
54
|
+
var invalid = Boolean(message && tone === 'critical');
|
|
55
|
+
var fieldContext = [{
|
|
58
56
|
disabled: disabled,
|
|
59
|
-
invalid:
|
|
60
|
-
}
|
|
57
|
+
invalid: invalid
|
|
58
|
+
}, {
|
|
59
|
+
'aria-describedby': mergeIds(message && messageId, description && descriptionId),
|
|
60
|
+
'aria-invalid': invalid || undefined,
|
|
61
|
+
id: inputId
|
|
62
|
+
}]; // label prep
|
|
61
63
|
|
|
62
64
|
var hiddenLabel = /*#__PURE__*/jsxs(VisuallyHidden, {
|
|
63
65
|
as: "label",
|
|
@@ -71,35 +73,31 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
|
71
73
|
as: "label",
|
|
72
74
|
htmlFor: inputId,
|
|
73
75
|
children: /*#__PURE__*/jsxs(Text, {
|
|
74
|
-
inline: true,
|
|
75
76
|
tone: disabled ? 'disabled' : 'neutral',
|
|
76
|
-
weight: "
|
|
77
|
+
weight: "semibold",
|
|
77
78
|
children: [label, ' ', secondaryLabel && /*#__PURE__*/jsx(Text, {
|
|
78
79
|
inline: true,
|
|
79
80
|
tone: disabled ? 'disabled' : 'muted',
|
|
81
|
+
weight: "regular",
|
|
80
82
|
children: secondaryLabel
|
|
81
83
|
})]
|
|
82
84
|
})
|
|
83
85
|
}),
|
|
84
86
|
'reserve-space': /*#__PURE__*/jsxs(Fragment, {
|
|
85
87
|
children: [hiddenLabel, /*#__PURE__*/jsx(Text, {
|
|
86
|
-
inline: true,
|
|
87
88
|
"aria-hidden": true,
|
|
88
89
|
children: "\xA0"
|
|
89
90
|
})]
|
|
90
91
|
})
|
|
91
92
|
};
|
|
93
|
+
var LabelWrapper = labelVisibility === 'hidden' ? Fragment : FieldLabelWrapper;
|
|
92
94
|
return /*#__PURE__*/jsx(FieldContextProvider, {
|
|
93
95
|
value: fieldContext,
|
|
94
|
-
children: /*#__PURE__*/jsxs(Stack,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
children: [/*#__PURE__*/jsxs(
|
|
99
|
-
display: "flex",
|
|
100
|
-
alignItems: "center",
|
|
101
|
-
justifyContent: "spaceBetween",
|
|
102
|
-
gap: "large",
|
|
96
|
+
children: /*#__PURE__*/jsxs(Stack, {
|
|
97
|
+
ref: forwardedRef,
|
|
98
|
+
data: data,
|
|
99
|
+
gap: "medium",
|
|
100
|
+
children: [/*#__PURE__*/jsxs(LabelWrapper, {
|
|
103
101
|
children: [labelElement[labelVisibility], adornment]
|
|
104
102
|
}), description && /*#__PURE__*/jsx(Text, {
|
|
105
103
|
tone: "muted",
|
|
@@ -111,7 +109,7 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
|
111
109
|
id: messageId,
|
|
112
110
|
message: message
|
|
113
111
|
})]
|
|
114
|
-
})
|
|
112
|
+
})
|
|
115
113
|
});
|
|
116
114
|
});
|
|
117
115
|
Field.displayName = 'Field'; // Utils
|
|
@@ -129,6 +127,17 @@ function useFieldIds(id) {
|
|
|
129
127
|
} // Styled components
|
|
130
128
|
// ------------------------------
|
|
131
129
|
|
|
130
|
+
function FieldLabelWrapper(_ref2) {
|
|
131
|
+
var children = _ref2.children;
|
|
132
|
+
return /*#__PURE__*/jsx(Box, {
|
|
133
|
+
display: "flex",
|
|
134
|
+
alignItems: "center",
|
|
135
|
+
justifyContent: "spaceBetween",
|
|
136
|
+
gap: "large",
|
|
137
|
+
children: children
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
132
141
|
var messageToneMap = {
|
|
133
142
|
critical: 'critical',
|
|
134
143
|
neutral: 'muted',
|
|
@@ -140,10 +149,10 @@ var messageIconMap = {
|
|
|
140
149
|
neutral: null,
|
|
141
150
|
positive: CheckCircleIcon
|
|
142
151
|
};
|
|
143
|
-
var FieldMessage = function FieldMessage(
|
|
144
|
-
var message =
|
|
145
|
-
id =
|
|
146
|
-
tone =
|
|
152
|
+
var FieldMessage = function FieldMessage(_ref3) {
|
|
153
|
+
var message = _ref3.message,
|
|
154
|
+
id = _ref3.id,
|
|
155
|
+
tone = _ref3.tone;
|
|
147
156
|
var textTone = messageToneMap[tone];
|
|
148
157
|
var Icon = messageIconMap[tone];
|
|
149
158
|
return /*#__PURE__*/jsxs(Box, {
|
|
@@ -163,9 +172,9 @@ var FieldMessage = function FieldMessage(_ref2) {
|
|
|
163
172
|
});
|
|
164
173
|
};
|
|
165
174
|
|
|
166
|
-
function IndicatorContainer(
|
|
167
|
-
var children =
|
|
168
|
-
props = _objectWithoutProperties(
|
|
175
|
+
function IndicatorContainer(_ref4) {
|
|
176
|
+
var children = _ref4.children,
|
|
177
|
+
props = _objectWithoutProperties(_ref4, _excluded);
|
|
169
178
|
|
|
170
179
|
var _useTheme = useTheme(),
|
|
171
180
|
typography = _useTheme.typography,
|
|
@@ -194,4 +203,4 @@ function IndicatorContainer(_ref3) {
|
|
|
194
203
|
}));
|
|
195
204
|
}
|
|
196
205
|
|
|
197
|
-
export { Field, FieldMessage, useFieldContext, useFieldIds };
|
|
206
|
+
export { Field, FieldContextProvider, FieldMessage, useFieldContext, useFieldIds };
|
package/package.json
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spark-web/field",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/spark-web-field.cjs.js",
|
|
6
6
|
"module": "dist/spark-web-field.esm.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
7
10
|
"dependencies": {
|
|
8
|
-
"@babel/runtime": "^7.
|
|
9
|
-
"@emotion/css": "^11.
|
|
10
|
-
"@spark-web/a11y": "^1.0.
|
|
11
|
-
"@spark-web/box": "^1.0.
|
|
12
|
-
"@spark-web/icon": "^1.1.
|
|
13
|
-
"@spark-web/stack": "^1.0.
|
|
14
|
-
"@spark-web/text": "^1.0.
|
|
15
|
-
"@spark-web/theme": "^
|
|
16
|
-
"@spark-web/utils": "^1.1.
|
|
11
|
+
"@babel/runtime": "^7.18.0",
|
|
12
|
+
"@emotion/css": "^11.9.0",
|
|
13
|
+
"@spark-web/a11y": "^1.0.5",
|
|
14
|
+
"@spark-web/box": "^1.0.5",
|
|
15
|
+
"@spark-web/icon": "^1.1.3",
|
|
16
|
+
"@spark-web/stack": "^1.0.5",
|
|
17
|
+
"@spark-web/text": "^1.0.5",
|
|
18
|
+
"@spark-web/theme": "^3.0.1",
|
|
19
|
+
"@spark-web/utils": "^1.1.4"
|
|
17
20
|
},
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"@types/react": "^17.0.12",
|
package/CHANGELOG.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# @spark-web/field
|
|
2
|
-
|
|
3
|
-
## 1.0.3
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- [#42](https://github.com/brighte-labs/spark-web/pull/42)
|
|
8
|
-
[`435779a`](https://github.com/brighte-labs/spark-web/commit/435779aa42bd635bbf43e1fd41724c666402caa2)
|
|
9
|
-
Thanks [@lukebennett88](https://github.com/lukebennett88)! - Prevent multiple
|
|
10
|
-
versions of React
|
|
11
|
-
|
|
12
|
-
- Updated dependencies
|
|
13
|
-
[[`435779a`](https://github.com/brighte-labs/spark-web/commit/435779aa42bd635bbf43e1fd41724c666402caa2)]:
|
|
14
|
-
- @spark-web/a11y@1.0.3
|
|
15
|
-
- @spark-web/box@1.0.3
|
|
16
|
-
- @spark-web/icon@1.1.1
|
|
17
|
-
- @spark-web/stack@1.0.3
|
|
18
|
-
- @spark-web/text@1.0.3
|
|
19
|
-
- @spark-web/theme@2.0.2
|
|
20
|
-
- @spark-web/utils@1.1.1
|
|
21
|
-
|
|
22
|
-
## 1.0.2
|
|
23
|
-
|
|
24
|
-
### Patch Changes
|
|
25
|
-
|
|
26
|
-
- [#40](https://github.com/brighte-labs/spark-web/pull/40)
|
|
27
|
-
[`062c8ab`](https://github.com/brighte-labs/spark-web/commit/062c8ab8c7b4120f8d14c269b5f7801288c678ca)
|
|
28
|
-
Thanks [@lukebennett88](https://github.com/lukebennett88)! - Add
|
|
29
|
-
@babel/transform-runtime
|
|
30
|
-
|
|
31
|
-
- Updated dependencies
|
|
32
|
-
[[`062c8ab`](https://github.com/brighte-labs/spark-web/commit/062c8ab8c7b4120f8d14c269b5f7801288c678ca)]:
|
|
33
|
-
- @spark-web/a11y@1.0.2
|
|
34
|
-
- @spark-web/box@1.0.2
|
|
35
|
-
- @spark-web/icon@1.0.2
|
|
36
|
-
- @spark-web/stack@1.0.2
|
|
37
|
-
- @spark-web/text@1.0.2
|
|
38
|
-
- @spark-web/theme@2.0.1
|
|
39
|
-
- @spark-web/utils@1.0.2
|
|
40
|
-
|
|
41
|
-
## 1.0.1
|
|
42
|
-
|
|
43
|
-
### Patch Changes
|
|
44
|
-
|
|
45
|
-
- [#36](https://github.com/brighte-labs/spark-web/pull/36)
|
|
46
|
-
[`8546f8f`](https://github.com/brighte-labs/spark-web/commit/8546f8f05daaa79ea3ff954c6c4928a7a2d0622d)
|
|
47
|
-
Thanks [@lukebennett88](https://github.com/lukebennett88)! - Update Babel
|
|
48
|
-
config
|
|
49
|
-
|
|
50
|
-
- Updated dependencies
|
|
51
|
-
[[`aebff30`](https://github.com/brighte-labs/spark-web/commit/aebff30c86cb0a9db22b545c46159ce0d1c14afb),
|
|
52
|
-
[`8546f8f`](https://github.com/brighte-labs/spark-web/commit/8546f8f05daaa79ea3ff954c6c4928a7a2d0622d)]:
|
|
53
|
-
- @spark-web/theme@2.0.0
|
|
54
|
-
- @spark-web/a11y@1.0.1
|
|
55
|
-
- @spark-web/box@1.0.1
|
|
56
|
-
- @spark-web/icon@1.0.1
|
|
57
|
-
- @spark-web/stack@1.0.1
|
|
58
|
-
- @spark-web/text@1.0.1
|
|
59
|
-
- @spark-web/utils@1.0.1
|
|
60
|
-
|
|
61
|
-
## 1.0.0
|
|
62
|
-
|
|
63
|
-
### Major Changes
|
|
64
|
-
|
|
65
|
-
- [#27](https://github.com/brighte-labs/spark-web/pull/27)
|
|
66
|
-
[`4c8e398`](https://github.com/brighte-labs/spark-web/commit/4c8e3988f8a59d3dab60a6b67b1128b6ff2a5f2c)
|
|
67
|
-
Thanks [@JedWatson](https://github.com/JedWatson)! - Initial Version
|
|
68
|
-
|
|
69
|
-
### Patch Changes
|
|
70
|
-
|
|
71
|
-
- Updated dependencies
|
|
72
|
-
[[`4c8e398`](https://github.com/brighte-labs/spark-web/commit/4c8e3988f8a59d3dab60a6b67b1128b6ff2a5f2c)]:
|
|
73
|
-
- @spark-web/a11y@1.0.0
|
|
74
|
-
- @spark-web/box@1.0.0
|
|
75
|
-
- @spark-web/icon@1.0.0
|
|
76
|
-
- @spark-web/stack@1.0.0
|
|
77
|
-
- @spark-web/text@1.0.0
|
|
78
|
-
- @spark-web/theme@1.0.0
|
|
79
|
-
- @spark-web/utils@1.0.0
|
package/src/Field.tsx
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/css';
|
|
2
|
-
import { composeId, mergeIds, useId, VisuallyHidden } from '@spark-web/a11y';
|
|
3
|
-
import { Box } from '@spark-web/box';
|
|
4
|
-
import { CheckCircleIcon, ExclamationCircleIcon } from '@spark-web/icon';
|
|
5
|
-
import { Stack } from '@spark-web/stack';
|
|
6
|
-
import { Text } from '@spark-web/text';
|
|
7
|
-
import { useTheme } from '@spark-web/theme';
|
|
8
|
-
import type { DataAttributeMap } from '@spark-web/utils/internal';
|
|
9
|
-
import { buildDataAttributes } from '@spark-web/utils/internal';
|
|
10
|
-
import type { ReactElement, ReactNode } from 'react';
|
|
11
|
-
import { forwardRef, Fragment } from 'react';
|
|
12
|
-
|
|
13
|
-
import { FieldContextProvider } from './context';
|
|
14
|
-
|
|
15
|
-
export type Tone = keyof typeof messageToneMap;
|
|
16
|
-
|
|
17
|
-
export type FieldProps = {
|
|
18
|
-
id?: string;
|
|
19
|
-
data?: DataAttributeMap;
|
|
20
|
-
|
|
21
|
-
/** Optionally provide a utility or contextual hint, related to the field. */
|
|
22
|
-
adornment?: ReactElement;
|
|
23
|
-
/** Input component */
|
|
24
|
-
children: ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* Indicates that the field is perceivable but disabled, so it is not editable
|
|
27
|
-
* or otherwise operable.
|
|
28
|
-
*/
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
/** Provide additional information that will aid user input. */
|
|
31
|
-
description?: string;
|
|
32
|
-
/** Concisely label the field. */
|
|
33
|
-
label: string;
|
|
34
|
-
/**
|
|
35
|
-
* The label must always be provided for assistive technology, but you may
|
|
36
|
-
* hide it from sighted users when the intent can be inferred from context.
|
|
37
|
-
*/
|
|
38
|
-
labelVisibility?: 'hidden' | 'reserve-space' | 'visible';
|
|
39
|
-
/** Provide a message, informing the user about changes in state. */
|
|
40
|
-
message?: string;
|
|
41
|
-
/** Additional context, typically used to indicate that the field is optional. */
|
|
42
|
-
secondaryLabel?: string;
|
|
43
|
-
/** Provide a tone to influence elements of the field, and its input. */
|
|
44
|
-
tone?: Tone;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Using a [context](https://reactjs.org/docs/context.html), the field
|
|
49
|
-
* component connects the label, description, and message to the input element.
|
|
50
|
-
*/
|
|
51
|
-
export const Field = forwardRef<HTMLDivElement, FieldProps>(
|
|
52
|
-
(
|
|
53
|
-
{
|
|
54
|
-
children,
|
|
55
|
-
id: idProp,
|
|
56
|
-
data,
|
|
57
|
-
|
|
58
|
-
description,
|
|
59
|
-
disabled = false,
|
|
60
|
-
label,
|
|
61
|
-
adornment,
|
|
62
|
-
labelVisibility = 'visible',
|
|
63
|
-
message,
|
|
64
|
-
secondaryLabel,
|
|
65
|
-
tone = 'neutral',
|
|
66
|
-
},
|
|
67
|
-
forwardedRef
|
|
68
|
-
) => {
|
|
69
|
-
const { descriptionId, inputId, messageId } = useFieldIds(idProp);
|
|
70
|
-
|
|
71
|
-
// field context
|
|
72
|
-
const fieldContext = {
|
|
73
|
-
'aria-describedby': mergeIds(
|
|
74
|
-
message && messageId,
|
|
75
|
-
description && descriptionId
|
|
76
|
-
),
|
|
77
|
-
id: inputId,
|
|
78
|
-
disabled,
|
|
79
|
-
invalid: Boolean(message && tone === 'critical'),
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// label prep
|
|
83
|
-
const hiddenLabel = (
|
|
84
|
-
<VisuallyHidden as="label" htmlFor={inputId}>
|
|
85
|
-
{label} {secondaryLabel}
|
|
86
|
-
</VisuallyHidden>
|
|
87
|
-
);
|
|
88
|
-
const labelElement = {
|
|
89
|
-
hidden: hiddenLabel,
|
|
90
|
-
visible: (
|
|
91
|
-
<Box as="label" htmlFor={inputId}>
|
|
92
|
-
<Text inline tone={disabled ? 'disabled' : 'neutral'} weight="strong">
|
|
93
|
-
{label}{' '}
|
|
94
|
-
{secondaryLabel && (
|
|
95
|
-
<Text inline tone={disabled ? 'disabled' : 'muted'}>
|
|
96
|
-
{secondaryLabel}
|
|
97
|
-
</Text>
|
|
98
|
-
)}
|
|
99
|
-
</Text>
|
|
100
|
-
</Box>
|
|
101
|
-
),
|
|
102
|
-
'reserve-space': (
|
|
103
|
-
<Fragment>
|
|
104
|
-
{hiddenLabel}
|
|
105
|
-
<Text inline aria-hidden>
|
|
106
|
-
|
|
107
|
-
</Text>
|
|
108
|
-
</Fragment>
|
|
109
|
-
),
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<FieldContextProvider value={fieldContext}>
|
|
114
|
-
<Stack
|
|
115
|
-
gap={labelVisibility === 'hidden' ? undefined : 'small'}
|
|
116
|
-
ref={forwardedRef}
|
|
117
|
-
{...(data ? buildDataAttributes(data) : null)}
|
|
118
|
-
>
|
|
119
|
-
<Box
|
|
120
|
-
display="flex"
|
|
121
|
-
alignItems="center"
|
|
122
|
-
justifyContent="spaceBetween"
|
|
123
|
-
gap="large"
|
|
124
|
-
>
|
|
125
|
-
{labelElement[labelVisibility]}
|
|
126
|
-
{adornment}
|
|
127
|
-
</Box>
|
|
128
|
-
|
|
129
|
-
{description && (
|
|
130
|
-
<Text tone="muted" size="small" id={descriptionId}>
|
|
131
|
-
{description}
|
|
132
|
-
</Text>
|
|
133
|
-
)}
|
|
134
|
-
|
|
135
|
-
{children}
|
|
136
|
-
|
|
137
|
-
{message && (
|
|
138
|
-
<FieldMessage tone={tone} id={messageId} message={message} />
|
|
139
|
-
)}
|
|
140
|
-
</Stack>
|
|
141
|
-
</FieldContextProvider>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
);
|
|
145
|
-
Field.displayName = 'Field';
|
|
146
|
-
|
|
147
|
-
// Utils
|
|
148
|
-
// ------------------------------
|
|
149
|
-
|
|
150
|
-
export function useFieldIds(id?: string) {
|
|
151
|
-
const inputId = useId(id);
|
|
152
|
-
const descriptionId = composeId(inputId, 'description');
|
|
153
|
-
const messageId = composeId(inputId, 'message');
|
|
154
|
-
|
|
155
|
-
return { descriptionId, inputId, messageId };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Styled components
|
|
159
|
-
// ------------------------------
|
|
160
|
-
|
|
161
|
-
const messageToneMap = {
|
|
162
|
-
critical: 'critical',
|
|
163
|
-
neutral: 'muted',
|
|
164
|
-
positive: 'positive',
|
|
165
|
-
} as const;
|
|
166
|
-
|
|
167
|
-
// NOTE: use icons in addition to color for folks with visions issues
|
|
168
|
-
const messageIconMap = {
|
|
169
|
-
critical: ExclamationCircleIcon,
|
|
170
|
-
neutral: null,
|
|
171
|
-
positive: CheckCircleIcon,
|
|
172
|
-
} as const;
|
|
173
|
-
|
|
174
|
-
type FieldMessageProps = Required<Pick<FieldProps, 'message' | 'id' | 'tone'>>;
|
|
175
|
-
export const FieldMessage = ({ message, id, tone }: FieldMessageProps) => {
|
|
176
|
-
const textTone = messageToneMap[tone];
|
|
177
|
-
const Icon = messageIconMap[tone];
|
|
178
|
-
|
|
179
|
-
return (
|
|
180
|
-
<Box display="flex" gap="xsmall">
|
|
181
|
-
{Icon ? (
|
|
182
|
-
<IndicatorContainer>
|
|
183
|
-
<Icon size="xxsmall" tone={tone} />
|
|
184
|
-
</IndicatorContainer>
|
|
185
|
-
) : null}
|
|
186
|
-
<Text tone={textTone} size="small" id={id}>
|
|
187
|
-
{message}
|
|
188
|
-
</Text>
|
|
189
|
-
</Box>
|
|
190
|
-
);
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
function IndicatorContainer({ children, ...props }: { children: ReactNode }) {
|
|
194
|
-
const { typography, utils } = useTheme();
|
|
195
|
-
const { mobile, tablet } = typography.text.small;
|
|
196
|
-
const responsiveStyles = utils.responsiveStyles({
|
|
197
|
-
mobile: { height: mobile.capHeight },
|
|
198
|
-
tablet: { height: tablet.capHeight },
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
return (
|
|
202
|
-
<Box
|
|
203
|
-
display="flex"
|
|
204
|
-
alignItems="center"
|
|
205
|
-
aria-hidden
|
|
206
|
-
cursor="default"
|
|
207
|
-
flexShrink={0}
|
|
208
|
-
className={css(responsiveStyles)}
|
|
209
|
-
{...props}
|
|
210
|
-
>
|
|
211
|
-
{children}
|
|
212
|
-
</Box>
|
|
213
|
-
);
|
|
214
|
-
}
|
package/src/context.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
|
|
3
|
-
export type FieldContextType = {
|
|
4
|
-
'aria-describedby'?: string;
|
|
5
|
-
id: string;
|
|
6
|
-
disabled: boolean;
|
|
7
|
-
invalid: boolean;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const FieldContext = createContext<FieldContextType | null>(null);
|
|
11
|
-
export const FieldContextProvider = FieldContext.Provider;
|
|
12
|
-
|
|
13
|
-
export const FIELD_CONTEXT_ERROR_MESSAGE =
|
|
14
|
-
'Input components must be inside a `Field`.';
|
|
15
|
-
|
|
16
|
-
export function useFieldContext() {
|
|
17
|
-
const ctx = useContext(FieldContext);
|
|
18
|
-
|
|
19
|
-
if (!ctx) {
|
|
20
|
-
throw new Error(FIELD_CONTEXT_ERROR_MESSAGE);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return ctx;
|
|
24
|
-
}
|