@instructure/ui-modal 10.3.1-snapshot-9 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -2
- package/es/Modal/__new-tests__/Modal.test.js +33 -31
- package/es/Modal/index.js +6 -7
- package/es/Modal/props.js +2 -5
- package/lib/Modal/__new-tests__/Modal.test.js +33 -31
- package/lib/Modal/index.js +5 -8
- package/lib/Modal/props.js +1 -5
- package/package.json +19 -19
- package/src/Modal/README.md +94 -0
- package/src/Modal/__new-tests__/Modal.test.tsx +18 -23
- package/src/Modal/index.tsx +13 -29
- package/src/Modal/props.ts +4 -16
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Modal/index.d.ts +2 -8
- package/types/Modal/index.d.ts.map +1 -1
- package/types/Modal/props.d.ts +1 -1
- package/types/Modal/props.d.ts.map +1 -1
|
@@ -30,6 +30,7 @@ import '@testing-library/jest-dom'
|
|
|
30
30
|
|
|
31
31
|
import { Modal, ModalHeader, ModalBody, ModalFooter } from '../index'
|
|
32
32
|
import type { ModalProps } from '../props'
|
|
33
|
+
import { View } from '@instructure/ui-view'
|
|
33
34
|
|
|
34
35
|
describe('<Modal />', () => {
|
|
35
36
|
let consoleWarningMock: ReturnType<typeof vi.spyOn>
|
|
@@ -168,6 +169,23 @@ describe('<Modal />', () => {
|
|
|
168
169
|
expect(modalBody).toBeInTheDocument()
|
|
169
170
|
})
|
|
170
171
|
|
|
172
|
+
it('should handle custom children', async () => {
|
|
173
|
+
const bodyText = 'Modal-body-text'
|
|
174
|
+
const { findByText } = render(
|
|
175
|
+
<Modal open label="Modal Dialog" shouldReturnFocus={false}>
|
|
176
|
+
<View>
|
|
177
|
+
This is a custom child
|
|
178
|
+
</View>
|
|
179
|
+
<Modal.Body>{bodyText}</Modal.Body>
|
|
180
|
+
</Modal>
|
|
181
|
+
)
|
|
182
|
+
const modalBody = await findByText(bodyText)
|
|
183
|
+
const customChild = await findByText('This is a custom child')
|
|
184
|
+
|
|
185
|
+
expect(modalBody).toBeInTheDocument()
|
|
186
|
+
expect(customChild).toBeInTheDocument()
|
|
187
|
+
})
|
|
188
|
+
|
|
171
189
|
it('should apply the aria attributes', async () => {
|
|
172
190
|
const { findByRole } = render(
|
|
173
191
|
<Modal open label="Modal Dialog" shouldReturnFocus={false}>
|
|
@@ -350,29 +368,6 @@ describe('<Modal />', () => {
|
|
|
350
368
|
expect(consoleErrorMock).not.toHaveBeenCalled()
|
|
351
369
|
})
|
|
352
370
|
|
|
353
|
-
it('should not pass validation when children are invalid', async () => {
|
|
354
|
-
const { findByRole } = render(
|
|
355
|
-
<Modal open label="Modal Dialog" shouldReturnFocus={false}>
|
|
356
|
-
<Modal.Body>Foo Bar Baz</Modal.Body>
|
|
357
|
-
<Modal.Footer>
|
|
358
|
-
<button>Cancel</button>
|
|
359
|
-
</Modal.Footer>
|
|
360
|
-
<Modal.Header>Hello World</Modal.Header>
|
|
361
|
-
</Modal>
|
|
362
|
-
)
|
|
363
|
-
const dialog = await findByRole('dialog')
|
|
364
|
-
const expectedErrorMessage =
|
|
365
|
-
'Expected children of Modal in one of the following formats:'
|
|
366
|
-
|
|
367
|
-
expect(dialog).toBeInTheDocument()
|
|
368
|
-
expect(consoleErrorMock).toHaveBeenCalledWith(
|
|
369
|
-
expect.any(String),
|
|
370
|
-
expect.any(String),
|
|
371
|
-
expect.stringContaining(expectedErrorMessage),
|
|
372
|
-
expect.any(String)
|
|
373
|
-
)
|
|
374
|
-
})
|
|
375
|
-
|
|
376
371
|
it('should pass inverse variant to children when set', async () => {
|
|
377
372
|
let headerRef: ModalHeader | null = null
|
|
378
373
|
let bodyRef: ModalBody | null = null
|
package/src/Modal/index.tsx
CHANGED
|
@@ -23,13 +23,9 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/** @jsx jsx */
|
|
26
|
-
import
|
|
26
|
+
import { Children, Component, isValidElement, ReactElement } from 'react'
|
|
27
27
|
|
|
28
|
-
import {
|
|
29
|
-
passthroughProps,
|
|
30
|
-
safeCloneElement,
|
|
31
|
-
matchComponentTypes
|
|
32
|
-
} from '@instructure/ui-react-utils'
|
|
28
|
+
import { passthroughProps, safeCloneElement } from '@instructure/ui-react-utils'
|
|
33
29
|
import { createChainedFunction } from '@instructure/ui-utils'
|
|
34
30
|
import { testable } from '@instructure/ui-testable'
|
|
35
31
|
|
|
@@ -40,11 +36,8 @@ import { Dialog } from '@instructure/ui-dialog'
|
|
|
40
36
|
import { Mask } from '@instructure/ui-overlays'
|
|
41
37
|
|
|
42
38
|
import { ModalHeader } from './ModalHeader'
|
|
43
|
-
import type { ModalHeaderProps } from './ModalHeader/props'
|
|
44
39
|
import { ModalBody } from './ModalBody'
|
|
45
|
-
import type { ModalBodyProps } from './ModalBody/props'
|
|
46
40
|
import { ModalFooter } from './ModalFooter'
|
|
47
|
-
import type { ModalFooterProps } from './ModalFooter/props'
|
|
48
41
|
|
|
49
42
|
import { withStyle, jsx } from '@instructure/emotion'
|
|
50
43
|
|
|
@@ -59,10 +52,6 @@ import type {
|
|
|
59
52
|
ModalPropsForTransition
|
|
60
53
|
} from './props'
|
|
61
54
|
|
|
62
|
-
type HeaderChild = React.ComponentElement<ModalHeaderProps, ModalHeader>
|
|
63
|
-
type BodyChild = React.ComponentElement<ModalBodyProps, ModalBody>
|
|
64
|
-
type FooterChild = React.ComponentElement<ModalFooterProps, ModalFooter>
|
|
65
|
-
|
|
66
55
|
/**
|
|
67
56
|
---
|
|
68
57
|
category: components
|
|
@@ -160,23 +149,18 @@ class Modal extends Component<ModalProps, ModalState> {
|
|
|
160
149
|
renderChildren() {
|
|
161
150
|
const { children, variant, overflow } = this.props
|
|
162
151
|
|
|
163
|
-
return Children.map(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
} else {
|
|
174
|
-
return safeCloneElement(child, {
|
|
175
|
-
variant: variant
|
|
176
|
-
})
|
|
177
|
-
}
|
|
152
|
+
return Children.map(children as ReactElement, (child) => {
|
|
153
|
+
if (!child) return // ignore null, falsy children
|
|
154
|
+
|
|
155
|
+
if (isValidElement(child)) {
|
|
156
|
+
return safeCloneElement(child, {
|
|
157
|
+
variant: variant,
|
|
158
|
+
overflow: (child?.props as { overflow: string })?.overflow || overflow
|
|
159
|
+
})
|
|
160
|
+
} else {
|
|
161
|
+
return child
|
|
178
162
|
}
|
|
179
|
-
)
|
|
163
|
+
})
|
|
180
164
|
}
|
|
181
165
|
|
|
182
166
|
renderDialog(
|
package/src/Modal/props.ts
CHANGED
|
@@ -25,18 +25,11 @@
|
|
|
25
25
|
import React from 'react'
|
|
26
26
|
import PropTypes from 'prop-types'
|
|
27
27
|
|
|
28
|
-
import {
|
|
29
|
-
element,
|
|
30
|
-
Children as ChildrenPropTypes
|
|
31
|
-
} from '@instructure/ui-prop-types'
|
|
28
|
+
import { element } from '@instructure/ui-prop-types'
|
|
32
29
|
import { transitionTypePropType } from '@instructure/ui-motion'
|
|
33
30
|
|
|
34
31
|
import { Dialog } from '@instructure/ui-dialog'
|
|
35
32
|
|
|
36
|
-
import { ModalHeader } from './ModalHeader'
|
|
37
|
-
import { ModalBody } from './ModalBody'
|
|
38
|
-
import { ModalFooter } from './ModalFooter'
|
|
39
|
-
|
|
40
33
|
import type {
|
|
41
34
|
AsElementType,
|
|
42
35
|
PropValidators,
|
|
@@ -154,9 +147,9 @@ type ModalPropsForDialog = {
|
|
|
154
147
|
|
|
155
148
|
type ModalOwnProps = {
|
|
156
149
|
/**
|
|
157
|
-
*
|
|
150
|
+
* Recommended children types are: `Modal.Header`, `Modal.Body`, `Modal.Footer`. Custom children can be used as well. `Variant` and `overflow` properties are always passed down to children.
|
|
158
151
|
*/
|
|
159
|
-
children: React.ReactNode
|
|
152
|
+
children: React.ReactNode
|
|
160
153
|
|
|
161
154
|
/**
|
|
162
155
|
* The size of the `<Modal />` content
|
|
@@ -205,12 +198,7 @@ type ModalState = {
|
|
|
205
198
|
|
|
206
199
|
const propTypes: PropValidators<PropKeys> = {
|
|
207
200
|
label: PropTypes.string.isRequired,
|
|
208
|
-
children:
|
|
209
|
-
[ModalHeader, ModalBody, ModalFooter],
|
|
210
|
-
[ModalHeader, ModalBody],
|
|
211
|
-
[ModalBody, ModalFooter],
|
|
212
|
-
[ModalBody]
|
|
213
|
-
),
|
|
201
|
+
children: PropTypes.node,
|
|
214
202
|
as: PropTypes.elementType,
|
|
215
203
|
size: PropTypes.oneOf(['auto', 'small', 'medium', 'large', 'fullscreen']),
|
|
216
204
|
variant: PropTypes.oneOf(['default', 'inverse']),
|