@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 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://bitbucket.org/brighte-energy/energy/src/14a694872cc43bb454981bada65f5f12b56f77c9/spark-web/packages/utils-spark/src/buildDataAttributes.ts#spark-web/packages/utils-spark/src/buildDataAttributes.ts-1
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 FieldContextType = {
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 fieldContext = {
60
- 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
61
- id: inputId,
58
+ var invalid = Boolean(message && tone === 'critical');
59
+ var fieldContext = [{
62
60
  disabled: disabled,
63
- invalid: Boolean(message && tone === 'critical')
64
- }; // label prep
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: "strong",
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, _objectSpread(_objectSpread({
99
- gap: labelVisibility === 'hidden' ? undefined : 'small',
100
- ref: forwardedRef
101
- }, data ? internal.buildDataAttributes(data) : null), {}, {
102
- children: [/*#__PURE__*/jsxRuntime.jsxs(box.Box, {
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(_ref2) {
148
- var message = _ref2.message,
149
- id = _ref2.id,
150
- tone = _ref2.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(_ref3) {
171
- var children = _ref3.children,
172
- props = _objectWithoutProperties(_ref3, _excluded);
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 fieldContext = {
60
- 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
61
- id: inputId,
58
+ var invalid = Boolean(message && tone === 'critical');
59
+ var fieldContext = [{
62
60
  disabled: disabled,
63
- invalid: Boolean(message && tone === 'critical')
64
- }; // label prep
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: "strong",
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, _objectSpread(_objectSpread({
99
- gap: labelVisibility === 'hidden' ? undefined : 'small',
100
- ref: forwardedRef
101
- }, data ? internal.buildDataAttributes(data) : null), {}, {
102
- children: [/*#__PURE__*/jsxRuntime.jsxs(box.Box, {
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(_ref2) {
148
- var message = _ref2.message,
149
- id = _ref2.id,
150
- tone = _ref2.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(_ref3) {
171
- var children = _ref3.children,
172
- props = _objectWithoutProperties(_ref3, _excluded);
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 fieldContext = {
56
- 'aria-describedby': mergeIds(message && messageId, description && descriptionId),
57
- id: inputId,
54
+ var invalid = Boolean(message && tone === 'critical');
55
+ var fieldContext = [{
58
56
  disabled: disabled,
59
- invalid: Boolean(message && tone === 'critical')
60
- }; // label prep
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: "strong",
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, _objectSpread(_objectSpread({
95
- gap: labelVisibility === 'hidden' ? undefined : 'small',
96
- ref: forwardedRef
97
- }, data ? buildDataAttributes(data) : null), {}, {
98
- children: [/*#__PURE__*/jsxs(Box, {
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(_ref2) {
144
- var message = _ref2.message,
145
- id = _ref2.id,
146
- tone = _ref2.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(_ref3) {
167
- var children = _ref3.children,
168
- props = _objectWithoutProperties(_ref3, _excluded);
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": "1.0.3",
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.14.6",
9
- "@emotion/css": "^11.7.1",
10
- "@spark-web/a11y": "^1.0.3",
11
- "@spark-web/box": "^1.0.3",
12
- "@spark-web/icon": "^1.1.1",
13
- "@spark-web/stack": "^1.0.3",
14
- "@spark-web/text": "^1.0.3",
15
- "@spark-web/theme": "^2.0.2",
16
- "@spark-web/utils": "^1.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
- &nbsp;
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
- }
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export { useFieldContext } from './context';
2
- export { Field, FieldMessage, useFieldIds } from './Field';
3
-
4
- // types
5
-
6
- export type { FieldContextType } from './context';
7
- export type { FieldProps, Tone } from './Field';