@bikdotai/bik-component-library 0.0.806-beta.9 → 0.0.807-beta.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/dist/cjs/components/feature-announcements/FeatureAnnouncementProvider.js +1 -1
- package/dist/cjs/components/feature-announcements/FeatureAnnouncementProvider.js.map +1 -1
- package/dist/cjs/components/feature-announcements/MajorUpdatePopup.js +1 -1
- package/dist/cjs/components/feature-announcements/MajorUpdatePopup.js.map +1 -1
- package/dist/cjs/components/feature-announcements/MinorUpdatePopup.js +1 -1
- package/dist/cjs/components/feature-announcements/MinorUpdatePopup.js.map +1 -1
- package/dist/cjs/components/feature-announcements/utils/animationHelpers.js.map +1 -1
- package/dist/cjs/editor/BikEditor.styles.js +8 -2
- package/dist/cjs/editor/BikEditor.styles.js.map +1 -1
- package/dist/cjs/editor/extensions/buildExtensions.js +1 -1
- package/dist/cjs/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js +2 -0
- package/dist/cjs/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js.map +1 -0
- package/dist/cjs/editor/extensions/plainClipboard/PlainClipboardExtension.js +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/PlainClipboardExtension.js.map +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/pasteUtils.js +2 -0
- package/dist/cjs/editor/extensions/plainClipboard/pasteUtils.js.map +1 -0
- package/dist/cjs/src/components/bik-layout/MockMenus.d.ts +0 -1
- package/dist/cjs/src/components/feature-announcements/types/props.types.d.ts +3 -3
- package/dist/cjs/src/components/feature-announcements/utils/animationHelpers.d.ts +1 -1
- package/dist/cjs/src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.d.ts +7 -0
- package/dist/cjs/src/editor/extensions/plainClipboard/pasteUtils.d.ts +21 -0
- package/dist/esm/components/feature-announcements/FeatureAnnouncementProvider.js +1 -1
- package/dist/esm/components/feature-announcements/FeatureAnnouncementProvider.js.map +1 -1
- package/dist/esm/components/feature-announcements/MajorUpdatePopup.js +1 -1
- package/dist/esm/components/feature-announcements/MajorUpdatePopup.js.map +1 -1
- package/dist/esm/components/feature-announcements/MinorUpdatePopup.js +1 -1
- package/dist/esm/components/feature-announcements/MinorUpdatePopup.js.map +1 -1
- package/dist/esm/components/feature-announcements/utils/animationHelpers.js.map +1 -1
- package/dist/esm/editor/BikEditor.styles.js +6 -0
- package/dist/esm/editor/BikEditor.styles.js.map +1 -1
- package/dist/esm/editor/extensions/buildExtensions.js +1 -1
- package/dist/esm/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/esm/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js +2 -0
- package/dist/esm/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js.map +1 -0
- package/dist/esm/editor/extensions/plainClipboard/PlainClipboardExtension.js +1 -1
- package/dist/esm/editor/extensions/plainClipboard/PlainClipboardExtension.js.map +1 -1
- package/dist/esm/editor/extensions/plainClipboard/pasteUtils.js +2 -0
- package/dist/esm/editor/extensions/plainClipboard/pasteUtils.js.map +1 -0
- package/dist/esm/src/components/bik-layout/MockMenus.d.ts +0 -1
- package/dist/esm/src/components/feature-announcements/types/props.types.d.ts +3 -3
- package/dist/esm/src/components/feature-announcements/utils/animationHelpers.d.ts +1 -1
- package/dist/esm/src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.d.ts +7 -0
- package/dist/esm/src/editor/extensions/plainClipboard/pasteUtils.d.ts +21 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animationHelpers.js","sources":["../../../../../src/components/feature-announcements/utils/animationHelpers.ts"],"sourcesContent":["import { ANIMATION_TIMING } from '../constants';\n\n/**\n * Calculate transform for closing animation\n * @param popupElement - Popup element reference\n * @param targetElement - Target element to animate towards\n * @returns Transform CSS string\n */\nexport const calculateCloseTransform = (\n\tpopupElement: HTMLElement,\n\ttargetElement: Element,\n): string => {\n\tconst popupRect = popupElement.getBoundingClientRect();\n\tconst targetRect = targetElement.getBoundingClientRect();\n\n\tconst translateX =\n\t\ttargetRect.left +\n\t\ttargetRect.width / 2 -\n\t\t(popupRect.left + popupRect.width / 2);\n\tconst translateY =\n\t\ttargetRect.top +\n\t\ttargetRect.height / 2 -\n\t\t(popupRect.top + popupRect.height / 2);\n\n\treturn `translate(${translateX}px, ${translateY}px) scale(0)`;\n};\n\n/**\n * Hide Joyride arrow element\n * @param popupRef - Reference to popup element\n */\nexport const hideJoyrideArrow = (popupRef: HTMLElement | null): void => {\n\tif (!popupRef) return;\n\n\tconst tooltip = popupRef.closest('[class*=\"react-joyride__tooltip\"]');\n\tif (!tooltip) return;\n\n\tconst arrow = tooltip.querySelector(\n\t\t'[class*=\"react-joyride__arrow\"]',\n\t) as HTMLElement;\n\tif (arrow) {\n\t\tarrow.style.display = 'none';\n\t\tarrow.style.visibility = 'hidden';\n\t\tarrow.style.opacity = '0';\n\t}\n};\n\n/**\n * Execute callback after animation completes\n * @param callback - Function to execute\n * @param delay - Optional delay override\n */\nexport const executeAfterAnimation = (\n\tcallback: () => void
|
|
1
|
+
{"version":3,"file":"animationHelpers.js","sources":["../../../../../src/components/feature-announcements/utils/animationHelpers.ts"],"sourcesContent":["import { ANIMATION_TIMING } from '../constants';\n\n/**\n * Calculate transform for closing animation\n * @param popupElement - Popup element reference\n * @param targetElement - Target element to animate towards\n * @returns Transform CSS string\n */\nexport const calculateCloseTransform = (\n\tpopupElement: HTMLElement,\n\ttargetElement: Element,\n): string => {\n\tconst popupRect = popupElement.getBoundingClientRect();\n\tconst targetRect = targetElement.getBoundingClientRect();\n\n\tconst translateX =\n\t\ttargetRect.left +\n\t\ttargetRect.width / 2 -\n\t\t(popupRect.left + popupRect.width / 2);\n\tconst translateY =\n\t\ttargetRect.top +\n\t\ttargetRect.height / 2 -\n\t\t(popupRect.top + popupRect.height / 2);\n\n\treturn `translate(${translateX}px, ${translateY}px) scale(0)`;\n};\n\n/**\n * Hide Joyride arrow element\n * @param popupRef - Reference to popup element\n */\nexport const hideJoyrideArrow = (popupRef: HTMLElement | null): void => {\n\tif (!popupRef) return;\n\n\tconst tooltip = popupRef.closest('[class*=\"react-joyride__tooltip\"]');\n\tif (!tooltip) return;\n\n\tconst arrow = tooltip.querySelector(\n\t\t'[class*=\"react-joyride__arrow\"]',\n\t) as HTMLElement;\n\tif (arrow) {\n\t\tarrow.style.display = 'none';\n\t\tarrow.style.visibility = 'hidden';\n\t\tarrow.style.opacity = '0';\n\t}\n};\n\n/**\n * Execute callback after animation completes\n * @param callback - Function to execute\n * @param delay - Optional delay override\n */\nexport const executeAfterAnimation = (\n\tcallback: () => void | Promise<void>,\n\tdelay: number = ANIMATION_TIMING.CLOSE_DURATION,\n): void => {\n\tsetTimeout(callback, delay);\n};\n"],"names":["calculateCloseTransform","popupElement","targetElement","popupRect","getBoundingClientRect","targetRect","left","width","top","height","hideJoyrideArrow","popupRef","tooltip","closest","arrow","querySelector","style","display","visibility","opacity","executeAfterAnimation","callback","delay","arguments","length","undefined","ANIMATION_TIMING","CLOSE_DURATION","setTimeout"],"mappings":"oEAQaA,EAA0BA,CACtCC,EACAC,KAEA,MAAMC,EAAYF,EAAaG,wBACzBC,EAAaH,EAAcE,wBAWjC,MAAoB,aARnBC,EAAWC,KACXD,EAAWE,MAAQ,GAClBJ,EAAUG,KAAOH,EAAUI,MAAQ,SAEpCF,EAAWG,IACXH,EAAWI,OAAS,GACnBN,EAAUK,IAAML,EAAUM,OAAS,gBAEwB,EAOjDC,EAAoBC,IAChC,IAAKA,EAAU,OAEf,MAAMC,EAAUD,EAASE,QAAQ,qCACjC,IAAKD,EAAS,OAEd,MAAME,EAAQF,EAAQG,cACrB,mCAEGD,IACHA,EAAME,MAAMC,QAAU,OACtBH,EAAME,MAAME,WAAa,SACzBJ,EAAME,MAAMG,QAAU,IACtB,EAQWC,EAAwB,SACpCC,GAES,IADTC,EAAAC,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAgBG,GAAAA,EAAiBC,eAEjCC,WAAWP,EAAUC,EACtB"}
|
|
@@ -17,6 +17,12 @@ import e from"styled-components";import{COLORS as o}from"../constants/Theme.js";
|
|
|
17
17
|
padding: 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* Enter = new paragraph → visible gap. Shift+Enter = <br> inside
|
|
21
|
+
the same paragraph → no gap. Matches Google Docs / Word behavior. */
|
|
22
|
+
p + p {
|
|
23
|
+
margin-top: 4px;
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
ul,
|
|
21
27
|
ol {
|
|
22
28
|
margin: 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BikEditor.styles.js","sources":["../../../src/editor/BikEditor.styles.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '../constants/Theme';\n\nexport const BikEditorShell = styled.div<{\n\tminHeight?: string;\n\tmaxHeight?: string;\n}>`\n\tposition: relative;\n\twidth: 100%;\n\n\t.ProseMirror {\n\t\tmin-height: ${({ minHeight }) => minHeight ?? '80px'};\n\t\tmax-height: ${({ maxHeight }) => maxHeight ?? 'none'};\n\t\toverflow-y: auto;\n\t\toutline: none;\n\t\tpadding: 8px 12px;\n\t\tfont-size: 14px;\n\t\tline-height: 1.5;\n\t\tword-break: break-word;\n\n\t\tp {\n\t\t\tmargin: 0;\n\t\t\tpadding: 0;\n\t\t}\n\n\t\tul,\n\t\tol {\n\t\t\tmargin: 0;\n\t\t\tpadding-left: 1.5em;\n\t\t}\n\n\t\tli + li {\n\t\t\tmargin-top: 2px;\n\t\t}\n\n\t\tp.is-editor-empty:first-child::before {\n\t\t\tcontent: attr(data-placeholder);\n\t\t\tfloat: left;\n\t\t\tcolor: #adb5bd;\n\t\t\tpointer-events: none;\n\t\t\theight: 0;\n\t\t}\n\t}\n\n\t.bik-mention {\n\t\tcolor: ${COLORS.content.brand};\n\t\tpadding: 1px 4px;\n\t}\n\t.bik-mention--team {\n\t\tcolor: ${COLORS.content.brand};\n\t}\n\t.bik-variable {\n\t}\n\n\ta,\n\t.bik-link {\n\t\tcolor: #4f46e5;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: #a5b4fc;\n\t\ttext-underline-offset: 2px;\n\t\tcursor: pointer;\n\t\t&:hover {\n\t\t\tcolor: #3730a3;\n\t\t\ttext-decoration-color: #6366f1;\n\t\t}\n\t}\n`;\n"],"names":["BikEditorShell","styled","div","_ref","minHeight","_ref2","maxHeight","COLORS","content","brand"],"mappings":"gFAGaA,MAAAA,EAAiBC,EAAOC,GAGnC;;;;;gBAKcC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;gBACtCC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM
|
|
1
|
+
{"version":3,"file":"BikEditor.styles.js","sources":["../../../src/editor/BikEditor.styles.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '../constants/Theme';\n\nexport const BikEditorShell = styled.div<{\n\tminHeight?: string;\n\tmaxHeight?: string;\n}>`\n\tposition: relative;\n\twidth: 100%;\n\n\t.ProseMirror {\n\t\tmin-height: ${({ minHeight }) => minHeight ?? '80px'};\n\t\tmax-height: ${({ maxHeight }) => maxHeight ?? 'none'};\n\t\toverflow-y: auto;\n\t\toutline: none;\n\t\tpadding: 8px 12px;\n\t\tfont-size: 14px;\n\t\tline-height: 1.5;\n\t\tword-break: break-word;\n\n\t\tp {\n\t\t\tmargin: 0;\n\t\t\tpadding: 0;\n\t\t}\n\n\t\t/* Enter = new paragraph → visible gap. Shift+Enter = <br> inside\n\t\t the same paragraph → no gap. Matches Google Docs / Word behavior. */\n\t\tp + p {\n\t\t\tmargin-top: 4px;\n\t\t}\n\n\t\tul,\n\t\tol {\n\t\t\tmargin: 0;\n\t\t\tpadding-left: 1.5em;\n\t\t}\n\n\t\tli + li {\n\t\t\tmargin-top: 2px;\n\t\t}\n\n\t\tp.is-editor-empty:first-child::before {\n\t\t\tcontent: attr(data-placeholder);\n\t\t\tfloat: left;\n\t\t\tcolor: #adb5bd;\n\t\t\tpointer-events: none;\n\t\t\theight: 0;\n\t\t}\n\t}\n\n\t.bik-mention {\n\t\tcolor: ${COLORS.content.brand};\n\t\tpadding: 1px 4px;\n\t}\n\t.bik-mention--team {\n\t\tcolor: ${COLORS.content.brand};\n\t}\n\t.bik-variable {\n\t}\n\n\ta,\n\t.bik-link {\n\t\tcolor: #4f46e5;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: #a5b4fc;\n\t\ttext-underline-offset: 2px;\n\t\tcursor: pointer;\n\t\t&:hover {\n\t\t\tcolor: #3730a3;\n\t\t\ttext-decoration-color: #6366f1;\n\t\t}\n\t}\n`;\n"],"names":["BikEditorShell","styled","div","_ref","minHeight","_ref2","maxHeight","COLORS","content","brand"],"mappings":"gFAGaA,MAAAA,EAAiBC,EAAOC,GAGnC;;;;;gBAKcC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;gBACtCC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuC3CC,EAAOC,QAAQC;;;;WAIfF,EAAOC,QAAQC;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import o from"@tiptap/extension-character-count";import e from"@tiptap/extension-color";import t from"@tiptap/extension-font-family";import n from"@tiptap/extension-highlight";import i from"@tiptap/extension-image";import r from"@tiptap/extension-link";import a from"@tiptap/extension-placeholder";import s from"@tiptap/extension-subscript";import m from"@tiptap/extension-superscript";import p from"@tiptap/extension-text-align";import{TextStyle as l}from"@tiptap/extension-text-style";import d from"@tiptap/extension-underline";import c from"@tiptap/starter-kit";import{FontSizeExtension as u}from"./FontSizeExtension.js";import{buildAgentMentionExtension as f,buildTeamMentionExtension as h}from"./mention/MentionExtension.js";import{PasteExtension as x}from"./paste/PasteExtension.js";import{ClipboardNormalizationExtension as g}from"./plainClipboard/ClipboardNormalizationExtension.js";import{PlainClipboardExtension as v}from"./plainClipboard/PlainClipboardExtension.js";import{SectionDividerNode as S}from"./sectionDivider/SectionDividerNode.js";import{SendShortcutExtension as C}from"./sendShortcut/SendShortcutExtension.js";import{buildSlashCommandExtension as b}from"./slashCommand/SlashCommandExtension.js";import{VariableDecorationExtension as k}from"./variable/VariableDecorationExtension.js";function j(j){var M,E,P,y,D,w,I,T,z;const N=null!==(E=null===(M=j.features)||void 0===M?void 0:M.richPaste)&&void 0!==E&&E,O=null!==(y=null===(P=j.features)||void 0===P?void 0:P.richTypography)&&void 0!==y&&y,R=null===(D=j.features)||void 0===D?void 0:D.allowedMarks,A=o=>!R||R.includes(o);return[...[c.configure({link:!1,underline:!1,bold:!!A("bold")&&{},italic:!!A("italic")&&{},strike:!!A("strike")&&{},code:!!A("code")&&{}}),...A("underline")?[d]:[],r.extend({addPasteRules:()=>[],addInputRules:()=>[]}).configure({openOnClick:!1,autolink:!1,linkOnPaste:!1,HTMLAttributes:{rel:"noopener noreferrer",class:"bik-link"}}),l,a.configure({placeholder:null!==(w=j.placeholder)&&void 0!==w?w:"Type a message..."}),...j.onPaste?[x.configure({onPaste:j.onPaste})]:[],...N?[g]:[v],C.configure({onSend:j.onSend,sendShortcut:j.sendShortcut,extraShortcuts:null!==(I=j.shortcuts)&&void 0!==I?I:[]}),k,...j.maxCharacters?[o.configure({limit:j.maxCharacters})]:[],S],...[...(null===(T=j.mentions)||void 0===T?void 0:T.agents)?[f(j.mentions.agents,j.onMentionSelected,j.renderMentionItem,j.renderMentionDropdown)]:[],...(null===(z=j.mentions)||void 0===z?void 0:z.teams)?[h(j.mentions.teams,j.onMentionSelected,j.renderMentionItem,j.renderMentionDropdown)]:[],...j.slashCommands?[b(j.slashCommands,j.onSlashCommandSelected,j.renderSlashCommandItem,j.renderSlashCommandDropdown)]:[]],...O?[e,n.configure({multicolor:!0}),t,u,p.configure({types:["heading","paragraph"]}),s,m,i]:[e]]}export{j as buildExtensions};
|
|
2
2
|
//# sourceMappingURL=buildExtensions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildExtensions.js","sources":["../../../../src/editor/extensions/buildExtensions.ts"],"sourcesContent":["import CharacterCount from '@tiptap/extension-character-count';\nimport Color from '@tiptap/extension-color';\nimport FontFamily from '@tiptap/extension-font-family';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport StarterKit from '@tiptap/starter-kit';\nimport type { ReactNode } from 'react';\nimport type {\n\tEditorFeatures,\n\tEditorSnapshot,\n\tKeyboardShortcut,\n\tMentionDropdownRenderProps,\n\tMentionItem,\n\tPasteData,\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../BikEditor.types';\nimport { FontSizeExtension } from './FontSizeExtension';\nimport {\n\tbuildAgentMentionExtension,\n\tbuildTeamMentionExtension,\n} from './mention/MentionExtension';\nimport { PasteExtension } from './paste/PasteExtension';\nimport { PlainClipboardExtension } from './plainClipboard/PlainClipboardExtension';\nimport { SectionDividerNode } from './sectionDivider/SectionDividerNode';\nimport { SendShortcutExtension } from './sendShortcut/SendShortcutExtension';\nimport { buildSlashCommandExtension } from './slashCommand/SlashCommandExtension';\nimport { VariableDecorationExtension } from './variable/VariableDecorationExtension';\n\ninterface ExtensionConfig {\n\tfeatures?: EditorFeatures;\n\tplaceholder?: string;\n\tmaxCharacters?: number;\n\thasSections?: boolean;\n\tmentions?: {\n\t\tagents?: { current: MentionItem[] };\n\t\tteams?: { current: MentionItem[] };\n\t};\n\tslashCommands?: { current: SlashCommandItem[] };\n\tonPaste?: (data: PasteData) => boolean | void;\n\tonSend?: (content: EditorSnapshot) => void;\n\tsendShortcut?:\n\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t| Array<{\n\t\t\t\tkey: string;\n\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t }>;\n\tshortcuts?: KeyboardShortcut[];\n\tonMentionSelected?: (item: MentionItem, char: '@' | '#') => void;\n\tonSlashCommandSelected?: (command: SlashCommandItem) => void;\n\trenderMentionItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderMentionDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\trenderSlashCommandItem?: (\n\t\titem: SlashCommandItem,\n\t\tisActive: boolean,\n\t) => ReactNode;\n\trenderSlashCommandDropdown?: (\n\t\tprops: SlashCommandDropdownRenderProps,\n\t) => ReactNode;\n}\n\nexport function buildExtensions(config: ExtensionConfig) {\n\tconst hasRichPaste = config.features?.richPaste ?? false;\n\tconst hasRichTypography = config.features?.richTypography ?? false;\n\n\t// When allowedMarks is specified only those marks are registered in the schema.\n\t// This disables rendering, keyboard shortcuts AND paste-preservation for the\n\t// excluded marks — all three come for free when the extension is absent.\n\tconst allowedMarks = config.features?.allowedMarks;\n\tconst isMark = (m: 'bold' | 'italic' | 'strike' | 'underline' | 'code') =>\n\t\t!allowedMarks || allowedMarks.includes(m);\n\n\tconst base = [\n\t\t// Exclude Link and Underline from StarterKit — TipTap v3 bundles both.\n\t\t// Without this, two copies of each are registered and the StarterKit copy's\n\t\t// click handler calls window.open even when openOnClick: false is set.\n\t\tStarterKit.configure({\n\t\t\tlink: false,\n\t\t\tunderline: false,\n\t\t\tbold: isMark('bold') ? {} : false,\n\t\t\titalic: isMark('italic') ? {} : false,\n\t\t\tstrike: isMark('strike') ? {} : false,\n\t\t\tcode: isMark('code') ? {} : false,\n\t\t}),\n\t\t...(isMark('underline') ? [Underline] : []),\n\t\t// Extend Link to strip addPasteRules() and addInputRules() so pasting a\n\t\t// URL never creates a hyperlink regardless of autolink/linkOnPaste values.\n\t\tLink.extend({\n\t\t\taddPasteRules: () => [],\n\t\t\taddInputRules: () => [],\n\t\t}).configure({\n\t\t\topenOnClick: false,\n\t\t\tautolink: false,\n\t\t\tlinkOnPaste: false,\n\t\t\tHTMLAttributes: {\n\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\tclass: 'bik-link',\n\t\t\t},\n\t\t}),\n\t\tTextStyle,\n\t\tPlaceholder.configure({\n\t\t\tplaceholder: config.placeholder ?? 'Type a message...',\n\t\t}),\n\t\t// Consumer paste callback runs first. If it returns true the event is\n\t\t// consumed and neither PlainClipboardExtension nor the editor's default\n\t\t// paste handling will run for that event.\n\t\t...(config.onPaste\n\t\t\t? [PasteExtension.configure({ onPaste: config.onPaste })]\n\t\t\t: []),\n\t\t//
|
|
1
|
+
{"version":3,"file":"buildExtensions.js","sources":["../../../../src/editor/extensions/buildExtensions.ts"],"sourcesContent":["import CharacterCount from '@tiptap/extension-character-count';\nimport Color from '@tiptap/extension-color';\nimport FontFamily from '@tiptap/extension-font-family';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport StarterKit from '@tiptap/starter-kit';\nimport type { ReactNode } from 'react';\nimport type {\n\tEditorFeatures,\n\tEditorSnapshot,\n\tKeyboardShortcut,\n\tMentionDropdownRenderProps,\n\tMentionItem,\n\tPasteData,\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../BikEditor.types';\nimport { FontSizeExtension } from './FontSizeExtension';\nimport {\n\tbuildAgentMentionExtension,\n\tbuildTeamMentionExtension,\n} from './mention/MentionExtension';\nimport { PasteExtension } from './paste/PasteExtension';\nimport { ClipboardNormalizationExtension } from './plainClipboard/ClipboardNormalizationExtension';\nimport { PlainClipboardExtension } from './plainClipboard/PlainClipboardExtension';\nimport { SectionDividerNode } from './sectionDivider/SectionDividerNode';\nimport { SendShortcutExtension } from './sendShortcut/SendShortcutExtension';\nimport { buildSlashCommandExtension } from './slashCommand/SlashCommandExtension';\nimport { VariableDecorationExtension } from './variable/VariableDecorationExtension';\n\ninterface ExtensionConfig {\n\tfeatures?: EditorFeatures;\n\tplaceholder?: string;\n\tmaxCharacters?: number;\n\thasSections?: boolean;\n\tmentions?: {\n\t\tagents?: { current: MentionItem[] };\n\t\tteams?: { current: MentionItem[] };\n\t};\n\tslashCommands?: { current: SlashCommandItem[] };\n\tonPaste?: (data: PasteData) => boolean | void;\n\tonSend?: (content: EditorSnapshot) => void;\n\tsendShortcut?:\n\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t| Array<{\n\t\t\t\tkey: string;\n\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t }>;\n\tshortcuts?: KeyboardShortcut[];\n\tonMentionSelected?: (item: MentionItem, char: '@' | '#') => void;\n\tonSlashCommandSelected?: (command: SlashCommandItem) => void;\n\trenderMentionItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderMentionDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\trenderSlashCommandItem?: (\n\t\titem: SlashCommandItem,\n\t\tisActive: boolean,\n\t) => ReactNode;\n\trenderSlashCommandDropdown?: (\n\t\tprops: SlashCommandDropdownRenderProps,\n\t) => ReactNode;\n}\n\nexport function buildExtensions(config: ExtensionConfig) {\n\tconst hasRichPaste = config.features?.richPaste ?? false;\n\tconst hasRichTypography = config.features?.richTypography ?? false;\n\n\t// When allowedMarks is specified only those marks are registered in the schema.\n\t// This disables rendering, keyboard shortcuts AND paste-preservation for the\n\t// excluded marks — all three come for free when the extension is absent.\n\tconst allowedMarks = config.features?.allowedMarks;\n\tconst isMark = (m: 'bold' | 'italic' | 'strike' | 'underline' | 'code') =>\n\t\t!allowedMarks || allowedMarks.includes(m);\n\n\tconst base = [\n\t\t// Exclude Link and Underline from StarterKit — TipTap v3 bundles both.\n\t\t// Without this, two copies of each are registered and the StarterKit copy's\n\t\t// click handler calls window.open even when openOnClick: false is set.\n\t\tStarterKit.configure({\n\t\t\tlink: false,\n\t\t\tunderline: false,\n\t\t\tbold: isMark('bold') ? {} : false,\n\t\t\titalic: isMark('italic') ? {} : false,\n\t\t\tstrike: isMark('strike') ? {} : false,\n\t\t\tcode: isMark('code') ? {} : false,\n\t\t}),\n\t\t...(isMark('underline') ? [Underline] : []),\n\t\t// Extend Link to strip addPasteRules() and addInputRules() so pasting a\n\t\t// URL never creates a hyperlink regardless of autolink/linkOnPaste values.\n\t\tLink.extend({\n\t\t\taddPasteRules: () => [],\n\t\t\taddInputRules: () => [],\n\t\t}).configure({\n\t\t\topenOnClick: false,\n\t\t\tautolink: false,\n\t\t\tlinkOnPaste: false,\n\t\t\tHTMLAttributes: {\n\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\tclass: 'bik-link',\n\t\t\t},\n\t\t}),\n\t\tTextStyle,\n\t\tPlaceholder.configure({\n\t\t\tplaceholder: config.placeholder ?? 'Type a message...',\n\t\t}),\n\t\t// Consumer paste callback runs first. If it returns true the event is\n\t\t// consumed and neither PlainClipboardExtension nor the editor's default\n\t\t// paste handling will run for that event.\n\t\t...(config.onPaste\n\t\t\t? [PasteExtension.configure({ onPaste: config.onPaste })]\n\t\t\t: []),\n\t\t// Non-rich editors: strip rich marks + normalize blanks on paste.\n\t\t// Rich editors (email): only normalize blanks (fix Google Docs spacing).\n\t\t...(!hasRichPaste\n\t\t\t? [PlainClipboardExtension]\n\t\t\t: [ClipboardNormalizationExtension]),\n\t\tSendShortcutExtension.configure({\n\t\t\tonSend: config.onSend,\n\t\t\tsendShortcut: config.sendShortcut,\n\t\t\textraShortcuts: config.shortcuts ?? [],\n\t\t}),\n\t\tVariableDecorationExtension,\n\t\t...(config.maxCharacters\n\t\t\t? [CharacterCount.configure({ limit: config.maxCharacters })]\n\t\t\t: []),\n\t\t// Always register SectionDividerNode so the custom <div data-section-divider>\n\t\t// node is part of the schema in every editor instance. This means imperative\n\t\t// callers (setBodyAndSections / setSectionContent) work even when no\n\t\t// `sections` prop was provided at mount time.\n\t\tSectionDividerNode,\n\t];\n\n\tconst mentionExtensions = [\n\t\t...(config.mentions?.agents\n\t\t\t? [\n\t\t\t\t\tbuildAgentMentionExtension(\n\t\t\t\t\t\tconfig.mentions.agents,\n\t\t\t\t\t\tconfig.onMentionSelected,\n\t\t\t\t\t\tconfig.renderMentionItem,\n\t\t\t\t\t\tconfig.renderMentionDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t\t...(config.mentions?.teams\n\t\t\t? [\n\t\t\t\t\tbuildTeamMentionExtension(\n\t\t\t\t\t\tconfig.mentions.teams,\n\t\t\t\t\t\tconfig.onMentionSelected,\n\t\t\t\t\t\tconfig.renderMentionItem,\n\t\t\t\t\t\tconfig.renderMentionDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t\t...(config.slashCommands\n\t\t\t? [\n\t\t\t\t\tbuildSlashCommandExtension(\n\t\t\t\t\t\tconfig.slashCommands,\n\t\t\t\t\t\tconfig.onSlashCommandSelected,\n\t\t\t\t\t\tconfig.renderSlashCommandItem,\n\t\t\t\t\t\tconfig.renderSlashCommandDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t];\n\n\tconst richExtensions = hasRichTypography\n\t\t? [\n\t\t\t\tColor,\n\t\t\t\tHighlight.configure({ multicolor: true }),\n\t\t\t\tFontFamily,\n\t\t\t\tFontSizeExtension,\n\t\t\t\tTextAlign.configure({ types: ['heading', 'paragraph'] }),\n\t\t\t\tSubscript,\n\t\t\t\tSuperscript,\n\t\t\t\tImage,\n\t\t ]\n\t\t: [Color];\n\n\treturn [...base, ...mentionExtensions, ...richExtensions];\n}\n"],"names":["buildExtensions","config","hasRichPaste","_b","_a","features","richPaste","hasRichTypography","_d","_c","richTypography","allowedMarks","_e","isMark","m","includes","StarterKit","configure","link","underline","bold","italic","strike","code","Underline","Link","extend","addPasteRules","addInputRules","openOnClick","autolink","linkOnPaste","HTMLAttributes","rel","class","TextStyle","Placeholder","placeholder","_f","onPaste","PasteExtension","ClipboardNormalizationExtension","PlainClipboardExtension","SendShortcutExtension","onSend","sendShortcut","extraShortcuts","_g","shortcuts","VariableDecorationExtension","maxCharacters","CharacterCount","limit","SectionDividerNode","_h","mentions","agents","buildAgentMentionExtension","onMentionSelected","renderMentionItem","renderMentionDropdown","_j","teams","buildTeamMentionExtension","slashCommands","buildSlashCommandExtension","onSlashCommandSelected","renderSlashCommandItem","renderSlashCommandDropdown","Color","Highlight","multicolor","FontFamily","FontSizeExtension","TextAlign","types","Subscript","Superscript","Image"],"mappings":"0xCAqEM,SAAUA,EAAgBC,yBAC/B,MAAMC,EAA6C,QAA9BC,EAAiB,QAAjBC,EAAAH,EAAOI,gBAAU,IAAAD,OAAA,EAAAA,EAAAE,iBAAa,IAAAH,GAAAA,EAC7CI,EAAuD,QAAnCC,EAAiB,QAAjBC,EAAAR,EAAOI,gBAAU,IAAAI,OAAA,EAAAA,EAAAC,sBAAkB,IAAAF,GAAAA,EAKvDG,EAA8B,QAAfC,EAAAX,EAAOI,gBAAQ,IAAAO,OAAA,EAAAA,EAAED,aAChCE,EAAUC,IACdH,GAAgBA,EAAaI,SAASD,GA0GxC,MAAO,IAxGM,CAIZE,EAAWC,UAAU,CACpBC,MAAM,EACNC,WAAW,EACXC,OAAMP,EAAO,SAAU,CAAE,EACzBQ,SAAQR,EAAO,WAAY,CAAE,EAC7BS,SAAQT,EAAO,WAAY,CAAE,EAC7BU,OAAMV,EAAO,SAAU,CAAE,OAEtBA,EAAO,aAAe,CAACW,GAAa,GAGxCC,EAAKC,OAAO,CACXC,cAAeA,IAAM,GACrBC,cAAeA,IAAM,KACnBX,UAAU,CACZY,aAAa,EACbC,UAAU,EACVC,aAAa,EACbC,eAAgB,CACfC,IAAK,sBACLC,MAAO,cAGTC,EACAC,EAAYnB,UAAU,CACrBoB,oBAAaC,EAAArC,EAAOoC,2BAAe,yBAKhCpC,EAAOsC,QACR,CAACC,EAAevB,UAAU,CAAEsB,QAAStC,EAAOsC,WAC5C,MAGErC,EAEF,CAACuC,GADD,CAACC,GAEJC,EAAsB1B,UAAU,CAC/B2B,OAAQ3C,EAAO2C,OACfC,aAAc5C,EAAO4C,aACrBC,uBAAgBC,EAAA9C,EAAO+C,yBAAa,KAErCC,KACIhD,EAAOiD,cACR,CAACC,EAAelC,UAAU,CAAEmC,MAAOnD,EAAOiD,iBAC1C,GAKHG,MAGyB,aACrBC,EAAArD,EAAOsD,+BAAUC,QAClB,CACAC,EACCxD,EAAOsD,SAASC,OAChBvD,EAAOyD,kBACPzD,EAAO0D,kBACP1D,EAAO2D,wBAGR,eACCC,EAAA5D,EAAOsD,+BAAUO,OAClB,CACAC,EACC9D,EAAOsD,SAASO,MAChB7D,EAAOyD,kBACPzD,EAAO0D,kBACP1D,EAAO2D,wBAGR,MACC3D,EAAO+D,cACR,CACAC,EACChE,EAAO+D,cACP/D,EAAOiE,uBACPjE,EAAOkE,uBACPlE,EAAOmE,6BAGR,OAGmB7D,EACpB,CACA8D,EACAC,EAAUrD,UAAU,CAAEsD,YAAY,IAClCC,EACAC,EACAC,EAAUzD,UAAU,CAAE0D,MAAO,CAAC,UAAW,eACzCC,EACAC,EACAC,GAEA,CAACT,GAGL"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Extension as t}from"../../../node_modules/@tiptap/core/dist/index.js";import{DOMParser as e,Slice as r}from"@tiptap/pm/model";import{Plugin as o}from"@tiptap/pm/state";import{BLOCK_SELECTOR as i,cleanBlockBrs as a,normalizeBlanks as n}from"./pasteUtils.js";const l=t.create({name:"clipboardNormalization",addProseMirrorPlugins:()=>[new o({props:{handlePaste(t,o){var l,p,d;if(null===(p=null===(l=o.clipboardData)||void 0===l?void 0:l.files)||void 0===p?void 0:p.length)return!1;const s=null===(d=o.clipboardData)||void 0===d?void 0:d.getData("text/html");if(!s)return!1;if(s.includes("data-pm-slice"))return!1;const c=document.createElement("div");if(c.innerHTML=s,!c.querySelector(i))return!1;a(c);const m=t.state.schema,u=e.fromSchema(m).parseSlice(c),f=n(u.content),v=new r(f,u.openStart,u.openEnd);return t.dispatch(t.state.tr.replaceSelection(v)),!0}}})]});export{l as ClipboardNormalizationExtension};
|
|
2
|
+
//# sourceMappingURL=ClipboardNormalizationExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClipboardNormalizationExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport { DOMParser as ProseMirrorDOMParser, Slice } from '@tiptap/pm/model';\nimport { Plugin } from '@tiptap/pm/state';\nimport { BLOCK_SELECTOR, cleanBlockBrs, normalizeBlanks } from './pasteUtils';\n\n/**\n * Lightweight paste normalizer for rich-paste editors (email).\n * Fixes Google Docs' standalone `<br>` between paragraphs and collapses\n * consecutive empty paragraphs — but keeps ALL formatting marks intact.\n */\nexport const ClipboardNormalizationExtension = Extension.create({\n\tname: 'clipboardNormalization',\n\taddProseMirrorPlugins() {\n\t\treturn [\n\t\t\tnew Plugin({\n\t\t\t\tprops: {\n\t\t\t\t\thandlePaste(_view, event) {\n\t\t\t\t\t\tif (event.clipboardData?.files?.length) return false;\n\t\t\t\t\t\tconst html = event.clipboardData?.getData('text/html');\n\t\t\t\t\t\tif (!html) return false;\n\t\t\t\t\t\tif (html.includes('data-pm-slice')) return false;\n\n\t\t\t\t\t\tconst container = document.createElement('div');\n\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\tif (!container.querySelector(BLOCK_SELECTOR)) return false;\n\n\t\t\t\t\t\tcleanBlockBrs(container);\n\t\t\t\t\t\tconst schema = _view.state.schema;\n\t\t\t\t\t\tconst parsed =\n\t\t\t\t\t\t\tProseMirrorDOMParser.fromSchema(schema).parseSlice(container);\n\t\t\t\t\t\tconst cleaned = normalizeBlanks(parsed.content);\n\t\t\t\t\t\tconst slice = new Slice(cleaned, parsed.openStart, parsed.openEnd);\n\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\t},\n});\n"],"names":["ClipboardNormalizationExtension","Extension","create","name","addProseMirrorPlugins","Plugin","props","handlePaste","_view","event","_b","clipboardData","_a","files","length","html","_c","getData","includes","container","document","createElement","innerHTML","querySelector","BLOCK_SELECTOR","cleanBlockBrs","schema","state","parsed","ProseMirrorDOMParser","fromSchema","parseSlice","cleaned","normalizeBlanks","content","slice","Slice","openStart","openEnd","dispatch","tr","replaceSelection"],"mappings":"8QAUaA,EAAkCC,EAAUC,OAAO,CAC/DC,KAAM,yBACNC,sBAAqBA,IACb,CACN,IAAIC,EAAO,CACVC,MAAO,CACNC,YAAYC,EAAOC,aAClB,WAAIC,EAAqB,UAArBD,EAAME,qBAAe,IAAAC,OAAA,EAAAA,EAAAC,4BAAOC,OAAQ,OAAO,EAC/C,MAAMC,EAA0B,QAAnBC,EAAAP,EAAME,qBAAa,IAAAK,OAAA,EAAAA,EAAEC,QAAQ,aAC1C,IAAKF,EAAM,OAAO,EAClB,GAAIA,EAAKG,SAAS,iBAAkB,OAAO,EAE3C,MAAMC,EAAYC,SAASC,cAAc,OAEzC,GADAF,EAAUG,UAAYP,GACjBI,EAAUI,cAAcC,GAAiB,OAAO,EAErDC,EAAcN,GACd,MAAMO,EAASlB,EAAMmB,MAAMD,OACrBE,EACLC,EAAqBC,WAAWJ,GAAQK,WAAWZ,GAC9Ca,EAAUC,EAAgBL,EAAOM,SACjCC,EAAQ,IAAIC,EAAMJ,EAASJ,EAAOS,UAAWT,EAAOU,SAE1D,OADA9B,EAAM+B,SAAS/B,EAAMmB,MAAMa,GAAGC,iBAAiBN,KACxC,CACR"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Extension as t}from"../../../node_modules/@tiptap/core/dist/index.js";import{DOMParser as e,Slice as
|
|
1
|
+
import{Extension as t}from"../../../node_modules/@tiptap/core/dist/index.js";import{DOMParser as e,Slice as r,Fragment as a}from"@tiptap/pm/model";import{Plugin as o}from"@tiptap/pm/state";import{BLOCK_SELECTOR as i,cleanBlockBrs as n,normalizeBlanks as l,stripRichMarks as p}from"./pasteUtils.js";const d=t.create({name:"plainClipboard",addProseMirrorPlugins:()=>[new o({props:{handlePaste(t,o){var d,s,c,m;if(null===(s=null===(d=o.clipboardData)||void 0===d?void 0:d.files)||void 0===s?void 0:s.length)return!1;const u=null===(c=o.clipboardData)||void 0===c?void 0:c.getData("text/html"),f=null===(m=o.clipboardData)||void 0===m?void 0:m.getData("text/plain");if(!f)return!1;if(null==u?void 0:u.includes("data-pm-slice"))return!1;const v=t.state.schema;if(u){const a=document.createElement("div");a.innerHTML=u;if(a.querySelector(i)){n(a);const o=e.fromSchema(v).parseSlice(a),i=l(p(o.content)),d=new r(i,o.openStart,o.openEnd);return t.dispatch(t.state.tr.replaceSelection(d)),!0}}const h=f.split("\n").map((t=>v.node("paragraph",null,t?[v.text(t)]:[]))),S=new r(a.fromArray(h),1,1);return t.dispatch(t.state.tr.replaceSelection(S)),!0}}})]});export{d as PlainClipboardExtension};
|
|
2
2
|
//# sourceMappingURL=PlainClipboardExtension.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlainClipboardExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/PlainClipboardExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport {\n\tFragment,\n\
|
|
1
|
+
{"version":3,"file":"PlainClipboardExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/PlainClipboardExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport {\n\tFragment,\n\tDOMParser as ProseMirrorDOMParser,\n\tSlice,\n} from '@tiptap/pm/model';\nimport { Plugin } from '@tiptap/pm/state';\nimport {\n\tBLOCK_SELECTOR,\n\tcleanBlockBrs,\n\tnormalizeBlanks,\n\tstripRichMarks,\n} from './pasteUtils';\n\nexport const PlainClipboardExtension = Extension.create({\n\tname: 'plainClipboard',\n\taddProseMirrorPlugins() {\n\t\treturn [\n\t\t\tnew Plugin({\n\t\t\t\tprops: {\n\t\t\t\t\thandlePaste(_view, event) {\n\t\t\t\t\t\tif (event.clipboardData?.files?.length) return false;\n\t\t\t\t\t\tconst html = event.clipboardData?.getData('text/html');\n\t\t\t\t\t\tconst text = event.clipboardData?.getData('text/plain');\n\t\t\t\t\t\tif (!text) return false;\n\n\t\t\t\t\t\tif (html?.includes('data-pm-slice')) return false;\n\n\t\t\t\t\t\tconst schema = _view.state.schema;\n\n\t\t\t\t\t\tif (html) {\n\t\t\t\t\t\t\tconst container = document.createElement('div');\n\t\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\t\tconst hasBlocks = container.querySelector(BLOCK_SELECTOR);\n\t\t\t\t\t\t\tif (hasBlocks) {\n\t\t\t\t\t\t\t\tcleanBlockBrs(container);\n\t\t\t\t\t\t\t\tconst parsed =\n\t\t\t\t\t\t\t\t\tProseMirrorDOMParser.fromSchema(schema).parseSlice(container);\n\t\t\t\t\t\t\t\tconst cleaned = normalizeBlanks(stripRichMarks(parsed.content));\n\t\t\t\t\t\t\t\tconst slice = new Slice(\n\t\t\t\t\t\t\t\t\tcleaned,\n\t\t\t\t\t\t\t\t\tparsed.openStart,\n\t\t\t\t\t\t\t\t\tparsed.openEnd,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst paragraphs = text\n\t\t\t\t\t\t\t.split('\\n')\n\t\t\t\t\t\t\t.map((line) =>\n\t\t\t\t\t\t\t\tschema.node('paragraph', null, line ? [schema.text(line)] : []),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tconst slice = new Slice(Fragment.fromArray(paragraphs), 1, 1);\n\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\t},\n});\n"],"names":["PlainClipboardExtension","Extension","create","name","addProseMirrorPlugins","Plugin","props","handlePaste","_view","event","_b","clipboardData","_a","files","length","html","_c","getData","text","_d","includes","schema","state","container","document","createElement","innerHTML","querySelector","BLOCK_SELECTOR","cleanBlockBrs","parsed","ProseMirrorDOMParser","fromSchema","parseSlice","cleaned","normalizeBlanks","stripRichMarks","content","slice","Slice","openStart","openEnd","dispatch","tr","replaceSelection","paragraphs","split","map","line","node","Fragment","fromArray"],"mappings":"gTAcaA,EAA0BC,EAAUC,OAAO,CACvDC,KAAM,iBACNC,sBAAqBA,IACb,CACN,IAAIC,EAAO,CACVC,MAAO,CACNC,YAAYC,EAAOC,eAClB,WAAIC,EAAqB,UAArBD,EAAME,qBAAe,IAAAC,OAAA,EAAAA,EAAAC,4BAAOC,OAAQ,OAAO,EAC/C,MAAMC,EAA0B,QAAnBC,EAAAP,EAAME,qBAAa,IAAAK,OAAA,EAAAA,EAAEC,QAAQ,aACpCC,EAA0B,QAAnBC,EAAAV,EAAME,qBAAa,IAAAQ,OAAA,EAAAA,EAAEF,QAAQ,cAC1C,IAAKC,EAAM,OAAO,EAElB,GAAIH,aAAI,EAAJA,EAAMK,SAAS,iBAAkB,OAAO,EAE5C,MAAMC,EAASb,EAAMc,MAAMD,OAE3B,GAAIN,EAAM,CACT,MAAMQ,EAAYC,SAASC,cAAc,OACzCF,EAAUG,UAAYX,EAEtB,GADkBQ,EAAUI,cAAcC,GAC3B,CACdC,EAAcN,GACd,MAAMO,EACLC,EAAqBC,WAAWX,GAAQY,WAAWV,GAC9CW,EAAUC,EAAgBC,EAAeN,EAAOO,UAChDC,EAAQ,IAAIC,EACjBL,EACAJ,EAAOU,UACPV,EAAOW,SAGR,OADAjC,EAAMkC,SAASlC,EAAMc,MAAMqB,GAAGC,iBAAiBN,KACxC,CACP,CACD,CAED,MAAMO,EAAa3B,EACjB4B,MAAM,MACNC,KAAKC,GACL3B,EAAO4B,KAAK,YAAa,KAAMD,EAAO,CAAC3B,EAAOH,KAAK8B,IAAS,MAExDV,EAAQ,IAAIC,EAAMW,EAASC,UAAUN,GAAa,EAAG,GAE3D,OADArC,EAAMkC,SAASlC,EAAMc,MAAMqB,GAAGC,iBAAiBN,KACxC,CACR"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Fragment as e}from"@tiptap/pm/model";const t=new Set(["P","LI","H1","H2","H3","H4","H5","H6","TD","TH","PRE"]),r="p,div,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre",n=new Set(["bold","italic","strike","underline","code"]);function o(e){const r=Array.from(e.querySelectorAll("br"));for(const n of r){let r=!1,o=n.parentElement;for(;o&&o!==e;){if(t.has(o.tagName)){r=!0;break}o=o.parentElement}r||n.parentElement.replaceChild(document.createElement("p"),n)}}function a(t){const r=[];let n=!1;return t.forEach((e=>{var t;if("paragraph"===e.type.name&&1===e.childCount&&"hardBreak"===(null===(t=e.firstChild)||void 0===t?void 0:t.type.name))return n||r.push(e.type.create(e.attrs)),void(n=!0);const o="paragraph"===e.type.name&&0===e.childCount;o&&n||(n=o,e.isBlock&&!e.isLeaf?r.push(e.copy(a(e.content))):r.push(e))})),e.from(r)}function l(t){const r=[];return t.forEach((e=>{if(e.isText){const t=e.marks.filter((e=>n.has(e.type.name)));r.push(t.length===e.marks.length?e:e.mark(t))}else r.push(e.copy(l(e.content)))})),e.from(r)}export{r as BLOCK_SELECTOR,t as TEXTBLOCK_TAGS,o as cleanBlockBrs,a as normalizeBlanks,l as stripRichMarks};
|
|
2
|
+
//# sourceMappingURL=pasteUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pasteUtils.js","sources":["../../../../../src/editor/extensions/plainClipboard/pasteUtils.ts"],"sourcesContent":["import { Fragment, Node as PMNode } from '@tiptap/pm/model';\n\nexport const TEXTBLOCK_TAGS = new Set([\n\t'P',\n\t'LI',\n\t'H1',\n\t'H2',\n\t'H3',\n\t'H4',\n\t'H5',\n\t'H6',\n\t'TD',\n\t'TH',\n\t'PRE',\n]);\n\nexport const BLOCK_SELECTOR =\n\t'p,div,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre';\n\nconst BASIC_MARKS = new Set(['bold', 'italic', 'strike', 'underline', 'code']);\n\n/**\n * Replace `<br>` elements that sit at block level (not inside a textblock\n * like `<p>`, `<li>`, etc.) with empty `<p></p>` elements. Google Docs\n * puts standalone `<br>` tags between paragraphs to represent blank lines.\n * Without this, ProseMirror parses them as top-level hardBreak nodes.\n */\nexport function cleanBlockBrs(container: HTMLElement): void {\n\tconst brs = Array.from(container.querySelectorAll('br'));\n\tfor (const br of brs) {\n\t\tlet insideTextblock = false;\n\t\tlet el = br.parentElement;\n\t\twhile (el && el !== container) {\n\t\t\tif (TEXTBLOCK_TAGS.has(el.tagName)) {\n\t\t\t\tinsideTextblock = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tel = el.parentElement;\n\t\t}\n\t\tif (!insideTextblock) {\n\t\t\tbr.parentElement!.replaceChild(document.createElement('p'), br);\n\t\t}\n\t}\n}\n\n/**\n * 1. Convert paragraphs containing only a hard_break into empty paragraphs.\n * 2. Collapse consecutive empty paragraphs into one.\n */\nexport function normalizeBlanks(fragment: Fragment): Fragment {\n\tconst nodes: PMNode[] = [];\n\tlet prevEmpty = false;\n\tfragment.forEach((node) => {\n\t\tconst isHardBreakOnly =\n\t\t\tnode.type.name === 'paragraph' &&\n\t\t\tnode.childCount === 1 &&\n\t\t\tnode.firstChild?.type.name === 'hardBreak';\n\t\tif (isHardBreakOnly) {\n\t\t\tif (!prevEmpty) nodes.push(node.type.create(node.attrs));\n\t\t\tprevEmpty = true;\n\t\t\treturn;\n\t\t}\n\t\tconst isEmpty = node.type.name === 'paragraph' && node.childCount === 0;\n\t\tif (isEmpty && prevEmpty) return;\n\t\tprevEmpty = isEmpty;\n\t\tif (node.isBlock && !node.isLeaf) {\n\t\t\tnodes.push(node.copy(normalizeBlanks(node.content)));\n\t\t} else {\n\t\t\tnodes.push(node);\n\t\t}\n\t});\n\treturn Fragment.from(nodes);\n}\n\n/**\n * Strip only \"rich\" marks (link, textStyle, highlight, etc.) while keeping\n * basic formatting marks (bold, italic, strike, underline, code) that\n * messaging channels can represent.\n */\nexport function stripRichMarks(fragment: Fragment): Fragment {\n\tconst nodes: PMNode[] = [];\n\tfragment.forEach((node) => {\n\t\tif (node.isText) {\n\t\t\tconst kept = node.marks.filter((m) => BASIC_MARKS.has(m.type.name));\n\t\t\tnodes.push(kept.length === node.marks.length ? node : node.mark(kept));\n\t\t} else {\n\t\t\tnodes.push(node.copy(stripRichMarks(node.content)));\n\t\t}\n\t});\n\treturn Fragment.from(nodes);\n}\n"],"names":["TEXTBLOCK_TAGS","Set","BLOCK_SELECTOR","BASIC_MARKS","cleanBlockBrs","container","brs","Array","from","querySelectorAll","br","insideTextblock","el","parentElement","has","tagName","replaceChild","document","createElement","normalizeBlanks","fragment","nodes","prevEmpty","forEach","node","type","name","childCount","_a","firstChild","push","create","attrs","isEmpty","isBlock","isLeaf","copy","content","Fragment","stripRichMarks","isText","kept","marks","filter","m","length","mark"],"mappings":"4CAEaA,MAAAA,EAAiB,IAAIC,IAAI,CACrC,IACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,QAGYC,EACZ,wDAEKC,EAAc,IAAIF,IAAI,CAAC,OAAQ,SAAU,SAAU,YAAa,SAQhE,SAAUG,EAAcC,GAC7B,MAAMC,EAAMC,MAAMC,KAAKH,EAAUI,iBAAiB,OAClD,IAAK,MAAMC,KAAMJ,EAAK,CACrB,IAAIK,GAAkB,EAClBC,EAAKF,EAAGG,cACZ,KAAOD,GAAMA,IAAOP,GAAW,CAC9B,GAAIL,EAAec,IAAIF,EAAGG,SAAU,CACnCJ,GAAkB,EAClB,KACA,CACDC,EAAKA,EAAGC,aACR,CACIF,GACJD,EAAGG,cAAeG,aAAaC,SAASC,cAAc,KAAMR,EAE7D,CACF,CAMM,SAAUS,EAAgBC,GAC/B,MAAMC,EAAkB,GACxB,IAAIC,GAAY,EAoBhB,OAnBAF,EAASG,SAASC,UAKjB,GAHoB,cAAnBA,EAAKC,KAAKC,MACU,IAApBF,EAAKG,YAC0B,eAAhB,QAAfC,EAAAJ,EAAKK,kBAAU,IAAAD,OAAA,EAAAA,EAAEH,KAAKC,MAItB,OAFKJ,GAAWD,EAAMS,KAAKN,EAAKC,KAAKM,OAAOP,EAAKQ,aACjDV,GAAY,GAGb,MAAMW,EAA6B,cAAnBT,EAAKC,KAAKC,MAA4C,IAApBF,EAAKG,WACnDM,GAAWX,IACfA,EAAYW,EACRT,EAAKU,UAAYV,EAAKW,OACzBd,EAAMS,KAAKN,EAAKY,KAAKjB,EAAgBK,EAAKa,WAE1ChB,EAAMS,KAAKN,GACX,IAEKc,EAAS9B,KAAKa,EACtB,CAOM,SAAUkB,EAAenB,GAC9B,MAAMC,EAAkB,GASxB,OARAD,EAASG,SAASC,IACjB,GAAIA,EAAKgB,OAAQ,CAChB,MAAMC,EAAOjB,EAAKkB,MAAMC,QAAQC,GAAMzC,EAAYW,IAAI8B,EAAEnB,KAAKC,QAC7DL,EAAMS,KAAKW,EAAKI,SAAWrB,EAAKkB,MAAMG,OAASrB,EAAOA,EAAKsB,KAAKL,GAChE,MACApB,EAAMS,KAAKN,EAAKY,KAAKG,EAAef,EAAKa,UACzC,IAEKC,EAAS9B,KAAKa,EACtB"}
|
|
@@ -9,12 +9,12 @@ export interface PopupBaseProps {
|
|
|
9
9
|
feature: FeatureAnnouncement;
|
|
10
10
|
currentIndex: number;
|
|
11
11
|
totalFeatures: number;
|
|
12
|
-
onSkip: () => void;
|
|
13
|
-
onExplore: () => void;
|
|
12
|
+
onSkip: () => Promise<void> | void;
|
|
13
|
+
onExplore: (triggeredAction?: string) => void;
|
|
14
14
|
onPrevious: () => void;
|
|
15
15
|
onNext: () => void;
|
|
16
16
|
setIsClosing?: (isClosing: boolean) => void;
|
|
17
|
-
onSecondaryAction?: () => void;
|
|
17
|
+
onSecondaryAction?: () => Promise<void> | void;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Major update popup props
|
|
@@ -15,4 +15,4 @@ export declare const hideJoyrideArrow: (popupRef: HTMLElement | null) => void;
|
|
|
15
15
|
* @param callback - Function to execute
|
|
16
16
|
* @param delay - Optional delay override
|
|
17
17
|
*/
|
|
18
|
-
export declare const executeAfterAnimation: (callback: () => void
|
|
18
|
+
export declare const executeAfterAnimation: (callback: () => void | Promise<void>, delay?: number) => void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight paste normalizer for rich-paste editors (email).
|
|
4
|
+
* Fixes Google Docs' standalone `<br>` between paragraphs and collapses
|
|
5
|
+
* consecutive empty paragraphs — but keeps ALL formatting marks intact.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ClipboardNormalizationExtension: Extension<any, any>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Fragment } from '@tiptap/pm/model';
|
|
2
|
+
export declare const TEXTBLOCK_TAGS: Set<string>;
|
|
3
|
+
export declare const BLOCK_SELECTOR = "p,div,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre";
|
|
4
|
+
/**
|
|
5
|
+
* Replace `<br>` elements that sit at block level (not inside a textblock
|
|
6
|
+
* like `<p>`, `<li>`, etc.) with empty `<p></p>` elements. Google Docs
|
|
7
|
+
* puts standalone `<br>` tags between paragraphs to represent blank lines.
|
|
8
|
+
* Without this, ProseMirror parses them as top-level hardBreak nodes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function cleanBlockBrs(container: HTMLElement): void;
|
|
11
|
+
/**
|
|
12
|
+
* 1. Convert paragraphs containing only a hard_break into empty paragraphs.
|
|
13
|
+
* 2. Collapse consecutive empty paragraphs into one.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeBlanks(fragment: Fragment): Fragment;
|
|
16
|
+
/**
|
|
17
|
+
* Strip only "rich" marks (link, textStyle, highlight, etc.) while keeping
|
|
18
|
+
* basic formatting marks (bold, italic, strike, underline, code) that
|
|
19
|
+
* messaging channels can represent.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stripRichMarks(fragment: Fragment): Fragment;
|