How to wrap selected content with node?

Hello. I need to implement a custom node and button. User selects content, click the button and should be selected content replaced with wrapped one (similar to mark except it’s block node with content)

I implemented it the following way:

    view.dispatch(
        view.state.tr
          .replaceWith(
            view.state.selection.from,
            view.state.selection.to,
            schema.nodes.myCustomNode.create({paramA: "abc"}, view.state.selection.content().content.firstChild.content)
          )
      )

I’m expecting that view.state.selection.content().content.firstChild.content contains selected content only. When user selects content in complex block (like checklist / list item / code block) it also has parent type: [{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"qwe"}]}]}] (list_item in this example). In this case I’ll list_item which will contain another list_item

How can I get only selected content without parent part / correctly implement selection wrapping?

content gives you the selected content. It’s just that your assumption about what that will look like doesn’t really hold (it’s going to be a slice of a tree, which will include parent nodes that the range is partially inside of). Take a look at the transform wrap method, which might be what you’re looking for.