@contember/react-block-repeater 2.0.0-alpha.39 → 2.0.0-alpha.40

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.
Files changed (45) hide show
  1. package/dist/development/src/components/Block.cjs +1 -1
  2. package/dist/development/src/components/Block.cjs.map +1 -1
  3. package/dist/development/src/components/Block.js +1 -1
  4. package/dist/development/src/components/Block.js.map +1 -1
  5. package/dist/development/src/components/BlockRepeater.cjs +4 -4
  6. package/dist/development/src/components/BlockRepeater.cjs.map +1 -1
  7. package/dist/development/src/components/BlockRepeater.js +4 -4
  8. package/dist/development/src/components/BlockRepeater.js.map +1 -1
  9. package/dist/development/src/components/BlockRepeaterAddItemTrigger.cjs +8 -4
  10. package/dist/development/src/components/BlockRepeaterAddItemTrigger.cjs.map +1 -1
  11. package/dist/development/src/components/BlockRepeaterAddItemTrigger.js +9 -5
  12. package/dist/development/src/components/BlockRepeaterAddItemTrigger.js.map +1 -1
  13. package/dist/development/src/contexts.cjs.map +1 -1
  14. package/dist/development/src/contexts.js.map +1 -1
  15. package/dist/development/src/hooks/useBlockRepeaterCurrentBlock.cjs.map +1 -1
  16. package/dist/development/src/hooks/useBlockRepeaterCurrentBlock.js.map +1 -1
  17. package/dist/production/src/components/Block.cjs.map +1 -1
  18. package/dist/production/src/components/Block.js.map +1 -1
  19. package/dist/production/src/components/BlockRepeater.cjs.map +1 -1
  20. package/dist/production/src/components/BlockRepeater.js.map +1 -1
  21. package/dist/production/src/components/BlockRepeaterAddItemTrigger.cjs +7 -3
  22. package/dist/production/src/components/BlockRepeaterAddItemTrigger.cjs.map +1 -1
  23. package/dist/production/src/components/BlockRepeaterAddItemTrigger.js +8 -4
  24. package/dist/production/src/components/BlockRepeaterAddItemTrigger.js.map +1 -1
  25. package/dist/production/src/contexts.cjs.map +1 -1
  26. package/dist/production/src/contexts.js.map +1 -1
  27. package/dist/production/src/hooks/useBlockRepeaterCurrentBlock.cjs.map +1 -1
  28. package/dist/production/src/hooks/useBlockRepeaterCurrentBlock.js.map +1 -1
  29. package/dist/types/components/Block.d.ts +28 -0
  30. package/dist/types/components/Block.d.ts.map +1 -1
  31. package/dist/types/components/BlockRepeater.d.ts +28 -0
  32. package/dist/types/components/BlockRepeater.d.ts.map +1 -1
  33. package/dist/types/components/BlockRepeaterAddItemTrigger.d.ts +33 -1
  34. package/dist/types/components/BlockRepeaterAddItemTrigger.d.ts.map +1 -1
  35. package/dist/types/contexts.d.ts +3 -0
  36. package/dist/types/contexts.d.ts.map +1 -1
  37. package/dist/types/hooks/useBlockRepeaterCurrentBlock.d.ts +5 -1
  38. package/dist/types/hooks/useBlockRepeaterCurrentBlock.d.ts.map +1 -1
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +6 -5
  41. package/src/components/Block.tsx +28 -0
  42. package/src/components/BlockRepeater.tsx +29 -0
  43. package/src/components/BlockRepeaterAddItemTrigger.tsx +48 -5
  44. package/src/contexts.ts +4 -0
  45. 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-alpha.39",
4
+ "version": "2.0.0-alpha.40",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "main": "./dist/production/index.js",
@@ -29,10 +29,11 @@
29
29
  "ae:test": "api-extractor run"
30
30
  },
31
31
  "dependencies": {
32
- "@contember/react-binding": "2.0.0-alpha.39",
33
- "@contember/react-multipass-rendering": "2.0.0-alpha.39",
34
- "@contember/react-repeater": "2.0.0-alpha.39",
35
- "@contember/react-utils": "2.0.0-alpha.39",
32
+ "@contember/react-binding": "2.0.0-alpha.40",
33
+ "@contember/react-multipass-rendering": "2.0.0-alpha.40",
34
+ "@contember/react-repeater": "2.0.0-alpha.40",
35
+ "@contember/react-utils": "2.0.0-alpha.40",
36
+ "@radix-ui/primitive": "^1.1.0",
36
37
  "@radix-ui/react-slot": "^1.1.0"
37
38
  },
38
39
  "peerDependencies": {
@@ -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
- children: ReactElement
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 onClick = useMemo(() => () => addItem?.(index, it => {
58
+ const doAddItem = useCallback(() => addItem(index, (it, options) => {
19
59
  it().getField(discriminatedBy).updateValue(type)
20
- }), [addItem, discriminatedBy, index, type])
60
+ preprocess?.(it, options)
61
+ }), [addItem, discriminatedBy, index, preprocess, type])
62
+
63
+ const { onClick, ...otherProps } = props as React.ButtonHTMLAttributes<HTMLButtonElement>
21
64
 
22
- return <Slot onClick={onClick} {...props} />
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
- export const useBlockRepeaterCurrentBlock = () => {
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