@contember/react-block-repeater 2.0.0-alpha.9 → 2.0.0-beta.2
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/dist/development/src/components/Block.cjs +1 -1
- package/dist/development/src/components/Block.cjs.map +1 -1
- package/dist/development/src/components/Block.js +1 -1
- package/dist/development/src/components/Block.js.map +1 -1
- package/dist/development/src/components/BlockRepeater.cjs +4 -4
- package/dist/development/src/components/BlockRepeater.cjs.map +1 -1
- package/dist/development/src/components/BlockRepeater.js +4 -4
- package/dist/development/src/components/BlockRepeater.js.map +1 -1
- package/dist/development/src/components/BlockRepeaterAddItemTrigger.cjs +8 -4
- package/dist/development/src/components/BlockRepeaterAddItemTrigger.cjs.map +1 -1
- package/dist/development/src/components/BlockRepeaterAddItemTrigger.js +9 -5
- package/dist/development/src/components/BlockRepeaterAddItemTrigger.js.map +1 -1
- package/dist/development/src/contexts.cjs.map +1 -1
- package/dist/development/src/contexts.js.map +1 -1
- package/dist/development/src/hooks/useBlockRepeaterCurrentBlock.cjs.map +1 -1
- package/dist/development/src/hooks/useBlockRepeaterCurrentBlock.js.map +1 -1
- package/dist/development/src/internal/helpers/staticAnalyzer.cjs.map +1 -1
- package/dist/production/src/components/Block.cjs.map +1 -1
- package/dist/production/src/components/Block.js.map +1 -1
- package/dist/production/src/components/BlockRepeater.cjs.map +1 -1
- package/dist/production/src/components/BlockRepeater.js.map +1 -1
- package/dist/production/src/components/BlockRepeaterAddItemTrigger.cjs +7 -3
- package/dist/production/src/components/BlockRepeaterAddItemTrigger.cjs.map +1 -1
- package/dist/production/src/components/BlockRepeaterAddItemTrigger.js +8 -4
- package/dist/production/src/components/BlockRepeaterAddItemTrigger.js.map +1 -1
- package/dist/production/src/contexts.cjs.map +1 -1
- package/dist/production/src/contexts.js.map +1 -1
- package/dist/production/src/hooks/useBlockRepeaterCurrentBlock.cjs.map +1 -1
- package/dist/production/src/hooks/useBlockRepeaterCurrentBlock.js.map +1 -1
- package/dist/production/src/internal/helpers/staticAnalyzer.cjs.map +1 -1
- package/dist/types/components/Block.d.ts +28 -0
- package/dist/types/components/Block.d.ts.map +1 -1
- package/dist/types/components/BlockRepeater.d.ts +28 -0
- package/dist/types/components/BlockRepeater.d.ts.map +1 -1
- package/dist/types/components/BlockRepeaterAddItemTrigger.d.ts +33 -1
- package/dist/types/components/BlockRepeaterAddItemTrigger.d.ts.map +1 -1
- package/dist/types/contexts.d.ts +3 -0
- package/dist/types/contexts.d.ts.map +1 -1
- package/dist/types/hooks/useBlockRepeaterCurrentBlock.d.ts +5 -1
- package/dist/types/hooks/useBlockRepeaterCurrentBlock.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -7
- package/src/components/Block.tsx +28 -0
- package/src/components/BlockRepeater.tsx +29 -0
- package/src/components/BlockRepeaterAddItemTrigger.tsx +48 -5
- package/src/contexts.ts +4 -0
- package/src/hooks/useBlockRepeaterCurrentBlock.ts +5 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/react-block-repeater",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "2.0.0-
|
|
4
|
+
"version": "2.0.0-beta.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/production/index.js",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"types": "./dist/types/index.d.ts",
|
|
12
12
|
"development": "./dist/development/index.js",
|
|
13
13
|
"production": "./dist/production/index.js",
|
|
14
|
+
"typescript": "./src/index.ts",
|
|
14
15
|
"default": "./dist/production/index.js"
|
|
15
16
|
},
|
|
16
17
|
"require": {
|
|
@@ -28,11 +29,12 @@
|
|
|
28
29
|
"ae:test": "api-extractor run"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"@contember/react-binding": "2.0.0-
|
|
32
|
-
"@contember/react-multipass-rendering": "2.0.0-
|
|
33
|
-
"@contember/react-repeater": "2.0.0-
|
|
34
|
-
"@contember/react-utils": "2.0.0-
|
|
35
|
-
"@radix-ui/
|
|
32
|
+
"@contember/react-binding": "2.0.0-beta.2",
|
|
33
|
+
"@contember/react-multipass-rendering": "2.0.0-beta.2",
|
|
34
|
+
"@contember/react-repeater": "2.0.0-beta.2",
|
|
35
|
+
"@contember/react-utils": "2.0.0-beta.2",
|
|
36
|
+
"@radix-ui/primitive": "^1.1.0",
|
|
37
|
+
"@radix-ui/react-slot": "^1.1.0"
|
|
36
38
|
},
|
|
37
39
|
"peerDependencies": {
|
|
38
40
|
"react": "^18 || ^19",
|
|
@@ -47,4 +49,4 @@
|
|
|
47
49
|
"url": "https://github.com/contember/interface.git",
|
|
48
50
|
"directory": "packages/react-block-repeater"
|
|
49
51
|
}
|
|
50
|
-
}
|
|
52
|
+
}
|
package/src/components/Block.tsx
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
import { BindingError, Component } from '@contember/react-binding'
|
|
2
2
|
import { ReactNode } from 'react'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Props for the {@link Block} component.
|
|
6
|
+
*/
|
|
4
7
|
export interface BlockProps {
|
|
8
|
+
/**
|
|
9
|
+
* The content of the block.
|
|
10
|
+
*/
|
|
5
11
|
children: ReactNode
|
|
12
|
+
/**
|
|
13
|
+
* Identifier of the block.
|
|
14
|
+
*/
|
|
6
15
|
name: string
|
|
16
|
+
/**
|
|
17
|
+
* Optional label for the block.
|
|
18
|
+
*/
|
|
7
19
|
label?: ReactNode
|
|
20
|
+
/**
|
|
21
|
+
* Optional form for the block.
|
|
22
|
+
*/
|
|
8
23
|
form?: ReactNode
|
|
9
24
|
}
|
|
10
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Represents individual blocks within a block repeater.
|
|
28
|
+
*
|
|
29
|
+
* ## Props {@link BlockProps}
|
|
30
|
+
* - name, children, ?label, ?form
|
|
31
|
+
*
|
|
32
|
+
* ## Example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <Block name="text" label="Text">
|
|
35
|
+
* <Field field="content" />
|
|
36
|
+
* </Block>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
11
39
|
export const Block = Component<BlockProps>(props => {
|
|
12
40
|
throw new BindingError('"Block" component is not supposed to be rendered.')
|
|
13
41
|
}, ({ label, children, form }) => {
|
|
@@ -4,13 +4,42 @@ import { useState } from 'react'
|
|
|
4
4
|
import { extractBlocks } from '../internal/helpers/staticAnalyzer'
|
|
5
5
|
import { BlockRepeaterConfigContext } from '../contexts'
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Props for the {@link BlockRepeater} component.
|
|
9
|
+
*/
|
|
7
10
|
export type BlockRepeaterProps =
|
|
8
11
|
& {
|
|
12
|
+
/**
|
|
13
|
+
* A field that is used to determine the order of the entities.
|
|
14
|
+
*/
|
|
9
15
|
sortableBy: RepeaterProps['sortableBy']
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Discrimination field is a field that is used to determine which block should be rendered for a given entity.
|
|
19
|
+
*/
|
|
10
20
|
discriminationField: SugaredRelativeSingleField['field']
|
|
11
21
|
}
|
|
12
22
|
& RepeaterProps
|
|
13
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A repeater component that renders different blocks based on the value of a discrimination field.
|
|
26
|
+
* This is headless component that does not impose any UI. Check DefaultBlockRepeater in UI library for a styled version.
|
|
27
|
+
*
|
|
28
|
+
* ## Props {@link BlockRepeaterProps}
|
|
29
|
+
* - field or entities, sortableBy, discriminationField, children
|
|
30
|
+
*
|
|
31
|
+
* ## Example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* <BlockRepeater field="blocks" discriminationField="type" sortableBy="order">
|
|
34
|
+
* <Block name="text" label="Text">
|
|
35
|
+
* <Field field="content" />
|
|
36
|
+
* </Block>
|
|
37
|
+
* <Block name="image" label="Image">
|
|
38
|
+
* <ImageField field="image" />
|
|
39
|
+
* </Block>
|
|
40
|
+
* </BlockRepeater>
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
14
43
|
export const BlockRepeater = Component<BlockRepeaterProps>(({ children, ...props }, env) => {
|
|
15
44
|
const [blocks] = useState(() => extractBlocks(children, env))
|
|
16
45
|
if (Object.keys(blocks).length === 0) {
|
|
@@ -1,23 +1,66 @@
|
|
|
1
1
|
import { Slot } from '@radix-ui/react-slot'
|
|
2
2
|
import { useBlockRepeaterConfig } from '../contexts'
|
|
3
|
-
import React, { ReactElement, useMemo } from 'react'
|
|
3
|
+
import React, { ReactElement, useCallback, useMemo } from 'react'
|
|
4
4
|
import { EntityAccessor } from '@contember/react-binding'
|
|
5
5
|
import { RepeaterAddItemIndex, useRepeaterMethods } from '@contember/react-repeater'
|
|
6
|
+
import { composeEventHandlers } from '@radix-ui/primitive'
|
|
6
7
|
|
|
8
|
+
|
|
9
|
+
const SlotType = Slot as React.ForwardRefExoticComponent<React.ButtonHTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Props for the {@link BlockRepeaterAddItemTrigger} component.
|
|
13
|
+
*/
|
|
7
14
|
export interface BlockRepeaterAddItemTriggerProps {
|
|
8
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The type of the item to add.
|
|
18
|
+
*/
|
|
9
19
|
type: string
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The index at which to add the item.
|
|
23
|
+
* Can be one of:
|
|
24
|
+
* - number: Adds the item at the specified index.
|
|
25
|
+
* - `'first'`: Adds the item at the beginning.
|
|
26
|
+
* - undefined or `'last'`: Adds the item at the end.
|
|
27
|
+
*/
|
|
10
28
|
index?: RepeaterAddItemIndex
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A function to preprocess the entity.
|
|
32
|
+
*/
|
|
11
33
|
preprocess?: EntityAccessor.BatchUpdatesHandler
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The button element.
|
|
37
|
+
*/
|
|
38
|
+
children: ReactElement
|
|
12
39
|
}
|
|
13
40
|
|
|
41
|
+
/**
|
|
42
|
+
* A trigger component for adding item of given type to a block repeater.
|
|
43
|
+
*
|
|
44
|
+
* ## Props {@link BlockRepeaterAddItemTriggerProps}
|
|
45
|
+
* - type, ?index, ?preprocess, children
|
|
46
|
+
*
|
|
47
|
+
* ## Example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <BlockRepeaterAddItemTrigger type="image" index="first">
|
|
50
|
+
* <button>Add Image</button>
|
|
51
|
+
* </BlockRepeaterAddItemTrigger>
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
14
54
|
export const BlockRepeaterAddItemTrigger = ({ preprocess, index, type, ...props }: BlockRepeaterAddItemTriggerProps) => {
|
|
15
55
|
const { discriminatedBy } = useBlockRepeaterConfig()
|
|
16
56
|
|
|
17
57
|
const { addItem } = useRepeaterMethods()
|
|
18
|
-
const
|
|
58
|
+
const doAddItem = useCallback(() => addItem(index, (it, options) => {
|
|
19
59
|
it().getField(discriminatedBy).updateValue(type)
|
|
20
|
-
|
|
60
|
+
preprocess?.(it, options)
|
|
61
|
+
}), [addItem, discriminatedBy, index, preprocess, type])
|
|
62
|
+
|
|
63
|
+
const { onClick, ...otherProps } = props as React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
21
64
|
|
|
22
|
-
return <
|
|
65
|
+
return <SlotType onClick={composeEventHandlers(onClick, doAddItem)} {...otherProps} />
|
|
23
66
|
}
|
package/src/contexts.ts
CHANGED
|
@@ -8,4 +8,8 @@ const BlockRepeaterConfigContext_ = createRequiredContext<{
|
|
|
8
8
|
}>('BlockRepeaterConfigContext')
|
|
9
9
|
/** @internal */
|
|
10
10
|
export const BlockRepeaterConfigContext = BlockRepeaterConfigContext_[0]
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns configuration of the block repeater (discrimination field and blocks map).
|
|
14
|
+
*/
|
|
11
15
|
export const useBlockRepeaterConfig = BlockRepeaterConfigContext_[1]
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { useEntity } from '@contember/react-binding'
|
|
2
2
|
import { useBlockRepeaterConfig } from '../contexts'
|
|
3
|
+
import { BlockProps } from '../components'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current block props (see {@link BlockProps}).
|
|
7
|
+
*/
|
|
8
|
+
export const useBlockRepeaterCurrentBlock = (): BlockProps | undefined => {
|
|
5
9
|
const entity = useEntity()
|
|
6
10
|
const { discriminatedBy, blocks } = useBlockRepeaterConfig()
|
|
7
11
|
const field = entity.getField<string>(discriminatedBy).value
|