@instructure/ui-form-field 11.6.0 → 11.6.1-snapshot-129
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/CHANGELOG.md +46 -300
- package/es/FormField/{index.js → v1/index.js} +1 -1
- package/es/FormField/v2/index.js +78 -0
- package/es/FormField/v2/props.js +26 -0
- package/es/FormFieldGroup/{index.js → v1/index.js} +5 -4
- package/es/FormFieldGroup/v2/index.js +130 -0
- package/es/FormFieldGroup/v2/props.js +26 -0
- package/es/FormFieldGroup/v2/styles.js +49 -0
- package/es/FormFieldLabel/{index.js → v1/index.js} +1 -1
- package/es/FormFieldLabel/v2/index.js +83 -0
- package/es/FormFieldLabel/v2/props.js +26 -0
- package/es/FormFieldLabel/v2/styles.js +62 -0
- package/es/FormFieldLabel/v2/theme.js +52 -0
- package/es/FormFieldLayout/{index.js → v1/index.js} +2 -2
- package/es/FormFieldLayout/{styles.js → v1/styles.js} +2 -2
- package/es/FormFieldLayout/v2/index.js +207 -0
- package/es/FormFieldLayout/v2/props.js +26 -0
- package/es/FormFieldLayout/v2/styles.js +171 -0
- package/es/FormFieldMessage/{index.js → v1/index.js} +1 -1
- package/es/FormFieldMessage/v2/index.js +96 -0
- package/es/FormFieldMessage/v2/props.js +26 -0
- package/es/FormFieldMessage/v2/styles.js +69 -0
- package/es/FormFieldMessages/{index.js → v1/index.js} +2 -2
- package/es/FormFieldMessages/v2/index.js +88 -0
- package/es/FormFieldMessages/v2/props.js +26 -0
- package/es/FormFieldMessages/v2/styles.js +50 -0
- package/es/{index.js → exports/a.js} +6 -6
- package/es/exports/b.js +29 -0
- package/lib/FormField/{index.js → v1/index.js} +3 -3
- package/lib/FormField/v2/index.js +85 -0
- package/lib/FormField/v2/props.js +31 -0
- package/lib/FormFieldGroup/{index.js → v1/index.js} +11 -10
- package/lib/FormFieldGroup/v2/index.js +136 -0
- package/lib/FormFieldGroup/v2/props.js +31 -0
- package/lib/FormFieldGroup/v2/styles.js +55 -0
- package/lib/FormFieldLabel/{index.js → v1/index.js} +1 -1
- package/lib/FormFieldLabel/v2/index.js +89 -0
- package/lib/FormFieldLabel/v2/props.js +31 -0
- package/lib/FormFieldLabel/v2/styles.js +68 -0
- package/lib/FormFieldLabel/v2/theme.js +58 -0
- package/lib/FormFieldLayout/{index.js → v1/index.js} +3 -3
- package/lib/FormFieldLayout/{styles.js → v1/styles.js} +1 -1
- package/lib/FormFieldLayout/v2/index.js +220 -0
- package/lib/FormFieldLayout/v2/props.js +31 -0
- package/lib/FormFieldLayout/v2/styles.js +177 -0
- package/lib/FormFieldMessage/{index.js → v1/index.js} +2 -2
- package/lib/FormFieldMessage/v2/index.js +101 -0
- package/lib/FormFieldMessage/v2/props.js +31 -0
- package/lib/FormFieldMessage/v2/styles.js +75 -0
- package/lib/FormFieldMessages/{index.js → v1/index.js} +3 -3
- package/lib/FormFieldMessages/v2/index.js +93 -0
- package/lib/FormFieldMessages/v2/props.js +31 -0
- package/lib/FormFieldMessages/v2/styles.js +56 -0
- package/lib/{index.js → exports/a.js} +12 -12
- package/lib/exports/b.js +47 -0
- package/package.json +43 -21
- package/src/FormField/{index.tsx → v1/index.tsx} +1 -1
- package/src/FormField/{props.ts → v1/props.ts} +1 -1
- package/src/FormField/v2/README.md +43 -0
- package/src/FormField/v2/index.tsx +87 -0
- package/src/FormField/v2/props.ts +104 -0
- package/src/FormFieldGroup/{index.tsx → v1/index.tsx} +6 -4
- package/src/FormFieldGroup/{props.ts → v1/props.ts} +2 -2
- package/src/FormFieldGroup/v2/README.md +114 -0
- package/src/FormFieldGroup/v2/index.tsx +182 -0
- package/src/FormFieldGroup/v2/props.ts +103 -0
- package/src/FormFieldGroup/v2/styles.ts +58 -0
- package/src/FormFieldLabel/{index.tsx → v1/index.tsx} +1 -1
- package/src/FormFieldLabel/v2/index.tsx +95 -0
- package/src/FormFieldLabel/v2/props.ts +49 -0
- package/src/FormFieldLabel/v2/styles.ts +74 -0
- package/src/FormFieldLabel/v2/theme.ts +56 -0
- package/src/FormFieldLayout/{index.tsx → v1/index.tsx} +2 -2
- package/src/FormFieldLayout/{props.ts → v1/props.ts} +1 -1
- package/src/FormFieldLayout/{styles.ts → v1/styles.ts} +2 -2
- package/src/FormFieldLayout/v2/index.tsx +237 -0
- package/src/FormFieldLayout/v2/props.ts +157 -0
- package/src/FormFieldLayout/v2/styles.ts +209 -0
- package/src/FormFieldMessage/{index.tsx → v1/index.tsx} +1 -1
- package/src/FormFieldMessage/{props.ts → v1/props.ts} +4 -1
- package/src/FormFieldMessage/{styles.ts → v1/styles.ts} +2 -3
- package/src/FormFieldMessage/v2/index.tsx +104 -0
- package/src/FormFieldMessage/v2/props.ts +48 -0
- package/src/FormFieldMessage/v2/styles.ts +76 -0
- package/src/FormFieldMessages/{index.tsx → v1/index.tsx} +2 -2
- package/src/FormFieldMessages/{props.ts → v1/props.ts} +1 -1
- package/src/FormFieldMessages/v2/index.tsx +99 -0
- package/src/FormFieldMessages/v2/props.ts +59 -0
- package/src/FormFieldMessages/v2/styles.ts +55 -0
- package/src/{index.ts → exports/a.ts} +17 -13
- package/src/exports/b.ts +43 -0
- package/tsconfig.build.json +1 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/FormField/v1/index.d.ts.map +1 -0
- package/types/FormField/{props.d.ts → v1/props.d.ts} +1 -1
- package/types/FormField/v1/props.d.ts.map +1 -0
- package/types/FormField/v2/index.d.ts +23 -0
- package/types/FormField/v2/index.d.ts.map +1 -0
- package/types/FormField/v2/props.d.ts +57 -0
- package/types/FormField/v2/props.d.ts.map +1 -0
- package/types/FormFieldGroup/{index.d.ts → v1/index.d.ts} +1 -1
- package/types/FormFieldGroup/v1/index.d.ts.map +1 -0
- package/types/FormFieldGroup/{props.d.ts → v1/props.d.ts} +2 -2
- package/types/FormFieldGroup/v1/props.d.ts.map +1 -0
- package/types/FormFieldGroup/v1/styles.d.ts.map +1 -0
- package/types/FormFieldGroup/v1/theme.d.ts.map +1 -0
- package/types/FormFieldGroup/v2/index.d.ts +45 -0
- package/types/FormFieldGroup/v2/index.d.ts.map +1 -0
- package/types/FormFieldGroup/v2/props.d.ts +48 -0
- package/types/FormFieldGroup/v2/props.d.ts.map +1 -0
- package/types/FormFieldGroup/v2/styles.d.ts +14 -0
- package/types/FormFieldGroup/v2/styles.d.ts.map +1 -0
- package/types/FormFieldLabel/v1/index.d.ts.map +1 -0
- package/types/FormFieldLabel/v1/props.d.ts.map +1 -0
- package/types/FormFieldLabel/v1/styles.d.ts.map +1 -0
- package/types/FormFieldLabel/v1/theme.d.ts.map +1 -0
- package/types/FormFieldLabel/v2/index.d.ts +38 -0
- package/types/FormFieldLabel/v2/index.d.ts.map +1 -0
- package/types/FormFieldLabel/v2/props.d.ts +14 -0
- package/types/FormFieldLabel/v2/props.d.ts.map +1 -0
- package/types/FormFieldLabel/v2/styles.d.ts +15 -0
- package/types/FormFieldLabel/v2/styles.d.ts.map +1 -0
- package/types/FormFieldLabel/v2/theme.d.ts +10 -0
- package/types/FormFieldLabel/v2/theme.d.ts.map +1 -0
- package/types/FormFieldLayout/v1/index.d.ts.map +1 -0
- package/types/FormFieldLayout/{props.d.ts → v1/props.d.ts} +1 -1
- package/types/FormFieldLayout/v1/props.d.ts.map +1 -0
- package/types/FormFieldLayout/v1/styles.d.ts.map +1 -0
- package/types/FormFieldLayout/v1/theme.d.ts.map +1 -0
- package/types/FormFieldLayout/v2/index.d.ts +14 -0
- package/types/FormFieldLayout/v2/index.d.ts.map +1 -0
- package/types/FormFieldLayout/v2/props.d.ts +90 -0
- package/types/FormFieldLayout/v2/props.d.ts.map +1 -0
- package/types/FormFieldLayout/v2/styles.d.ts +25 -0
- package/types/FormFieldLayout/v2/styles.d.ts.map +1 -0
- package/types/FormFieldMessage/{index.d.ts → v1/index.d.ts} +2 -2
- package/types/FormFieldMessage/v1/index.d.ts.map +1 -0
- package/types/FormFieldMessage/{props.d.ts → v1/props.d.ts} +1 -1
- package/types/FormFieldMessage/v1/props.d.ts.map +1 -0
- package/types/FormFieldMessage/v1/styles.d.ts.map +1 -0
- package/types/FormFieldMessage/v1/theme.d.ts.map +1 -0
- package/types/FormFieldMessage/v2/index.d.ts +24 -0
- package/types/FormFieldMessage/v2/index.d.ts.map +1 -0
- package/types/FormFieldMessage/v2/props.d.ts +16 -0
- package/types/FormFieldMessage/v2/props.d.ts.map +1 -0
- package/types/FormFieldMessage/v2/styles.d.ts +18 -0
- package/types/FormFieldMessage/v2/styles.d.ts.map +1 -0
- package/types/FormFieldMessages/{index.d.ts → v1/index.d.ts} +1 -1
- package/types/FormFieldMessages/v1/index.d.ts.map +1 -0
- package/types/FormFieldMessages/{props.d.ts → v1/props.d.ts} +1 -1
- package/types/FormFieldMessages/v1/props.d.ts.map +1 -0
- package/types/FormFieldMessages/v1/styles.d.ts.map +1 -0
- package/types/FormFieldMessages/v1/theme.d.ts.map +1 -0
- package/types/FormFieldMessages/v2/index.d.ts +36 -0
- package/types/FormFieldMessages/v2/index.d.ts.map +1 -0
- package/types/FormFieldMessages/v2/props.d.ts +25 -0
- package/types/FormFieldMessages/v2/props.d.ts.map +1 -0
- package/types/FormFieldMessages/v2/styles.d.ts +14 -0
- package/types/FormFieldMessages/v2/styles.d.ts.map +1 -0
- package/types/exports/a.d.ts +14 -0
- package/types/exports/a.d.ts.map +1 -0
- package/types/exports/b.d.ts +14 -0
- package/types/exports/b.d.ts.map +1 -0
- package/types/utils/v1/FormPropTypes.d.ts.map +1 -0
- package/types/FormField/index.d.ts.map +0 -1
- package/types/FormField/props.d.ts.map +0 -1
- package/types/FormFieldGroup/index.d.ts.map +0 -1
- package/types/FormFieldGroup/props.d.ts.map +0 -1
- package/types/FormFieldGroup/styles.d.ts.map +0 -1
- package/types/FormFieldGroup/theme.d.ts.map +0 -1
- package/types/FormFieldLabel/index.d.ts.map +0 -1
- package/types/FormFieldLabel/props.d.ts.map +0 -1
- package/types/FormFieldLabel/styles.d.ts.map +0 -1
- package/types/FormFieldLabel/theme.d.ts.map +0 -1
- package/types/FormFieldLayout/index.d.ts.map +0 -1
- package/types/FormFieldLayout/props.d.ts.map +0 -1
- package/types/FormFieldLayout/styles.d.ts.map +0 -1
- package/types/FormFieldLayout/theme.d.ts.map +0 -1
- package/types/FormFieldMessage/index.d.ts.map +0 -1
- package/types/FormFieldMessage/props.d.ts.map +0 -1
- package/types/FormFieldMessage/styles.d.ts.map +0 -1
- package/types/FormFieldMessage/theme.d.ts.map +0 -1
- package/types/FormFieldMessages/index.d.ts.map +0 -1
- package/types/FormFieldMessages/props.d.ts.map +0 -1
- package/types/FormFieldMessages/styles.d.ts.map +0 -1
- package/types/FormFieldMessages/theme.d.ts.map +0 -1
- package/types/FormPropTypes.d.ts.map +0 -1
- package/types/index.d.ts +0 -14
- package/types/index.d.ts.map +0 -1
- /package/es/FormField/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldGroup/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldGroup/{styles.js → v1/styles.js} +0 -0
- /package/es/FormFieldGroup/{theme.js → v1/theme.js} +0 -0
- /package/es/FormFieldLabel/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldLabel/{styles.js → v1/styles.js} +0 -0
- /package/es/FormFieldLabel/{theme.js → v1/theme.js} +0 -0
- /package/es/FormFieldLayout/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldLayout/{theme.js → v1/theme.js} +0 -0
- /package/es/FormFieldMessage/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldMessage/{styles.js → v1/styles.js} +0 -0
- /package/es/FormFieldMessage/{theme.js → v1/theme.js} +0 -0
- /package/es/FormFieldMessages/{props.js → v1/props.js} +0 -0
- /package/es/FormFieldMessages/{styles.js → v1/styles.js} +0 -0
- /package/es/FormFieldMessages/{theme.js → v1/theme.js} +0 -0
- /package/es/{FormPropTypes.js → utils/v1/FormPropTypes.js} +0 -0
- /package/lib/FormField/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldGroup/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldGroup/{styles.js → v1/styles.js} +0 -0
- /package/lib/FormFieldGroup/{theme.js → v1/theme.js} +0 -0
- /package/lib/FormFieldLabel/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldLabel/{styles.js → v1/styles.js} +0 -0
- /package/lib/FormFieldLabel/{theme.js → v1/theme.js} +0 -0
- /package/lib/FormFieldLayout/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldLayout/{theme.js → v1/theme.js} +0 -0
- /package/lib/FormFieldMessage/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldMessage/{styles.js → v1/styles.js} +0 -0
- /package/lib/FormFieldMessage/{theme.js → v1/theme.js} +0 -0
- /package/lib/FormFieldMessages/{props.js → v1/props.js} +0 -0
- /package/lib/FormFieldMessages/{styles.js → v1/styles.js} +0 -0
- /package/lib/FormFieldMessages/{theme.js → v1/theme.js} +0 -0
- /package/lib/{FormPropTypes.js → utils/v1/FormPropTypes.js} +0 -0
- /package/src/FormField/{README.md → v1/README.md} +0 -0
- /package/src/FormFieldGroup/{README.md → v1/README.md} +0 -0
- /package/src/FormFieldGroup/{styles.ts → v1/styles.ts} +0 -0
- /package/src/FormFieldGroup/{theme.ts → v1/theme.ts} +0 -0
- /package/src/FormFieldLabel/{props.ts → v1/props.ts} +0 -0
- /package/src/FormFieldLabel/{styles.ts → v1/styles.ts} +0 -0
- /package/src/FormFieldLabel/{theme.ts → v1/theme.ts} +0 -0
- /package/src/FormFieldLayout/{theme.ts → v1/theme.ts} +0 -0
- /package/src/FormFieldMessage/{theme.ts → v1/theme.ts} +0 -0
- /package/src/FormFieldMessages/{styles.ts → v1/styles.ts} +0 -0
- /package/src/FormFieldMessages/{theme.ts → v1/theme.ts} +0 -0
- /package/src/{FormPropTypes.ts → utils/v1/FormPropTypes.ts} +0 -0
- /package/types/FormField/{index.d.ts → v1/index.d.ts} +0 -0
- /package/types/FormFieldGroup/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/FormFieldGroup/{theme.d.ts → v1/theme.d.ts} +0 -0
- /package/types/FormFieldLabel/{index.d.ts → v1/index.d.ts} +0 -0
- /package/types/FormFieldLabel/{props.d.ts → v1/props.d.ts} +0 -0
- /package/types/FormFieldLabel/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/FormFieldLabel/{theme.d.ts → v1/theme.d.ts} +0 -0
- /package/types/FormFieldLayout/{index.d.ts → v1/index.d.ts} +0 -0
- /package/types/FormFieldLayout/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/FormFieldLayout/{theme.d.ts → v1/theme.d.ts} +0 -0
- /package/types/FormFieldMessage/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/FormFieldMessage/{theme.d.ts → v1/theme.d.ts} +0 -0
- /package/types/FormFieldMessages/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/FormFieldMessages/{theme.d.ts → v1/theme.d.ts} +0 -0
- /package/types/{FormPropTypes.d.ts → utils/v1/FormPropTypes.d.ts} +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { forwardRef, useEffect, useState, useCallback } from 'react'
|
|
26
|
+
import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
|
|
27
|
+
import { omitProps, useDeterministicId } from '@instructure/ui-react-utils'
|
|
28
|
+
|
|
29
|
+
import { useStyle } from '@instructure/emotion'
|
|
30
|
+
import { FormFieldMessages } from '../../FormFieldMessages/v2'
|
|
31
|
+
import generateStyle from './styles'
|
|
32
|
+
import { allowedProps } from './props'
|
|
33
|
+
import type { FormFieldLayoutProps } from './props'
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
---
|
|
37
|
+
parent: FormField
|
|
38
|
+
---
|
|
39
|
+
**/
|
|
40
|
+
const FormFieldLayout = forwardRef<Element, FormFieldLayoutProps>(
|
|
41
|
+
(props, ref) => {
|
|
42
|
+
const {
|
|
43
|
+
inline = false,
|
|
44
|
+
layout = 'stacked',
|
|
45
|
+
as = 'label',
|
|
46
|
+
labelAlign = 'end',
|
|
47
|
+
vAlign,
|
|
48
|
+
label,
|
|
49
|
+
messages,
|
|
50
|
+
messagesId: messagesIdProp,
|
|
51
|
+
children,
|
|
52
|
+
width,
|
|
53
|
+
elementRef,
|
|
54
|
+
inputContainerRef,
|
|
55
|
+
isGroup,
|
|
56
|
+
isRequired = false,
|
|
57
|
+
margin,
|
|
58
|
+
disabled = false,
|
|
59
|
+
readOnly = false,
|
|
60
|
+
themeOverride,
|
|
61
|
+
...rest
|
|
62
|
+
} = props
|
|
63
|
+
|
|
64
|
+
// Deterministic ID generation
|
|
65
|
+
const [deterministicId, setDeterministicId] = useState<string | undefined>()
|
|
66
|
+
const getId = useDeterministicId('FormFieldLayout')
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
setDeterministicId(getId())
|
|
69
|
+
}, [])
|
|
70
|
+
|
|
71
|
+
const messagesId = messagesIdProp || deterministicId
|
|
72
|
+
const labelId = deterministicId ? `${deterministicId}-Label` : undefined
|
|
73
|
+
|
|
74
|
+
// Filter out error and success messages when disabled or readOnly
|
|
75
|
+
const filteredMessages =
|
|
76
|
+
disabled || readOnly
|
|
77
|
+
? messages?.filter(
|
|
78
|
+
(msg) =>
|
|
79
|
+
msg.type !== 'error' &&
|
|
80
|
+
msg.type !== 'newError' &&
|
|
81
|
+
msg.type !== 'success'
|
|
82
|
+
)
|
|
83
|
+
: messages
|
|
84
|
+
|
|
85
|
+
// Compute style props
|
|
86
|
+
const hasMessages =
|
|
87
|
+
filteredMessages && filteredMessages.length > 0
|
|
88
|
+
? filteredMessages.some((msg) => {
|
|
89
|
+
if (msg.text) {
|
|
90
|
+
if (typeof msg.text === 'string') {
|
|
91
|
+
return msg.text.length > 0
|
|
92
|
+
}
|
|
93
|
+
return true
|
|
94
|
+
}
|
|
95
|
+
return false
|
|
96
|
+
})
|
|
97
|
+
: false
|
|
98
|
+
|
|
99
|
+
const hasVisibleLabel = label ? hasVisibleChildren(label) : false
|
|
100
|
+
|
|
101
|
+
const hasErrorMsgAndIsGroup =
|
|
102
|
+
!!filteredMessages?.find(
|
|
103
|
+
(m) => m.type === 'error' || m.type === 'newError'
|
|
104
|
+
) && !!isGroup
|
|
105
|
+
|
|
106
|
+
const invalid = !!filteredMessages?.find(
|
|
107
|
+
(m) => m.type === 'error' || m.type === 'newError'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
// Styles
|
|
111
|
+
const styles = useStyle({
|
|
112
|
+
generateStyle,
|
|
113
|
+
themeOverride,
|
|
114
|
+
params: {
|
|
115
|
+
hasMessages,
|
|
116
|
+
hasVisibleLabel,
|
|
117
|
+
hasErrorMsgAndIsGroup,
|
|
118
|
+
inline,
|
|
119
|
+
layout,
|
|
120
|
+
vAlign,
|
|
121
|
+
labelAlign,
|
|
122
|
+
margin,
|
|
123
|
+
messages: filteredMessages,
|
|
124
|
+
isRequired,
|
|
125
|
+
invalid
|
|
126
|
+
},
|
|
127
|
+
componentId: 'FormFieldLayout',
|
|
128
|
+
displayName: 'FormFieldLayout'
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const ElementType = as
|
|
132
|
+
|
|
133
|
+
const handleRef = useCallback(
|
|
134
|
+
(el: Element | null) => {
|
|
135
|
+
if (typeof ref === 'function') {
|
|
136
|
+
ref(el)
|
|
137
|
+
} else if (ref) {
|
|
138
|
+
const refObject = ref as React.MutableRefObject<Element | null>
|
|
139
|
+
refObject.current = el
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (typeof elementRef === 'function') {
|
|
143
|
+
elementRef(el)
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
[ref, elementRef]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
const handleInputContainerRef = useCallback(
|
|
150
|
+
(node: HTMLElement | null) => {
|
|
151
|
+
if (typeof inputContainerRef === 'function') {
|
|
152
|
+
inputContainerRef(node)
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
[inputContainerRef]
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
const renderLabel = () => {
|
|
159
|
+
const labelContent = hasVisibleLabel ? (
|
|
160
|
+
<>
|
|
161
|
+
{label}
|
|
162
|
+
{isRequired && (
|
|
163
|
+
<span
|
|
164
|
+
css={invalid ? styles?.requiredAsterisk : {}}
|
|
165
|
+
aria-hidden={true}
|
|
166
|
+
>
|
|
167
|
+
{' '}
|
|
168
|
+
*
|
|
169
|
+
</span>
|
|
170
|
+
)}
|
|
171
|
+
</>
|
|
172
|
+
) : (
|
|
173
|
+
label
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
if (hasVisibleLabel) {
|
|
177
|
+
if (ElementType === 'fieldset') {
|
|
178
|
+
// `legend` has some special built in CSS, this can only be reset
|
|
179
|
+
// this way https://stackoverflow.com/a/65866981/319473
|
|
180
|
+
return (
|
|
181
|
+
<legend style={{ display: 'contents' }}>
|
|
182
|
+
<span css={styles?.formFieldLabel}>{labelContent}</span>
|
|
183
|
+
</legend>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
return <span css={styles?.formFieldLabel}>{labelContent}</span>
|
|
187
|
+
} else if (label) {
|
|
188
|
+
if (ElementType === 'fieldset') {
|
|
189
|
+
return (
|
|
190
|
+
<legend id={labelId} style={{ display: 'contents' }}>
|
|
191
|
+
{label}
|
|
192
|
+
</legend>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
// needs to be wrapped because it needs an `id`
|
|
196
|
+
return (
|
|
197
|
+
<div id={labelId} style={{ display: 'contents' }}>
|
|
198
|
+
{label}
|
|
199
|
+
</div>
|
|
200
|
+
)
|
|
201
|
+
} else return null
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const renderVisibleMessages = () => {
|
|
205
|
+
return hasMessages ? (
|
|
206
|
+
<FormFieldMessages
|
|
207
|
+
id={messagesId}
|
|
208
|
+
messages={filteredMessages}
|
|
209
|
+
gridArea="messages"
|
|
210
|
+
/>
|
|
211
|
+
) : null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<ElementType
|
|
216
|
+
{...omitProps(rest, [...allowedProps])}
|
|
217
|
+
css={styles?.formFieldLayout}
|
|
218
|
+
aria-describedby={hasMessages ? messagesId : undefined}
|
|
219
|
+
aria-errormessage={rest['aria-invalid'] ? messagesId : undefined}
|
|
220
|
+
style={{ width }}
|
|
221
|
+
ref={handleRef}
|
|
222
|
+
>
|
|
223
|
+
{renderLabel()}
|
|
224
|
+
{hasErrorMsgAndIsGroup && renderVisibleMessages()}
|
|
225
|
+
<span css={styles?.formFieldChildren} ref={handleInputContainerRef}>
|
|
226
|
+
{children}
|
|
227
|
+
</span>
|
|
228
|
+
{!hasErrorMsgAndIsGroup && renderVisibleMessages()}
|
|
229
|
+
</ElementType>
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
FormFieldLayout.displayName = 'FormFieldLayout'
|
|
235
|
+
|
|
236
|
+
export default FormFieldLayout
|
|
237
|
+
export { FormFieldLayout, allowedProps }
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type {
|
|
26
|
+
AsElementType,
|
|
27
|
+
OtherHTMLAttributes
|
|
28
|
+
} from '@instructure/shared-types'
|
|
29
|
+
import type {
|
|
30
|
+
ComponentStyle,
|
|
31
|
+
Spacing,
|
|
32
|
+
ThemeOverrideValue
|
|
33
|
+
} from '@instructure/emotion'
|
|
34
|
+
import type { FormMessage } from '../../utils/v1/FormPropTypes'
|
|
35
|
+
import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
|
|
36
|
+
|
|
37
|
+
type FormFieldLayoutOwnProps = {
|
|
38
|
+
label: React.ReactNode
|
|
39
|
+
/**
|
|
40
|
+
* the id of the input (to link it to its label for a11y)
|
|
41
|
+
*/
|
|
42
|
+
id?: string
|
|
43
|
+
/**
|
|
44
|
+
* the element type to render as
|
|
45
|
+
*/
|
|
46
|
+
as?: AsElementType
|
|
47
|
+
/**
|
|
48
|
+
* Array of objects with shape: `{
|
|
49
|
+
* text: React.ReactNode,
|
|
50
|
+
* type: One of: ['newError', 'error', 'hint', 'success', 'screenreader-only']
|
|
51
|
+
* }`
|
|
52
|
+
*/
|
|
53
|
+
messages?: FormMessage[]
|
|
54
|
+
/**
|
|
55
|
+
* id for the form field messages
|
|
56
|
+
*/
|
|
57
|
+
messagesId?: string
|
|
58
|
+
children?: React.ReactNode
|
|
59
|
+
/**
|
|
60
|
+
* If `true` use an inline layout -- content will flow on the left/right side
|
|
61
|
+
* of this component
|
|
62
|
+
*/
|
|
63
|
+
inline?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* In `stacked` mode the container is below the label, in `inline` mode the
|
|
66
|
+
* container is to the right/left (depending on text direction)
|
|
67
|
+
*/
|
|
68
|
+
layout?: 'stacked' | 'inline'
|
|
69
|
+
/**
|
|
70
|
+
* The horizontal alignment of the label. Only works in `inline` layout
|
|
71
|
+
*/
|
|
72
|
+
labelAlign?: 'start' | 'end'
|
|
73
|
+
/**
|
|
74
|
+
* The vertical alignment of the label and the controls.
|
|
75
|
+
* "top" by default
|
|
76
|
+
*/
|
|
77
|
+
vAlign?: 'top' | 'middle' | 'bottom'
|
|
78
|
+
width?: string
|
|
79
|
+
/**
|
|
80
|
+
* Provides a reference to the container that holds the input element
|
|
81
|
+
* @param element The element that holds the input control as its children
|
|
82
|
+
*/
|
|
83
|
+
inputContainerRef?: (element: HTMLElement | null) => void
|
|
84
|
+
/**
|
|
85
|
+
* provides a reference to the underlying html root element
|
|
86
|
+
*/
|
|
87
|
+
elementRef?: (element: Element | null) => void
|
|
88
|
+
isGroup?: boolean
|
|
89
|
+
/**
|
|
90
|
+
* If `true`, displays an asterisk after the label to indicate the field is required
|
|
91
|
+
*/
|
|
92
|
+
isRequired?: boolean
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Valid values are `0`, `none`, `auto`, and Spacing token values,
|
|
96
|
+
* see https://instructure.design/layout-spacing. Apply these values via
|
|
97
|
+
* familiar CSS-like shorthand. For example, `margin="small auto large"`.
|
|
98
|
+
*/
|
|
99
|
+
margin?: Spacing
|
|
100
|
+
/**
|
|
101
|
+
* Whether the field is disabled. When true, error and success messages will be hidden.
|
|
102
|
+
*/
|
|
103
|
+
disabled?: boolean
|
|
104
|
+
/**
|
|
105
|
+
* Whether the field is read-only. When true, error and success messages will be hidden.
|
|
106
|
+
*/
|
|
107
|
+
readOnly?: boolean
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type PropKeys = keyof FormFieldLayoutOwnProps
|
|
111
|
+
|
|
112
|
+
type AllowedPropKeys = Readonly<Array<PropKeys>>
|
|
113
|
+
|
|
114
|
+
type FormFieldLayoutProps = FormFieldLayoutOwnProps & {
|
|
115
|
+
themeOverride?: ThemeOverrideValue
|
|
116
|
+
} & OtherHTMLAttributes<FormFieldLayoutOwnProps> &
|
|
117
|
+
WithDeterministicIdProps
|
|
118
|
+
|
|
119
|
+
type FormFieldLayoutStyle = ComponentStyle<
|
|
120
|
+
| 'formFieldLayout'
|
|
121
|
+
| 'formFieldLabel'
|
|
122
|
+
| 'formFieldChildren'
|
|
123
|
+
| 'requiredAsterisk'
|
|
124
|
+
>
|
|
125
|
+
const allowedProps: AllowedPropKeys = [
|
|
126
|
+
'label',
|
|
127
|
+
'id',
|
|
128
|
+
'as',
|
|
129
|
+
'messages',
|
|
130
|
+
'messagesId',
|
|
131
|
+
'children',
|
|
132
|
+
'inline',
|
|
133
|
+
'layout',
|
|
134
|
+
'labelAlign',
|
|
135
|
+
'width',
|
|
136
|
+
'inputContainerRef',
|
|
137
|
+
'elementRef',
|
|
138
|
+
'margin',
|
|
139
|
+
'vAlign',
|
|
140
|
+
'isRequired',
|
|
141
|
+
'disabled',
|
|
142
|
+
'readOnly'
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
type FormFieldStyleProps = {
|
|
146
|
+
hasMessages: boolean
|
|
147
|
+
hasVisibleLabel: boolean
|
|
148
|
+
hasErrorMsgAndIsGroup: boolean
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export type {
|
|
152
|
+
FormFieldStyleProps,
|
|
153
|
+
FormFieldLayoutProps,
|
|
154
|
+
FormFieldLayoutStyle,
|
|
155
|
+
FormFieldLayoutOwnProps
|
|
156
|
+
}
|
|
157
|
+
export { allowedProps }
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type {
|
|
26
|
+
FormFieldLayoutProps,
|
|
27
|
+
FormFieldLayoutStyle,
|
|
28
|
+
FormFieldStyleProps
|
|
29
|
+
} from './props'
|
|
30
|
+
import type { NewComponentTypes, SharedTokens } from '@instructure/ui-themes'
|
|
31
|
+
import { calcSpacingFromShorthand } from '@instructure/emotion'
|
|
32
|
+
|
|
33
|
+
type StyleParams = FormFieldStyleProps & {
|
|
34
|
+
inline: FormFieldLayoutProps['inline']
|
|
35
|
+
layout: FormFieldLayoutProps['layout']
|
|
36
|
+
vAlign: FormFieldLayoutProps['vAlign']
|
|
37
|
+
labelAlign: FormFieldLayoutProps['labelAlign']
|
|
38
|
+
margin: FormFieldLayoutProps['margin']
|
|
39
|
+
messages: FormFieldLayoutProps['messages']
|
|
40
|
+
isRequired: FormFieldLayoutProps['isRequired']
|
|
41
|
+
invalid: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const generateGridLayout = (
|
|
45
|
+
isInlineLayout: boolean,
|
|
46
|
+
hasErrorMsgAndIsGroup: boolean,
|
|
47
|
+
hasVisibleLabel: boolean,
|
|
48
|
+
hasMessages: boolean
|
|
49
|
+
) => {
|
|
50
|
+
if (isInlineLayout) {
|
|
51
|
+
if (hasErrorMsgAndIsGroup) {
|
|
52
|
+
if (hasMessages) {
|
|
53
|
+
return `${hasVisibleLabel ? ' "label messages"' : '. messages'}
|
|
54
|
+
". controls"`
|
|
55
|
+
} else {
|
|
56
|
+
return `${hasVisibleLabel ? ' "label controls"' : '. controls'}`
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
return `${hasVisibleLabel ? ' "label controls"' : '. controls'}
|
|
60
|
+
${hasMessages ? ' ". messages"' : ''}`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// stacked layout -- in this case we could use a simple `Flex`
|
|
64
|
+
if (hasErrorMsgAndIsGroup) {
|
|
65
|
+
return `${hasVisibleLabel ? ' "label"' : ''}
|
|
66
|
+
${hasMessages ? ' "messages"' : ''}
|
|
67
|
+
"controls"`
|
|
68
|
+
} else {
|
|
69
|
+
return `${hasVisibleLabel ? ' "label"' : ''}
|
|
70
|
+
"controls"
|
|
71
|
+
${hasMessages ? ' "messages"' : ''}`
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* ---
|
|
76
|
+
* private: true
|
|
77
|
+
* ---
|
|
78
|
+
* Generates the style object from the theme and provided additional information
|
|
79
|
+
* @param componentTheme The theme variable object.
|
|
80
|
+
* @param params Additional parameters to customize the style.
|
|
81
|
+
* @param sharedTokens Shared token object that stores common values for the theme.
|
|
82
|
+
* @return The final style object, which will be used in the component
|
|
83
|
+
*/
|
|
84
|
+
const generateStyle = (
|
|
85
|
+
componentTheme: NewComponentTypes['FormFieldLayout'],
|
|
86
|
+
params: StyleParams,
|
|
87
|
+
sharedTokens: SharedTokens
|
|
88
|
+
): FormFieldLayoutStyle => {
|
|
89
|
+
const { inline, layout, vAlign, labelAlign, margin, messages } = params
|
|
90
|
+
const { hasMessages, hasVisibleLabel, hasErrorMsgAndIsGroup } = params
|
|
91
|
+
const cssMargin = calcSpacingFromShorthand(margin, {
|
|
92
|
+
...sharedTokens.spacing,
|
|
93
|
+
...sharedTokens.legacy.spacing
|
|
94
|
+
})
|
|
95
|
+
const isInlineLayout = layout === 'inline'
|
|
96
|
+
|
|
97
|
+
const hasNonEmptyMessages = messages?.reduce(
|
|
98
|
+
(acc, message) => acc || message.type !== 'screenreader-only',
|
|
99
|
+
false
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
// This is quite ugly, we should simplify it
|
|
103
|
+
const gridTemplateAreas = generateGridLayout(
|
|
104
|
+
isInlineLayout,
|
|
105
|
+
hasErrorMsgAndIsGroup,
|
|
106
|
+
hasVisibleLabel,
|
|
107
|
+
hasMessages
|
|
108
|
+
)
|
|
109
|
+
let gridTemplateColumns = '100%' // stacked layout
|
|
110
|
+
if (isInlineLayout) {
|
|
111
|
+
gridTemplateColumns = '1fr 3fr'
|
|
112
|
+
if (inline) {
|
|
113
|
+
gridTemplateColumns = 'auto 3fr'
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const labelStyles = {
|
|
117
|
+
all: 'initial',
|
|
118
|
+
display: 'block',
|
|
119
|
+
gridArea: 'label',
|
|
120
|
+
color: componentTheme.textColor,
|
|
121
|
+
fontFamily: componentTheme.fontFamily,
|
|
122
|
+
fontWeight: componentTheme.fontWeight,
|
|
123
|
+
fontSize: componentTheme.fontSize,
|
|
124
|
+
lineHeight: componentTheme.lineHeight,
|
|
125
|
+
...(isInlineLayout && {
|
|
126
|
+
margin: '0',
|
|
127
|
+
// when inline add a small padding between the label and the control
|
|
128
|
+
paddingRight: componentTheme.gapPrimitives,
|
|
129
|
+
// and use the horizontal alignment prop
|
|
130
|
+
[`@media screen and (width >= ${componentTheme.stackedOrInlineBreakpoint})`]:
|
|
131
|
+
{
|
|
132
|
+
textAlign: labelAlign
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let alignItems = 'start'
|
|
138
|
+
if (vAlign == 'top') {
|
|
139
|
+
alignItems = 'start'
|
|
140
|
+
} else if (vAlign == 'middle') {
|
|
141
|
+
alignItems = 'center'
|
|
142
|
+
} else if (vAlign == 'bottom') {
|
|
143
|
+
alignItems = 'end'
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
formFieldLayout: {
|
|
147
|
+
label: 'formFieldLayout',
|
|
148
|
+
all: 'initial',
|
|
149
|
+
border: '0',
|
|
150
|
+
padding: '0',
|
|
151
|
+
margin: cssMargin,
|
|
152
|
+
minWidth: '0',
|
|
153
|
+
direction: 'inherit',
|
|
154
|
+
textAlign: 'start',
|
|
155
|
+
opacity: 'inherit',
|
|
156
|
+
display: 'grid',
|
|
157
|
+
alignItems: alignItems,
|
|
158
|
+
verticalAlign: 'middle', // removes margin in inline layouts
|
|
159
|
+
gridTemplateColumns: gridTemplateColumns,
|
|
160
|
+
gridTemplateAreas: gridTemplateAreas,
|
|
161
|
+
[`@media screen and (width < ${componentTheme.stackedOrInlineBreakpoint})`]:
|
|
162
|
+
{
|
|
163
|
+
// for small screens use the stacked layout
|
|
164
|
+
gridTemplateColumns: '100%',
|
|
165
|
+
gridTemplateAreas: generateGridLayout(
|
|
166
|
+
false,
|
|
167
|
+
hasErrorMsgAndIsGroup,
|
|
168
|
+
hasVisibleLabel,
|
|
169
|
+
hasMessages
|
|
170
|
+
)
|
|
171
|
+
},
|
|
172
|
+
columnGap: '0.375rem',
|
|
173
|
+
rowGap: hasNonEmptyMessages ? componentTheme.gapPrimitives : '0',
|
|
174
|
+
width: '100%',
|
|
175
|
+
...(inline && {
|
|
176
|
+
display: 'inline-grid',
|
|
177
|
+
width: 'auto'
|
|
178
|
+
})
|
|
179
|
+
},
|
|
180
|
+
formFieldLabel: {
|
|
181
|
+
label: 'formFieldLayout__label',
|
|
182
|
+
...labelStyles,
|
|
183
|
+
// NOTE: needs separate groups for `:is()` and `:-webkit-any()` because of css selector group validation (see https://www.w3.org/TR/selectors-3/#grouping)
|
|
184
|
+
'&:is(label)': labelStyles,
|
|
185
|
+
'&:-webkit-any(label)': labelStyles,
|
|
186
|
+
|
|
187
|
+
paddingBottom: hasNonEmptyMessages ? '0' : componentTheme.gapPrimitives
|
|
188
|
+
},
|
|
189
|
+
formFieldChildren: {
|
|
190
|
+
label: 'formFieldLayout__children',
|
|
191
|
+
gridArea: 'controls',
|
|
192
|
+
// add a small margin between the message and the controls
|
|
193
|
+
...(hasMessages && hasErrorMsgAndIsGroup && { marginTop: '0.375rem' }),
|
|
194
|
+
...(isInlineLayout &&
|
|
195
|
+
inline && {
|
|
196
|
+
[`@media screen and (width >= ${componentTheme.stackedOrInlineBreakpoint})`]:
|
|
197
|
+
{
|
|
198
|
+
justifySelf: 'start'
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
requiredAsterisk: {
|
|
203
|
+
label: 'formFieldLayout__requiredAsterisk',
|
|
204
|
+
color: componentTheme.asteriskColor
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export default generateStyle
|
|
@@ -28,7 +28,7 @@ import { ScreenReaderContent } from '@instructure/ui-a11y-content'
|
|
|
28
28
|
|
|
29
29
|
import { IconWarningSolid } from '@instructure/ui-icons'
|
|
30
30
|
|
|
31
|
-
import { withStyle } from '@instructure/emotion'
|
|
31
|
+
import { withStyleLegacy as withStyle } from '@instructure/emotion'
|
|
32
32
|
|
|
33
33
|
import generateStyle from './styles'
|
|
34
34
|
import generateComponentTheme from './theme'
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
|
|
25
25
|
import type { FormFieldMessageTheme } from '@instructure/shared-types'
|
|
26
26
|
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
|
|
27
|
-
import type {
|
|
27
|
+
import type {
|
|
28
|
+
FormMessageType,
|
|
29
|
+
FormMessageChild
|
|
30
|
+
} from '../../utils/v1/FormPropTypes'
|
|
28
31
|
|
|
29
32
|
type FormFieldMessageOwnProps = {
|
|
30
33
|
variant?: FormMessageType
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import type { FormFieldMessageTheme } from '@instructure/shared-types'
|
|
26
26
|
import type { FormFieldMessageProps, FormFieldMessageStyle } from './props'
|
|
27
|
-
import type { FormMessageType } from '
|
|
28
|
-
|
|
27
|
+
import type { FormMessageType } from '../../utils/v1/FormPropTypes'
|
|
29
28
|
/**
|
|
30
29
|
* ---
|
|
31
30
|
* private: true
|
|
@@ -54,7 +53,7 @@ const generateStyle = (
|
|
|
54
53
|
errorIcon: {
|
|
55
54
|
fontSize: componentTheme.fontSize,
|
|
56
55
|
marginRight: componentTheme.errorIconMarginRight,
|
|
57
|
-
lineHeight: 1.25
|
|
56
|
+
lineHeight: 1.25
|
|
58
57
|
},
|
|
59
58
|
formFieldMessage: {
|
|
60
59
|
label: 'formFieldMessage',
|