@bikdotai/bik-component-library 0.0.876-beta.1 → 0.0.876-beta.3
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/README.md +1 -0
- package/dist/cjs/components/WhatsAppTextEditor/AIRephraseButton.js +2 -2
- package/dist/cjs/components/WhatsAppTextEditor/AIRephraseButton.js.map +1 -1
- package/dist/cjs/components/WhatsAppTextEditor/WhatsAppTextEditor.js +4 -4
- package/dist/cjs/components/WhatsAppTextEditor/WhatsAppTextEditor.js.map +1 -1
- package/dist/cjs/components/WhatsAppTextEditor/WhatsAppTextEditorHeader.js +2 -2
- package/dist/cjs/components/WhatsAppTextEditor/WhatsAppTextEditorHeader.js.map +1 -1
- package/dist/cjs/components/accordion/Accordion.style.js +1 -1
- package/dist/cjs/components/accordion/Accordion.style.js.map +1 -1
- package/dist/cjs/components/action-button/ActionButton.styled.js +1 -1
- package/dist/cjs/components/action-button/ActionButton.styled.js.map +1 -1
- package/dist/cjs/components/analytics-chips-and-dropdowns/CommonStyles.js +1 -1
- package/dist/cjs/components/analytics-chips-and-dropdowns/CommonStyles.js.map +1 -1
- package/dist/cjs/components/bik-layout/SidebarStyles.js +1 -1
- package/dist/cjs/components/bik-layout/SidebarStyles.js.map +1 -1
- package/dist/cjs/components/button/Button.styled.js +3 -3
- package/dist/cjs/components/button/Button.styled.js.map +1 -1
- package/dist/cjs/components/buttonGroup/ButtonGroupStyle.js +1 -1
- package/dist/cjs/components/buttonGroup/ButtonGroupStyle.js.map +1 -1
- package/dist/cjs/components/card-selector/CardSelector.styled.js +1 -1
- package/dist/cjs/components/card-selector/CardSelector.styled.js.map +1 -1
- package/dist/cjs/components/carousel-preview/CarouselPreview.style.js +2 -2
- package/dist/cjs/components/carousel-preview/CarouselPreview.style.js.map +1 -1
- package/dist/cjs/components/checkBox/CheckBox.styled.js +1 -1
- package/dist/cjs/components/checkBox/CheckBox.styled.js.map +1 -1
- package/dist/cjs/components/dropdown/MenuItem/MenuItem.js +1 -1
- package/dist/cjs/components/dropdown/MenuItem/MenuItem.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/OpennedDropdown.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/OpennedDropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/MenuItem.js +27 -10
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/MenuItem.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/MenuList.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/MenuList.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/SelectAllMenu.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/menu/SelectAllMenu.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/utils/iterationOnOptions.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/utils/iterationOnOptions.js.map +1 -1
- package/dist/cjs/components/dropdown/hooks/useDropdown.js +1 -1
- package/dist/cjs/components/dropdown/hooks/useDropdown.js.map +1 -1
- package/dist/cjs/components/dual-icon-button/DualIconButton.styled.js +2 -2
- package/dist/cjs/components/dual-icon-button/DualIconButton.styled.js.map +1 -1
- package/dist/cjs/components/floating-action-button/FloatingActionButton.styles.js +1 -1
- package/dist/cjs/components/floating-action-button/FloatingActionButton.styles.js.map +1 -1
- package/dist/cjs/components/icon-button/IconButton.styled.js +4 -4
- package/dist/cjs/components/icon-button/IconButton.styled.js.map +1 -1
- package/dist/cjs/components/multi-level-dropdown/MultiLevelDropdown.js +1 -1
- package/dist/cjs/components/multi-level-dropdown/MultiLevelDropdown.js.map +1 -1
- package/dist/cjs/components/multi-level-dropdown/MultiLevelDropdown.styled.js +28 -19
- package/dist/cjs/components/multi-level-dropdown/MultiLevelDropdown.styled.js.map +1 -1
- package/dist/cjs/components/plans/SubscriptionPlanSelector.js +1 -1
- package/dist/cjs/components/plans/SubscriptionPlanSelector.js.map +1 -1
- package/dist/cjs/components/product-picker-v2/style.js +2 -2
- package/dist/cjs/components/product-picker-v2/style.js.map +1 -1
- package/dist/cjs/components/switch/Switch.js +2 -2
- package/dist/cjs/components/switch/Switch.js.map +1 -1
- package/dist/cjs/components/template-preview/RCS/RCSPreview.styled.js +1 -1
- package/dist/cjs/components/template-preview/RCS/RCSPreview.styled.js.map +1 -1
- package/dist/cjs/components/template-preview/WhatsApp/ChatUI.style.js +1 -1
- package/dist/cjs/components/template-preview/WhatsApp/ChatUI.style.js.map +1 -1
- package/dist/esm/components/WhatsAppTextEditor/AIRephraseButton.js +2 -2
- package/dist/esm/components/WhatsAppTextEditor/AIRephraseButton.js.map +1 -1
- package/dist/esm/components/WhatsAppTextEditor/WhatsAppTextEditor.js +4 -4
- package/dist/esm/components/WhatsAppTextEditor/WhatsAppTextEditor.js.map +1 -1
- package/dist/esm/components/WhatsAppTextEditor/WhatsAppTextEditorHeader.js +2 -2
- package/dist/esm/components/WhatsAppTextEditor/WhatsAppTextEditorHeader.js.map +1 -1
- package/dist/esm/components/accordion/Accordion.style.js +1 -1
- package/dist/esm/components/accordion/Accordion.style.js.map +1 -1
- package/dist/esm/components/action-button/ActionButton.styled.js +1 -1
- package/dist/esm/components/action-button/ActionButton.styled.js.map +1 -1
- package/dist/esm/components/analytics-chips-and-dropdowns/CommonStyles.js +1 -1
- package/dist/esm/components/analytics-chips-and-dropdowns/CommonStyles.js.map +1 -1
- package/dist/esm/components/bik-layout/SidebarStyles.js +1 -1
- package/dist/esm/components/bik-layout/SidebarStyles.js.map +1 -1
- package/dist/esm/components/button/Button.styled.js +3 -3
- package/dist/esm/components/button/Button.styled.js.map +1 -1
- package/dist/esm/components/buttonGroup/ButtonGroupStyle.js +1 -1
- package/dist/esm/components/buttonGroup/ButtonGroupStyle.js.map +1 -1
- package/dist/esm/components/card-selector/CardSelector.styled.js +1 -1
- package/dist/esm/components/card-selector/CardSelector.styled.js.map +1 -1
- package/dist/esm/components/carousel-preview/CarouselPreview.style.js +2 -2
- package/dist/esm/components/carousel-preview/CarouselPreview.style.js.map +1 -1
- package/dist/esm/components/checkBox/CheckBox.styled.js +1 -1
- package/dist/esm/components/checkBox/CheckBox.styled.js.map +1 -1
- package/dist/esm/components/dropdown/MenuItem/MenuItem.js +1 -1
- package/dist/esm/components/dropdown/MenuItem/MenuItem.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/OpennedDropdown.js +300 -278
- package/dist/esm/components/dropdown/OpenedDropdown/components/OpennedDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuItem.d.ts +8 -0
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuItem.js +170 -126
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuItem.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuList.d.ts +4 -0
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuList.js +144 -112
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuList.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/SelectAllMenu.d.ts +1 -0
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/SelectAllMenu.js +32 -31
- package/dist/esm/components/dropdown/OpenedDropdown/components/menu/SelectAllMenu.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.d.ts +2 -0
- package/dist/esm/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.js +54 -39
- package/dist/esm/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/utils/iterationOnOptions.d.ts +18 -16
- package/dist/esm/components/dropdown/OpenedDropdown/utils/iterationOnOptions.js +73 -27
- package/dist/esm/components/dropdown/OpenedDropdown/utils/iterationOnOptions.js.map +1 -1
- package/dist/esm/components/dropdown/hooks/useDropdown.d.ts +4 -17
- package/dist/esm/components/dropdown/hooks/useDropdown.js +176 -163
- package/dist/esm/components/dropdown/hooks/useDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/type.d.ts +22 -0
- package/dist/esm/components/dual-icon-button/DualIconButton.styled.js +2 -2
- package/dist/esm/components/dual-icon-button/DualIconButton.styled.js.map +1 -1
- package/dist/esm/components/floating-action-button/FloatingActionButton.styles.js +1 -1
- package/dist/esm/components/floating-action-button/FloatingActionButton.styles.js.map +1 -1
- package/dist/esm/components/icon-button/IconButton.styled.js +4 -4
- package/dist/esm/components/icon-button/IconButton.styled.js.map +1 -1
- package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.js +46 -44
- package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.js.map +1 -1
- package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.styled.d.ts +3 -0
- package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.styled.js +25 -15
- package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.styled.js.map +1 -1
- package/dist/esm/components/multi-level-dropdown/type.d.ts +5 -0
- package/dist/esm/components/plans/SubscriptionPlanSelector.js +1 -1
- package/dist/esm/components/plans/SubscriptionPlanSelector.js.map +1 -1
- package/dist/esm/components/product-picker-v2/style.js +2 -2
- package/dist/esm/components/product-picker-v2/style.js.map +1 -1
- package/dist/esm/components/switch/Switch.js +2 -2
- package/dist/esm/components/switch/Switch.js.map +1 -1
- package/dist/esm/components/template-preview/RCS/RCSPreview.styled.js +1 -1
- package/dist/esm/components/template-preview/RCS/RCSPreview.styled.js.map +1 -1
- package/dist/esm/components/template-preview/WhatsApp/ChatUI.style.js +1 -1
- package/dist/esm/components/template-preview/WhatsApp/ChatUI.style.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
- [Sanitization](docs/sanitization.md) — the HTML/CSS sanitisation layer and what it strips
|
|
10
10
|
- [Editor](docs/editor/01-overview.md) — the rich-text editor: props, ref API, toolbar, email mode, customisation
|
|
11
11
|
- [FunnelChart & ComparisonBarChart](docs/charts/funnel-and-comparison-charts.md) — the analytics charts behind the Helpdesk AI Impact tab: branching funnel geometry, the shared chart card/palette/format helpers, and the zero states
|
|
12
|
+
- [Nested dropdown](docs/nested-dropdown.md) — `childrenLayout="nested"`: children rendered inline with a tri-state parent, collapsible groups, and how the selection payload is shaped
|
|
12
13
|
- [Channel Playground](src/components/channel-playground/README.md) — driving the AI on email / WhatsApp / Instagram: the transport seam, the channel skins, and the stream frame protocol
|
|
13
14
|
- [Frontend Testing Guide](docs/testing/writing-tests.md) — test authoring, linting, mandate exceptions, required status checks
|
|
14
15
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
display: flex;
|
|
19
19
|
align-items: center;
|
|
20
20
|
gap: 4px;
|
|
21
|
-
|
|
21
|
+
:hover {
|
|
22
22
|
filter: brightness(0.98);
|
|
23
23
|
}
|
|
24
24
|
`,T=s.default.button`
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
display: flex;
|
|
70
70
|
align-items: center;
|
|
71
71
|
gap: 8px;
|
|
72
|
-
|
|
72
|
+
:hover {
|
|
73
73
|
background: ${e=>e.selected||e.toneSubmenuOpen?"#d9e8db":"#f7f7f8"};
|
|
74
74
|
}
|
|
75
75
|
${e=>e.isChangeToneRow?`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIRephraseButton.js","sources":["../../../../src/components/WhatsAppTextEditor/AIRephraseButton.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { useOutside } from '@src/hooks/useOutside';\nimport { COLORS } from '@src/constants/Theme';\nimport ChevronDownIcon from '../../assets/icons/chevronDown.svg';\nimport ChevronRightIcon from '../../assets/icons/chevronRight.svg';\nimport EditIcon from '../../assets/icons/edit.svg';\nimport EmojiIcon from '../../assets/icons/emoji.svg';\nimport SparkleIcon from '../../assets/icons/magic-line.svg';\nimport BorderAnimation from './BorderAnimation';\n\nconst AIButtonGroup = styled.div<{ disabled?: boolean }>`\n\tdisplay: flex;\n\talign-items: center;\n\tborder: 1px solid transparent;\n\tborder-radius: 16px;\n\tbackground: #ffe8ef;\n\topacity: ${(props) => (props.disabled ? 0.5 : 1)};\n`;\n\nconst AIButton = styled.button<{ disabled?: boolean }>`\n\tborder: 0;\n\tbackground: #ffe8ef;\n\tcolor: #f53f77;\n\tborder-radius: 16px 0 0 16px;\n\tpadding: 4px 6px;\n\tfont-size: 12px;\n\tfont-weight: 400;\n\tline-height: 16px;\n\tcursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\t&:hover {\n\t\tfilter: brightness(0.98);\n\t}\n`;\n\nconst AIArrowButton = styled.button<{ disabled?: boolean }>`\n\tposition: relative;\n\tborder: 0;\n\tbackground: #ffe8ef;\n\tcolor: #f53f77;\n\tborder-radius: 0 16px 16px 0;\n\tpadding: 4px;\n\tline-height: 1;\n\tcursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};\n\tdisplay: flex;\n\talign-items: center;\n\t/* 12px inset divider, matching Figma (Line 14) */\n\t::before {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\ttop: 50%;\n\t\ttransform: translateY(-50%);\n\t\twidth: 1px;\n\t\theight: 12px;\n\t\tbackground: #f6c8d7;\n\t}\n`;\n\nconst AIDropdownContainer = styled.div`\n\tposition: relative;\n`;\n\nconst AIDropdownMenu = styled.div`\n\tposition: absolute;\n\ttop: calc(100% + 6px);\n\tleft: 0;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 8px;\n\twidth: 209px;\n\tz-index: 10;\n\tbox-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n\tpadding: 4px;\n`;\n\nconst AIDropdownItem = styled.button<{\n\tselected?: boolean;\n\tisInstructions?: boolean;\n\t/** Change tone row: green highlight when tone submenu is open */\n\ttoneSubmenuOpen?: boolean;\n\t/** Change tone row: green text/icon on hover or when submenu open */\n\tisChangeToneRow?: boolean;\n}>`\n\twidth: 100%;\n\ttext-align: left;\n\tborder: 0;\n\tbackground: ${(props) =>\n\t\tprops.selected || props.toneSubmenuOpen ? '#d9e8db' : 'transparent'};\n\tcolor: ${(props) =>\n\t\tprops.selected || props.toneSubmenuOpen\n\t\t\t? '#1e6b34'\n\t\t\t: COLORS.content.primary};\n\tpadding: 10px 10px;\n\tborder-radius: 6px;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\t&:hover {\n\t\tbackground: ${(props) =>\n\t\t\tprops.selected || props.toneSubmenuOpen ? '#d9e8db' : '#f7f7f8'};\n\t}\n\t${(props) =>\n\t\tprops.isChangeToneRow\n\t\t\t? `\n\t\t&:hover {\n\t\t\tcolor: #1e6b34;\n\t\t\tbackground: ${props.toneSubmenuOpen ? '#d9e8db' : '#f7f7f8'};\n\t\t}\n\t`\n\t\t\t: ''}\n`;\n\nconst ToneSubMenu = styled.div`\n\tposition: absolute;\n\ttop: 0;\n\tleft: calc(100% + 4px);\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 8px;\n\tmin-width: 140px;\n\tz-index: 11;\n\tbox-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n\tpadding: 4px;\n`;\n\ntype AIRephraseButtonProps = {\n\tlabel: string;\n\tdisabled?: boolean;\n\tloading?: boolean;\n\thighlighted?: boolean;\n\ttones?: AIActionToneOption[];\n\tselectedToneId?: string;\n\tinstructionActive?: boolean;\n\tonClick?: () => void;\n\tonToneChange?: (toneId: string) => void;\n\tonInstructionsClick?: () => void;\n\tshowSecondaryRephraseOption?: boolean;\n\tonSecondaryRephraseClick?: () => void;\n};\n\nexport const AIRephraseButton = ({\n\tlabel,\n\tdisabled,\n\tloading,\n\thighlighted,\n\ttones,\n\tselectedToneId,\n\tinstructionActive,\n\tonClick,\n\tonToneChange,\n\tonInstructionsClick,\n\tshowSecondaryRephraseOption,\n\tonSecondaryRephraseClick,\n}: AIRephraseButtonProps) => {\n\tconst dropdownRef = useRef<HTMLDivElement>(null);\n\tconst [isDropdownOpen, setIsDropdownOpen] = useState(false);\n\tconst [isToneMenuOpen, setIsToneMenuOpen] = useState(false);\n\tconst isDropdownDisabled = !!instructionActive || !!disabled || !!loading;\n\n\tuseOutside(dropdownRef, () => {\n\t\tsetIsDropdownOpen(false);\n\t\tsetIsToneMenuOpen(false);\n\t});\n\n\tuseEffect(() => {\n\t\tif (!instructionActive) return;\n\t\tsetIsDropdownOpen(false);\n\t\tsetIsToneMenuOpen(false);\n\t}, [instructionActive]);\n\n\treturn (\n\t\t<AIDropdownContainer ref={dropdownRef}>\n\t\t\t<BorderAnimation\n\t\t\t\tshowAnimation={!!highlighted}\n\t\t\t\tdisabled={!!disabled || !!loading}\n\t\t\t\tborderRadius={16}\n\t\t\t\tborderSize={2}\n\t\t\t>\n\t\t\t\t<AIButtonGroup disabled={disabled || loading}>\n\t\t\t\t\t<AIButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={disabled || loading}\n\t\t\t\t\t\tonClick={onClick}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SparkleIcon width={16} height={16} color=\"#f53f77\" />\n\t\t\t\t\t\t{loading ? '...' : label}\n\t\t\t\t\t</AIButton>\n\t\t\t\t\t<AIArrowButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={isDropdownDisabled}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\tsetIsDropdownOpen((prev) => !prev);\n\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronDownIcon width={16} height={16} />\n\t\t\t\t\t</AIArrowButton>\n\t\t\t\t</AIButtonGroup>\n\t\t\t</BorderAnimation>\n\t\t\t{isDropdownOpen ? (\n\t\t\t\t<AIDropdownMenu>\n\t\t\t\t\t{tones?.length ? (\n\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttoneSubmenuOpen={isToneMenuOpen}\n\t\t\t\t\t\t\tisChangeToneRow\n\t\t\t\t\t\t\tonMouseEnter={() => {\n\t\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\t\tsetIsToneMenuOpen(true);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => setIsToneMenuOpen((prev) => !prev)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: 8,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<EmojiIcon width={18} height={18} color=\"currentColor\" />\n\t\t\t\t\t\t\t\t\tChange tone\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<ChevronRightIcon width={14} height={14} color=\"currentColor\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tisInstructions\n\t\t\t\t\t\tselected={!!instructionActive}\n\t\t\t\t\t\tonMouseEnter={() => setIsToneMenuOpen(false)}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\tonInstructionsClick?.();\n\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<EditIcon width={16} height={16} color={COLORS.content.primary} />\n\t\t\t\t\t\tAdd instructions\n\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t{showSecondaryRephraseOption ? (\n\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonMouseEnter={() => setIsToneMenuOpen(false)}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tif (disabled || loading) return;\n\t\t\t\t\t\t\t\tonSecondaryRephraseClick?.();\n\t\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SparkleIcon\n\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\tcolor={COLORS.content.primary}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\tRephrase\n\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{isToneMenuOpen && tones?.length ? (\n\t\t\t\t\t\t<ToneSubMenu>\n\t\t\t\t\t\t\t{tones.map((tone) => (\n\t\t\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\t\t\tkey={tone.id}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tselected={tone.id === selectedToneId}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\t\t\t\tonToneChange?.(tone.id);\n\t\t\t\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{tone.label}\n\t\t\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ToneSubMenu>\n\t\t\t\t\t) : null}\n\t\t\t\t</AIDropdownMenu>\n\t\t\t) : null}\n\t\t</AIDropdownContainer>\n\t);\n};\nexport type AIActionToneOption = {\n\tid: string;\n\tlabel: string;\n};\n"],"names":["AIButtonGroup","styled","props","AIButton","AIArrowButton","AIDropdownContainer","AIDropdownMenu","COLORS","AIDropdownItem","ToneSubMenu","AIRephraseButton","label","disabled","loading","highlighted","tones","selectedToneId","instructionActive","onClick","onToneChange","onInstructionsClick","showSecondaryRephraseOption","onSecondaryRephraseClick","dropdownRef","useRef","isDropdownOpen","setIsDropdownOpen","useState","isToneMenuOpen","setIsToneMenuOpen","isDropdownDisabled","useOutside","useEffect","jsxs","jsx","BorderAnimation","SparkleIcon","prev","ChevronDownIcon","EmojiIcon","ChevronRightIcon","EditIcon","tone"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AIRephraseButton.js","sources":["../../../../src/components/WhatsAppTextEditor/AIRephraseButton.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { useOutside } from '@src/hooks/useOutside';\nimport { COLORS } from '@src/constants/Theme';\nimport ChevronDownIcon from '../../assets/icons/chevronDown.svg';\nimport ChevronRightIcon from '../../assets/icons/chevronRight.svg';\nimport EditIcon from '../../assets/icons/edit.svg';\nimport EmojiIcon from '../../assets/icons/emoji.svg';\nimport SparkleIcon from '../../assets/icons/magic-line.svg';\nimport BorderAnimation from './BorderAnimation';\n\nconst AIButtonGroup = styled.div<{ disabled?: boolean }>`\n\tdisplay: flex;\n\talign-items: center;\n\tborder: 1px solid transparent;\n\tborder-radius: 16px;\n\tbackground: #ffe8ef;\n\topacity: ${(props) => (props.disabled ? 0.5 : 1)};\n`;\n\nconst AIButton = styled.button<{ disabled?: boolean }>`\n\tborder: 0;\n\tbackground: #ffe8ef;\n\tcolor: #f53f77;\n\tborder-radius: 16px 0 0 16px;\n\tpadding: 4px 6px;\n\tfont-size: 12px;\n\tfont-weight: 400;\n\tline-height: 16px;\n\tcursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\t:hover {\n\t\tfilter: brightness(0.98);\n\t}\n`;\n\nconst AIArrowButton = styled.button<{ disabled?: boolean }>`\n\tposition: relative;\n\tborder: 0;\n\tbackground: #ffe8ef;\n\tcolor: #f53f77;\n\tborder-radius: 0 16px 16px 0;\n\tpadding: 4px;\n\tline-height: 1;\n\tcursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};\n\tdisplay: flex;\n\talign-items: center;\n\t/* 12px inset divider, matching Figma (Line 14) */\n\t::before {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\ttop: 50%;\n\t\ttransform: translateY(-50%);\n\t\twidth: 1px;\n\t\theight: 12px;\n\t\tbackground: #f6c8d7;\n\t}\n`;\n\nconst AIDropdownContainer = styled.div`\n\tposition: relative;\n`;\n\nconst AIDropdownMenu = styled.div`\n\tposition: absolute;\n\ttop: calc(100% + 6px);\n\tleft: 0;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 8px;\n\twidth: 209px;\n\tz-index: 10;\n\tbox-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n\tpadding: 4px;\n`;\n\nconst AIDropdownItem = styled.button<{\n\tselected?: boolean;\n\tisInstructions?: boolean;\n\t/** Change tone row: green highlight when tone submenu is open */\n\ttoneSubmenuOpen?: boolean;\n\t/** Change tone row: green text/icon on hover or when submenu open */\n\tisChangeToneRow?: boolean;\n}>`\n\twidth: 100%;\n\ttext-align: left;\n\tborder: 0;\n\tbackground: ${(props) =>\n\t\tprops.selected || props.toneSubmenuOpen ? '#d9e8db' : 'transparent'};\n\tcolor: ${(props) =>\n\t\tprops.selected || props.toneSubmenuOpen\n\t\t\t? '#1e6b34'\n\t\t\t: COLORS.content.primary};\n\tpadding: 10px 10px;\n\tborder-radius: 6px;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\t:hover {\n\t\tbackground: ${(props) =>\n\t\t\tprops.selected || props.toneSubmenuOpen ? '#d9e8db' : '#f7f7f8'};\n\t}\n\t${(props) =>\n\t\tprops.isChangeToneRow\n\t\t\t? `\n\t\t&:hover {\n\t\t\tcolor: #1e6b34;\n\t\t\tbackground: ${props.toneSubmenuOpen ? '#d9e8db' : '#f7f7f8'};\n\t\t}\n\t`\n\t\t\t: ''}\n`;\n\nconst ToneSubMenu = styled.div`\n\tposition: absolute;\n\ttop: 0;\n\tleft: calc(100% + 4px);\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 8px;\n\tmin-width: 140px;\n\tz-index: 11;\n\tbox-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);\n\tpadding: 4px;\n`;\n\ntype AIRephraseButtonProps = {\n\tlabel: string;\n\tdisabled?: boolean;\n\tloading?: boolean;\n\thighlighted?: boolean;\n\ttones?: AIActionToneOption[];\n\tselectedToneId?: string;\n\tinstructionActive?: boolean;\n\tonClick?: () => void;\n\tonToneChange?: (toneId: string) => void;\n\tonInstructionsClick?: () => void;\n\tshowSecondaryRephraseOption?: boolean;\n\tonSecondaryRephraseClick?: () => void;\n};\n\nexport const AIRephraseButton = ({\n\tlabel,\n\tdisabled,\n\tloading,\n\thighlighted,\n\ttones,\n\tselectedToneId,\n\tinstructionActive,\n\tonClick,\n\tonToneChange,\n\tonInstructionsClick,\n\tshowSecondaryRephraseOption,\n\tonSecondaryRephraseClick,\n}: AIRephraseButtonProps) => {\n\tconst dropdownRef = useRef<HTMLDivElement>(null);\n\tconst [isDropdownOpen, setIsDropdownOpen] = useState(false);\n\tconst [isToneMenuOpen, setIsToneMenuOpen] = useState(false);\n\tconst isDropdownDisabled = !!instructionActive || !!disabled || !!loading;\n\n\tuseOutside(dropdownRef, () => {\n\t\tsetIsDropdownOpen(false);\n\t\tsetIsToneMenuOpen(false);\n\t});\n\n\tuseEffect(() => {\n\t\tif (!instructionActive) return;\n\t\tsetIsDropdownOpen(false);\n\t\tsetIsToneMenuOpen(false);\n\t}, [instructionActive]);\n\n\treturn (\n\t\t<AIDropdownContainer ref={dropdownRef}>\n\t\t\t<BorderAnimation\n\t\t\t\tshowAnimation={!!highlighted}\n\t\t\t\tdisabled={!!disabled || !!loading}\n\t\t\t\tborderRadius={16}\n\t\t\t\tborderSize={2}\n\t\t\t>\n\t\t\t\t<AIButtonGroup disabled={disabled || loading}>\n\t\t\t\t\t<AIButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={disabled || loading}\n\t\t\t\t\t\tonClick={onClick}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SparkleIcon width={16} height={16} color=\"#f53f77\" />\n\t\t\t\t\t\t{loading ? '...' : label}\n\t\t\t\t\t</AIButton>\n\t\t\t\t\t<AIArrowButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={isDropdownDisabled}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\tsetIsDropdownOpen((prev) => !prev);\n\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronDownIcon width={16} height={16} />\n\t\t\t\t\t</AIArrowButton>\n\t\t\t\t</AIButtonGroup>\n\t\t\t</BorderAnimation>\n\t\t\t{isDropdownOpen ? (\n\t\t\t\t<AIDropdownMenu>\n\t\t\t\t\t{tones?.length ? (\n\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttoneSubmenuOpen={isToneMenuOpen}\n\t\t\t\t\t\t\tisChangeToneRow\n\t\t\t\t\t\t\tonMouseEnter={() => {\n\t\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\t\tsetIsToneMenuOpen(true);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => setIsToneMenuOpen((prev) => !prev)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: 8,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<EmojiIcon width={18} height={18} color=\"currentColor\" />\n\t\t\t\t\t\t\t\t\tChange tone\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<ChevronRightIcon width={14} height={14} color=\"currentColor\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tisInstructions\n\t\t\t\t\t\tselected={!!instructionActive}\n\t\t\t\t\t\tonMouseEnter={() => setIsToneMenuOpen(false)}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\tonInstructionsClick?.();\n\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<EditIcon width={16} height={16} color={COLORS.content.primary} />\n\t\t\t\t\t\tAdd instructions\n\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t{showSecondaryRephraseOption ? (\n\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonMouseEnter={() => setIsToneMenuOpen(false)}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tif (disabled || loading) return;\n\t\t\t\t\t\t\t\tonSecondaryRephraseClick?.();\n\t\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SparkleIcon\n\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\tcolor={COLORS.content.primary}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\tRephrase\n\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{isToneMenuOpen && tones?.length ? (\n\t\t\t\t\t\t<ToneSubMenu>\n\t\t\t\t\t\t\t{tones.map((tone) => (\n\t\t\t\t\t\t\t\t<AIDropdownItem\n\t\t\t\t\t\t\t\t\tkey={tone.id}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tselected={tone.id === selectedToneId}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tif (isDropdownDisabled) return;\n\t\t\t\t\t\t\t\t\t\tonToneChange?.(tone.id);\n\t\t\t\t\t\t\t\t\t\tsetIsDropdownOpen(false);\n\t\t\t\t\t\t\t\t\t\tsetIsToneMenuOpen(false);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{tone.label}\n\t\t\t\t\t\t\t\t</AIDropdownItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ToneSubMenu>\n\t\t\t\t\t) : null}\n\t\t\t\t</AIDropdownMenu>\n\t\t\t) : null}\n\t\t</AIDropdownContainer>\n\t);\n};\nexport type AIActionToneOption = {\n\tid: string;\n\tlabel: string;\n};\n"],"names":["AIButtonGroup","styled","props","AIButton","AIArrowButton","AIDropdownContainer","AIDropdownMenu","COLORS","AIDropdownItem","ToneSubMenu","AIRephraseButton","label","disabled","loading","highlighted","tones","selectedToneId","instructionActive","onClick","onToneChange","onInstructionsClick","showSecondaryRephraseOption","onSecondaryRephraseClick","dropdownRef","useRef","isDropdownOpen","setIsDropdownOpen","useState","isToneMenuOpen","setIsToneMenuOpen","isDropdownDisabled","useOutside","useEffect","jsxs","jsx","BorderAnimation","SparkleIcon","prev","ChevronDownIcon","EmojiIcon","ChevronRightIcon","EditIcon","tone"],"mappings":"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"}
|
|
@@ -62,15 +62,15 @@
|
|
|
62
62
|
cursor: pointer;
|
|
63
63
|
color: ${s.COLORS.content.primary};
|
|
64
64
|
transition: background-color 0.12s ease;
|
|
65
|
-
|
|
65
|
+
:not(:disabled):hover {
|
|
66
66
|
background-color: ${s.COLORS.surface.hovered};
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
:disabled {
|
|
69
69
|
opacity: 0.35;
|
|
70
70
|
cursor: not-allowed;
|
|
71
71
|
}
|
|
72
72
|
`,cn=g.default(H)`
|
|
73
|
-
|
|
73
|
+
:disabled {
|
|
74
74
|
opacity: 1;
|
|
75
75
|
cursor: wait;
|
|
76
76
|
}
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
font-size: 14px;
|
|
150
150
|
line-height: 1.2;
|
|
151
151
|
cursor: pointer;
|
|
152
|
-
|
|
152
|
+
:hover {
|
|
153
153
|
background: ${a=>a.selected?"#d9e8db":s.COLORS.surface.subdued};
|
|
154
154
|
}
|
|
155
155
|
`,v=new Jt.BaseWhatsappContentLangHelper,bn={[c.EditorActionTypes.BOLD]:"*",[c.EditorActionTypes.ITALIC]:"_",[c.EditorActionTypes.STRIKETHROUGH]:"~"};function mn(a){return`whatsapp-editor-rephrase-highlight-${a||"default"}`}const bt=Vt.default.forwardRef(({onChange:a,onClickVariable:Rn,text:P,RightComponent:mt,error:I,limit:M,onError:D,rows:Rt,actions:St,editorInstanceKey:A,editorSessionId:re,templateType:L="marketing",templateId:R,requestExecutor:fe,baseUrl:he,endpointPath:Oe,useCase:Ie,storeId:Le,apiAdapter:pe,conversationId:ke="whatsapp-template-editor",systemId:we="whatsapp-writer",intent:je="default",enabledAIActions:ve=[c.AIEditorActionTypes.REPHRASE,c.AIEditorActionTypes.SHORTEN,c.AIEditorActionTypes.EXPAND,c.AIEditorActionTypes.EMOJIFY],disableBuiltInAIActions:He=!1,promptOverrides:Pe,rephraseTones:Me,aiActionMinChars:De,instructionSuggestions:$e=B.DEFAULT_INSTRUCTION_SUGGESTIONS,onAnalyticsEvent:Ne,onAITagComputed:ie,prefillWasAiGenerated:C=!1,editorHeader:Fe,onAIToneSelect:At,onAIActionRequest:se,onBuildAIPrompt:qe,onBlur:Et,...Ct},Tt)=>{const f=r.useRef(null),[o,yt]=r.useState(P||""),[Be,z]=r.useState(!1),[xe,Ue]=r.useState(0),[l,ze]=r.useState(!1),[Ge,be]=r.useState(!1),[T,oe]=r.useState(""),[ce,_t]=r.useState({}),[m,We]=r.useState(null),[p,me]=r.useState([]),[y,G]=r.useState(0),[u,Xe]=r.useState(null),Ye=r.useRef(null),h=r.useRef(null),W=r.useRef(null),E=r.useRef(null),X=r.useRef(null),Y=r.useRef(null),Je=r.useRef(null),Re=r.useRef(!!C),ae=r.useRef(null),J=r.useRef(""),le=r.useRef(!1),[Se,Ve]=r.useState({}),Ot=r.useRef(`mount-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`),V=r.useMemo(()=>mn(`${A||"default"}-${re||Ot.current}`),[A,re]);r.useEffect(()=>{Re.current=!!C},[C,A]),r.useEffect(()=>{le.current=!1,J.current=""},[A,re]),r.useEffect(()=>{if(!C){le.current=!1,J.current="";return}if(le.current)return;const e=P??"";e.length>0&&(J.current=e,le.current=!0)},[C,P,A,re]);const ue=r.useMemo(()=>B.resolveActionPrompts(L,Pe,Me),[Pe,Me,L]),Qe=r.useMemo(()=>{const e=T.trim().toLowerCase();return e?$e.filter(t=>t.toLowerCase().includes(e)):[]},[$e,T]),Q=r.useMemo(()=>({...B.DEFAULT_AI_ACTION_MIN_CHARS,...De||{}}),[De]),Ze=Q[c.AIEditorActionTypes.REPHRASE]||B.DEFAULT_AI_ACTION_MIN_CHARS[c.AIEditorActionTypes.REPHRASE],It=r.useCallback(e=>{const t=e.trim().replace(/\s+/g," ");if(!t)return"";const i=t.split(" ").length;return`[anonymized:length_${t.length}:words_${i}]`},[]),S=r.useCallback((e,t)=>{Ne?.(e,t)},[Ne]),_=r.useCallback(e=>{yt(t=>t===e?t:e)},[]),k=r.useCallback(e=>{if(Y.current&&clearTimeout(Y.current),e.length>gt){a?.(e,e),Y.current=setTimeout(()=>{a?.(e,v.getHTML(e))},16);return}a?.(e,v.getHTML(e))},[a]),Ke=r.useCallback(e=>{const i=ae.current?.acceptedText||(C?J.current:"");if(!i||e===i)return;const d=ne.computeAiTagOnPostEdit({acceptedAiText:i,currentEditedText:e});ie?.({...d,source:"post_edit_debounce"})},[ie,C]),Z=r.useCallback(()=>{We(null),me([]),G(0),Xe(null),Ve({})},[]),et=r.useCallback(()=>{if(l||m&&p.length>0||xe>=Qt)return;const e=xe+1;Ue(e),typeof window<"u"&&A&&sessionStorage.setItem(V,String(e)),z(!0),W.current&&clearTimeout(W.current),W.current=setTimeout(()=>{z(!1)},1200)},[A,V,l,m,p,xe]),de=r.useRef(et);de.current=et;function Lt(e){const t=at.stripHtmlTags(e.target.value),i=ae.current;i&&!i.editedEventEmitted&&t!==i.acceptedText&&(ae.current={...i,editedEventEmitted:!0},S("ai_suggestion_edited",{action_type:i.actionType,template_id:R})),E.current&&(clearTimeout(E.current),E.current=null);const d=i?.acceptedText||(C?J.current:"");d&&t!==d&&(E.current=setTimeout(()=>{Ke(t)},Zt)),_(t),k(t)}function tt(e){const t=f?.current;t!=null&&(t.selectionStart?(t.focus(),t.selectionEnd=e):t.focus())}function kt(e){const t=bn[e];if(t&&f.current){const i=f.current.selectionStart,d=f.current.selectionEnd;if(i===d){const{text:b}=nt(t,i);tt(i+1),k(b)}else{const{text:b}=Ae(t);k(b)}}}function wt(e){const{text:t}=ge(e);k(t)}function Ae(e){let t=f.current?.value??"";if(f.current&&e){const i=f.current.selectionStart,d=f.current.selectionEnd,b=e;if(i===d)return ge(b);{t=v.wrappWildcard(i,d,b,t);const N=v.getHTML(t);return _(t),{text:t,html:N}}}return{text:t,html:t}}function ge(e){const t=f.current?.value??"";if(f.current&&e){const i=f.current.selectionStart,d=f.current.selectionEnd;if(i===d)return nt(e,i)}return{text:t,html:t}}function nt(e,t){let i=f.current?.value??"";i=i.slice(0,t)+e+i.slice(t);const d=v.getHTML(i);return _(i),{text:i,html:d}}r.useEffect(()=>{if(typeof window>"u"||!A)return;const e=Number(sessionStorage.getItem(V)||"0");return Number.isNaN(e)||Ue(e),()=>{sessionStorage.removeItem(V)}},[A,V]),r.useEffect(()=>{if(l){z(!1),h.current&&(clearTimeout(h.current),h.current=null);return}if(m&&p.length>0){z(!1),h.current&&(clearTimeout(h.current),h.current=null);return}const e=!!o.trim()&&o.length>=Ze;if(X.current===null){X.current=e,e&&(h.current=setTimeout(()=>{de.current()},ut));return}if(!e){X.current=!1,z(!1),h.current&&(clearTimeout(h.current),h.current=null);return}const t=!X.current&&e;X.current=!0,t&&de.current(),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{de.current()},ut)},[o,l,Ze,m,p]),r.useEffect(()=>()=>{h.current&&clearTimeout(h.current),W.current&&clearTimeout(W.current),Y.current&&clearTimeout(Y.current),E.current&&clearTimeout(E.current)},[]);const x=p[y]||"",$=r.useMemo(()=>!u||!x?null:`${u}-${y}-${x}`,[x,u,y]),rt=!!($&&Se[$]),jt=r.useMemo(()=>v.getHTML(m||""),[m]),vt=r.useMemo(()=>v.getHTML(x),[x]),Ee=p.length<dt,O=!!m&&p.length>0,Ht=p.length<=1||y<=0,Pt=p.length<=1||y>=p.length-1;r.useEffect(()=>{if(!O)return;const e=Ye.current;e&&(e.scrollTop=e.scrollHeight)},[x,O,l]);const K=r.useCallback(async(e,t=!1,i,d,b=c.AIActionVariant.DEFAULT)=>{if(!se&&!pe&&(!fe||!he)){D?.("AI configuration missing");return}if(!o.trim())return;const N=Q[e]||B.DEFAULT_AI_ACTION_MIN_CHARS[e]||50;if(o.length<N||l||t&&!Ee)return;const ee=ue[e],F=e===c.AIEditorActionTypes.REPHRASE&&L==="utility"&&b===c.AIActionVariant.REPHRASE?{...ee,label:"Rephrase",basePrompt:Kt}:ee,w=d||ce[e],st=F.tones?.find(q=>q.id===w),Ce=i!==void 0?i:T,ot=qe?.({actionType:e,actionVariant:b,currentText:o,templateType:L,config:F,toneId:w,toneLabel:st?.label,instructionText:Ce||void 0})||lt.buildActionPrompt({config:F,currentText:o,selectedToneId:w,instructionText:Ce});ze(!0),S("ai_action_triggered",{action_type:e,template_id:R,template_category:L});try{const q=se?await se({actionType:e,actionVariant:b,currentText:o,templateType:L,toneId:w,toneLabel:st?.label,instructionText:Ce||void 0,prompt:ot}):await lt.requestAISuggestion({apiAdapter:pe,requestExecutor:fe,baseUrl:he,endpointPath:Oe,prompt:ot,intent:je,conversationId:ke,systemId:we,useCase:Ie,storeId:Le}),Te=typeof q=="string"?q.trim():(q?.body||"").trim();if(!Te)return;if(!t){We(o),Xe(e),me([Te]),G(0);return}me(Nt=>{const ct=[...Nt,Te].slice(0,dt);return G(ct.length-1),ct})}catch{D?.("Failed to generate AI suggestion")}finally{ze(!1)}},[fe,he,o,l,Ee,ue,ce,T,S,R,Oe,pe,je,ke,we,Ie,Le,L,D,Q,se,qe]),Mt=r.useCallback(()=>{if(!x||!m||!u)return;_(x),k(x),S("ai_suggestion_accepted",{action_type:u,template_id:R}),ae.current={acceptedText:x,baselineText:m,actionType:u,editedEventEmitted:!1};const e=Re.current,t=ne.computeAiTagOnAccept({baselineText:m,acceptedText:x,initialAiPrefillPhase:e});e&&(Re.current=!1),ie?.({...t,source:"accept"}),Z()},[x,m,u,_,k,S,R,ie,Z]),Dt=r.useCallback(()=>{u&&(S("ai_suggestion_discarded",{action_type:u,template_id:R}),Z())},[Z,S,u,R]),it=r.useCallback(e=>{!u||!$||Se[$]||(Ve(t=>({...t,[$]:e})),S("ai_feedback_submitted",{action_type:u,template_id:R,rating:e,candidate_index:y+1}))},[$,S,Se,u,y,R]),$t=r.useMemo(()=>He?[]:ve.map(e=>{const t=ue[e],i=ce[e];return{type:e,label:t.label,isPrimary:e===c.AIEditorActionTypes.REPHRASE,loading:l&&u===e,highlighted:e===c.AIEditorActionTypes.REPHRASE&&Be,disabled:!o.trim()||o.length<(Q[e]||B.DEFAULT_AI_ACTION_MIN_CHARS[e]||50)||l||O&&u===e,showToneDropdown:e===c.AIEditorActionTypes.REPHRASE&&!!t.tones?.length,tones:t.tones,selectedToneId:i}}),[ve,He,ue,ce,l,u,O,Be,o,Q]);return r.useImperativeHandle(Tt,()=>({addTextOrWrap:Ae,addText:ge,get(){return o},setCaretPosition:tt}),[Ae,ge,o]),r.useEffect(()=>{P!==void 0&&_(P||"")},[P,_]),r.useEffect(()=>{if(!M||!D)return;const e=o.length>M?_e:I??"";Je.current!==e&&(Je.current=e,D(e))},[o,I,M,D]),n.jsxs(U.OuterContainer,{children:[n.jsxs(U.EditorFooterRow,{children:[n.jsx(U.EditorFooterTitle,{children:Fe?n.jsx(ye.TitleSmall,{"data-test":"body-text-for-edit-template",children:Fe}):null}),n.jsxs(U.EditorFooterRight,{children:[I&&I!==_e?n.jsxs(n.Fragment,{children:[n.jsx(Gt.default,{width:16,height:16,color:s.COLORS.content.negative}),n.jsx(ye.BodyCaption,{color:s.COLORS.content.negative,children:I})]}):null,M?n.jsxs(ye.BodyCaption,{style:{color:I===_e||o.length>M?s.COLORS.content.negative:s.COLORS.content.secondary},children:[o.length,"/",M]}):null]})]}),n.jsxs(U.Container,{isError:!!I,children:[O?n.jsxs(tn,{ref:Ye,children:[n.jsx(nn,{dangerouslySetInnerHTML:{__html:jt}}),l?n.jsx(ft,{"aria-busy":"true",children:n.jsxs(rn,{children:[n.jsx(j,{width:"96%"}),n.jsx(j,{width:"84%"}),n.jsx(j,{width:"68%"})]})}):n.jsx(ft,{dangerouslySetInnerHTML:{__html:vt}}),n.jsxs(sn,{children:[n.jsx(H,{"aria-label":"Previous suggestion",type:"button",disabled:Ht,onClick:()=>G(e=>Math.max(0,e-1)),children:n.jsx(qt.default,{width:14,height:14,color:s.COLORS.content.secondary})}),n.jsxs(on,{children:[y+1,"/",p.length]}),n.jsx(H,{"aria-label":"Next suggestion",type:"button",disabled:Pt,onClick:()=>G(e=>Math.min(p.length-1,e+1)),children:n.jsx(Bt.default,{width:14,height:14,color:s.COLORS.content.secondary})}),n.jsx(te.Tooltip,{body:"Like",placement:"top",children:n.jsx(H,{"aria-label":"Like suggestion",type:"button",disabled:rt,onClick:()=>it("like"),children:n.jsx(Yt.default,{width:14,height:14,color:s.COLORS.content.secondary})})}),n.jsx(te.Tooltip,{body:"Dislike",placement:"top",children:n.jsx(H,{"aria-label":"Dislike suggestion",type:"button",disabled:rt,onClick:()=>it("dislike"),children:n.jsx(Xt.default,{width:14,height:14,color:s.COLORS.content.secondary})})}),Ee?n.jsx(te.Tooltip,{body:l?"Regenerating…":"Regenerate",placement:"top",children:n.jsx(cn,{"aria-label":"Regenerate suggestion","aria-busy":l,type:"button",disabled:l,onClick:()=>{u&&K(u,!0)},children:l?n.jsx(an,{"aria-hidden":!0}):n.jsx(Wt.default,{width:14,height:14})})}):null,n.jsx(te.Tooltip,{body:"Discard",placement:"top",children:n.jsx(H,{"aria-label":"Discard suggestion",type:"button",onClick:Dt,children:n.jsx(Ut.default,{width:14,height:14,color:s.COLORS.content.secondary})})}),n.jsx(te.Tooltip,{body:"Accept",placement:"top",children:n.jsx(H,{"aria-label":"Accept suggestion",type:"button",onClick:Mt,children:n.jsx(Ft.default,{width:14,height:14,color:s.COLORS.content.secondary})})})]})]}):l?n.jsxs(en,{children:[n.jsx(j,{width:"96%"}),n.jsx(j,{width:"92%"}),n.jsx(j,{width:"88%"}),n.jsx(j,{width:"54%"})]}):n.jsx(U.TextSpace,{ref:f,...Ct,value:o,onChange:Lt,onBlur:e=>{E.current&&(clearTimeout(E.current),E.current=null),Ke(e.target.value),Et?.(e)},onPaste:e=>{const t=e.clipboardData.getData("text");if(t.length>gt){e.preventDefault();const i=f.current,d=i?.selectionStart??0,b=i?.selectionEnd??d,N=i?.value??o,ee=N.slice(0,d)+t+N.slice(b);_(ee),k(ee);const F=d+t.length;requestAnimationFrame(()=>{const w=f.current;if(w)try{w.setSelectionRange(F,F)}catch{}})}},rows:Rt}),Ge?n.jsxs(ln,{children:[n.jsxs(un,{children:[n.jsx(zt.default,{width:18,height:18,color:s.COLORS.content.secondary}),n.jsx(dn,{value:T,placeholder:"Add specific instructions to refine your message",onChange:e=>oe(at.stripHtmlTags(e.target.value))}),n.jsxs(gn,{children:[n.jsx(fn,{type:"button",onClick:()=>{oe(""),be(!1)},children:"Cancel"}),n.jsx(hn,{type:"button",onClick:()=>{const e=T.trim();e&&S("ai_instruction_used",{action_type:c.AIEditorActionTypes.REPHRASE,template_id:R,instruction_text:It(e)}),be(!1),oe(""),K(c.AIEditorActionTypes.REPHRASE,!1,e)},children:"Improve"})]})]}),T.trim().length>0&&Qe.length>0?n.jsx(pn,{children:Qe.map(e=>n.jsx(xn,{type:"button",selected:T===e,onClick:()=>oe(e),children:e},e))}):null]}):n.jsx(c.WhatsAppTextEditorHeader,{actions:St,ref:f,onActionSelect:kt,RightComponent:mt,rightActionsDisabled:O||l,onEmojiClick:wt,aiActions:$t,disableAllActions:O||l,instructionActive:Ge,onAIInstructionsClick:()=>be(!0),onAIToneChange:(e,t)=>{_t(i=>({...i,[e]:t})),At?.(e,t),e===c.AIEditorActionTypes.REPHRASE&&K(e,!1,void 0,t,c.AIActionVariant.DEFAULT)},onAIActionClick:(e,t=c.AIActionVariant.DEFAULT)=>{if(!l){if(O){if(u===e)return;Z(),K(e,!1,void 0,void 0,t);return}K(e,!1,void 0,void 0,t)}}})]})]})});bt.displayName="WhatsAppTextEditor";exports.AI_TAG_CHANGE_RATIO_THRESHOLD=ne.AI_TAG_CHANGE_RATIO_THRESHOLD;exports.computeAiTagOnAccept=ne.computeAiTagOnAccept;exports.levenshteinDistance=ne.levenshteinDistance;exports.WhatsAppTextEditor=bt;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WhatsAppTextEditor.js","sources":["../../../../src/components/WhatsAppTextEditor/WhatsAppTextEditor.tsx"],"sourcesContent":["import CheckIcon from '@src/assets/icons/check.svg';\nimport ChevronLeftIcon from '@src/assets/icons/chevronLeft.svg';\nimport ChevronRightIcon from '@src/assets/icons/chevronRight.svg';\nimport CrossIcon from '@src/assets/icons/cross.svg';\nimport EditIcon from '@src/assets/icons/edit.svg';\nimport InfoIcon from '@src/assets/icons/info.svg';\nimport RewindIcon from '@src/assets/icons/rewind.svg';\nimport ThumbsDownIcon from '@src/assets/icons/thumb-down-line.svg';\nimport ThumbsUpIcon from '@src/assets/icons/thumb-up-line.svg';\nimport { BaseWhatsappContentLangHelper } from '@src/helpers/BaseWhatsappContentLang.helper';\nimport { stripHtmlTags } from '@src/helpers/sanitize';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport styled, { keyframes } from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\nimport type { ApiRequestExecutor } from '../bik-chatbot/types';\nimport type { APIAdapter } from '../bik-chatbot/types/ai';\nimport { Tooltip } from '../tooltips/Tooltip';\nimport { BodyCaption, TitleSmall } from '../TypographyStyle';\nimport {\n\tAIActionPromptConfig,\n\tAIActionPromptRegistry,\n\tDEFAULT_AI_ACTION_MIN_CHARS,\n\tDEFAULT_INSTRUCTION_SUGGESTIONS,\n\tresolveActionPrompts,\n\tTemplateType,\n} from './ai/actionRegistry';\nimport {\n\tAITagPayload,\n\tcomputeAiTagOnAccept,\n\tcomputeAiTagOnPostEdit,\n} from './ai/aiTag';\nimport { buildActionPrompt, requestAISuggestion } from './ai/api';\nimport { AIActionToneOption } from './AIRephraseButton';\nimport {\n\tContainer,\n\tEditorFooterRight,\n\tEditorFooterRow,\n\tEditorFooterTitle,\n\tOuterContainer,\n\tTextSpace,\n} from './CustomEditor.styled';\nimport {\n\tAIActionVariant,\n\tAIEditorActionType,\n\tAIEditorActionTypes,\n\tAIHeaderAction,\n\tEditorActionTypes,\n\tWhatsAppEditorRightSlotProps,\n\tWhatsAppTextEditorHeader,\n} from './WhatsAppTextEditorHeader';\n\nconst LIMIT_REACHED = 'Character limit reached';\nconst REPHRASE_IDLE_MS = 3000;\nconst MAX_REPHRASE_HIGHLIGHTS = 5;\nconst MAX_SUGGESTIONS = 3;\nconst LARGE_INPUT_THRESHOLD = 1200;\nconst AI_TAG_RECOMPUTE_IDLE_MS = 1000;\nconst UTILITY_REPHRASE_PROMPT =\n\t'Rephrase this WhatsApp utility template to improve clarity and readability while preserving variables, intent, and compliance.';\n\nconst skeletonPulse = keyframes`\n\t0% { opacity: 0.55; }\n\t50% { opacity: 1; }\n\t100% { opacity: 0.55; }\n`;\n\nconst EditorSkeletonContainer = styled.div`\n\tpadding: 14px 12px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tmin-height: 150px;\n`;\n\nconst EditorSkeletonLine = styled.div<{ width: string }>`\n\theight: 16px;\n\tborder-radius: 6px;\n\twidth: ${(props) => props.width};\n\tbackground: #ececef;\n\tanimation: ${skeletonPulse} 1.1s ease-in-out infinite;\n`;\n\nconst SuggestionSessionContainer = styled.div`\n\tpadding: 12px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmax-height: 260px;\n\toverflow-y: scroll;\n\tscrollbar-width: thin;\n\tscrollbar-color: #c8c8cf transparent;\n\t::-webkit-scrollbar {\n\t\twidth: 8px;\n\t}\n\t::-webkit-scrollbar-thumb {\n\t\tbackground: #c8c8cf;\n\t\tborder-radius: 8px;\n\t}\n\t::-webkit-scrollbar-track {\n\t\tbackground: transparent;\n\t}\n`;\n\nconst SuggestionBaselineText = styled.div`\n\ttext-decoration: line-through;\n\tcolor: ${COLORS.content.secondary};\n`;\n\nconst SuggestionCandidateText = styled.div`\n\tcolor: ${COLORS.content.primary};\n`;\n\nconst SuggestionCandidateSkeleton = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\twidth: 100%;\n\tmin-height: 40px;\n`;\n\nconst SuggestionControlsRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n`;\n\nconst SuggestionCounter = styled.span`\n\tcolor: ${COLORS.content.primary};\n\tfont-size: 14px;\n`;\n\nconst SuggestionIconButton = styled.button`\n\tborder: 0;\n\tbackground: transparent;\n\tpadding: 6px;\n\tborder-radius: 6px;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\tcolor: ${COLORS.content.primary};\n\ttransition: background-color 0.12s ease;\n\t&:not(:disabled):hover {\n\t\tbackground-color: ${COLORS.surface.hovered};\n\t}\n\t&:disabled {\n\t\topacity: 0.35;\n\t\tcursor: not-allowed;\n\t}\n`;\n\n/** Regenerate stays full opacity while disabled so the loading shimmer stays visible (same pulse as editor skeleton). */\nconst SuggestionRegenerateButton = styled(SuggestionIconButton)`\n\t&:disabled {\n\t\topacity: 1;\n\t\tcursor: wait;\n\t}\n`;\n\nconst RegenerateIconShimmer = styled.div`\n\twidth: 14px;\n\theight: 14px;\n\tborder-radius: 4px;\n\tbackground: #ececef;\n\tflex-shrink: 0;\n\tanimation: ${skeletonPulse} 1.1s ease-in-out infinite;\n`;\n\n/** Same bottom toolbar slot as `WhatsAppTextEditorHeader` — replaces the full icon/AI panel while open. */\nconst InstructionContainer = styled.div`\n\tbackground: ${COLORS.surface.standard};\n\tdisplay: flex;\n\tflex-direction: column;\n\tpadding: 8px 12px;\n\tgap: 10px;\n\tborder-radius: 0 0 4px 4px;\n\tposition: relative;\n`;\n\nconst InstructionInputRow = styled.div`\n\tborder: 1px solid #f5a4c0;\n\tborder-radius: 10px;\n\tpadding: 8px 10px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tbackground: ${COLORS.surface.standard};\n`;\n\nconst InstructionInput = styled.input`\n\tflex: 1;\n\tmin-width: 0;\n\tborder: 0;\n\toutline: none;\n\tfont-size: 14px;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.primary};\n`;\n\nconst InstructionActions = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n`;\n\nconst InstructionCancel = styled.button`\n\tborder: 0;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.secondary};\n\tfont-size: 14px;\n\tfont-weight: 500;\n\tpadding: 0;\n\tcursor: pointer;\n`;\n\nconst InstructionImprove = styled.button`\n\tborder: 1px solid #5d3a72;\n\tcolor: #5d3a72;\n\tbackground: ${COLORS.surface.standard};\n\tborder-radius: 8px;\n\tpadding: 8px 14px;\n\tfont-size: 14px;\n\tline-height: 1.1;\n\tfont-weight: 600;\n\tcursor: pointer;\n`;\n\nconst InstructionSuggestionList = styled.div`\n\tmargin-top: 4px;\n\tborder-radius: 12px;\n\twidth: 331px;\n\tbackground: ${COLORS.surface.standard};\n\tbox-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);\n\toverflow: hidden;\n\tpadding: 4px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n`;\n\nconst InstructionSuggestionButton = styled.button<{ selected?: boolean }>`\n\twidth: 100%;\n\tborder: 0;\n\tborder-radius: 8px;\n\tbackground: ${(props) => (props.selected ? '#e5f3e8' : 'transparent')};\n\tcolor: ${(props) => (props.selected ? '#1e6b34' : COLORS.content.primary)};\n\ttext-align: left;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tline-height: 1.2;\n\tcursor: pointer;\n\t&:hover {\n\t\tbackground: ${(props) =>\n\t\t\tprops.selected ? '#d9e8db' : COLORS.surface.subdued};\n\t}\n`;\n\ntype AIEventName =\n\t| 'ai_action_triggered'\n\t| 'ai_feedback_submitted'\n\t| 'ai_suggestion_accepted'\n\t| 'ai_suggestion_discarded'\n\t| 'ai_suggestion_edited'\n\t| 'ai_instruction_used';\n\nenum AIFeedbackRating {\n\tLIKE = 'like',\n\tDISLIKE = 'dislike',\n}\n\ntype AIEventPayload = {\n\taction_type: AIEditorActionType;\n\ttemplate_id?: string | number;\n\ttemplate_category?: TemplateType;\n\trating?: AIFeedbackRating;\n\tcandidate_index?: number;\n\tinstruction_text?: string;\n};\n\ntype AIActionRequestPayload = {\n\tactionType: AIEditorActionType;\n\tactionVariant?: AIActionVariant;\n\tcurrentText: string;\n\ttemplateType: TemplateType;\n\ttoneId?: string;\n\ttoneLabel?: string;\n\tinstructionText?: string;\n\tprompt: string;\n};\n\ntype AIActionPromptBuildPayload = {\n\tactionType: AIEditorActionType;\n\tactionVariant?: AIActionVariant;\n\tcurrentText: string;\n\ttemplateType: TemplateType;\n\tconfig: AIActionPromptConfig;\n\ttoneId?: string;\n\ttoneLabel?: string;\n\tinstructionText?: string;\n};\n\nexport type CustomEditorProps =\n\tReact.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n\t\tonChange?: (text: string, html: string) => void;\n\t\ttext?: string;\n\t\tRightComponent?: React.ComponentType<WhatsAppEditorRightSlotProps>;\n\t\terror?: string;\n\t\tlimit?: number;\n\t\trows?: number;\n\t\tactions?: EditorActionTypes[];\n\n\t\t/**\n\t\t * Calls only for editor only error, not for errors coming from outside\n\t\t */\n\t\tonError?: (err: string) => void;\n\n\t\tonClickVariable?: (variable: string) => void;\n\t\teditorInstanceKey?: string;\n\t\teditorSessionId?: string;\n\t\ttemplateType?: TemplateType;\n\t\ttemplateId?: string | number;\n\t\trequestExecutor?: ApiRequestExecutor;\n\t\tbaseUrl?: string;\n\t\tendpointPath?: string;\n\t\tuseCase?: string;\n\t\tstoreId?: string;\n\t\tapiAdapter?: APIAdapter;\n\t\tconversationId?: string;\n\t\tsystemId?: string;\n\t\tintent?: string;\n\t\tenabledAIActions?: AIEditorActionType[];\n\t\tdisableBuiltInAIActions?: boolean;\n\t\tpromptOverrides?: AIActionPromptRegistry;\n\t\trephraseTones?: AIActionToneOption[];\n\t\taiActionMinChars?: Partial<Record<AIEditorActionType, number>>;\n\t\tinstructionSuggestions?: string[];\n\t\tonAnalyticsEvent?: (name: AIEventName, payload: AIEventPayload) => void;\n\t\t/**\n\t\t * Fires on AI-tag computations:\n\t\t * - `source: \"accept\"` after accepting a suggestion (addition check: >=50% => true)\n\t\t * - `source: \"post_edit_debounce\"` after edit idle/blur (retention check: <50% => true)\n\t\t * Persist `payload.isAiTagged` (or full payload) in host state and send on save.\n\t\t */\n\t\tonAITagComputed?: (payload: AITagPayload) => void;\n\t\t/**\n\t\t * When true, the editor body was loaded as fully AI-generated (prefill).\n\t\t * The first accepted suggestion will set `initialAiPrefillPhase` on the tag payload;\n\t\t * after that, only baseline vs accepted comparison applies.\n\t\t */\n\t\tprefillWasAiGenerated?: boolean;\n\t\t/**\n\t\t * Optional label above the editor (e.g. section title from the host).\n\t\t * When omitted, the left side of that top row is empty; limit/error stay on the right.\n\t\t */\n\t\teditorHeader?: React.ReactNode;\n\t\tonAIToneSelect?: (actionType: AIEditorActionType, toneId: string) => void;\n\t\tonAIActionRequest?: (\n\t\t\tpayload: AIActionRequestPayload,\n\t\t) => Promise<string | { body?: string }>;\n\t\tonBuildAIPrompt?: (payload: AIActionPromptBuildPayload) => string;\n\t\tonBlur?: React.FocusEventHandler<HTMLTextAreaElement>;\n\t};\nexport type CustomEditorRef = {\n\taddTextOrWrap: (textToAdd: string) => {\n\t\ttext: string;\n\t\thtml: string;\n\t};\n\taddText: (textToAdd: string) => {\n\t\ttext: string;\n\t\thtml: string;\n\t};\n\tget: () => string;\n\tsetCaretPosition(caretPos: number): void;\n};\n\nconst baseWhatsappContentLang = new BaseWhatsappContentLangHelper();\n\nconst WildCardMap: { [key in EditorActionTypes]?: string } = {\n\t[EditorActionTypes.BOLD]: '*',\n\t[EditorActionTypes.ITALIC]: '_',\n\t[EditorActionTypes.STRIKETHROUGH]: '~',\n};\n\nfunction getHighlightStorageKey(editorInstanceKey?: string) {\n\treturn `whatsapp-editor-rephrase-highlight-${editorInstanceKey || 'default'}`;\n}\n\nexport const WhatsAppTextEditor = React.forwardRef<\n\tCustomEditorRef,\n\tCustomEditorProps\n>(\n\t(\n\t\t{\n\t\t\tonChange,\n\t\t\tonClickVariable,\n\t\t\ttext: inputValue,\n\t\t\tRightComponent,\n\t\t\terror,\n\t\t\tlimit,\n\t\t\tonError,\n\t\t\trows,\n\t\t\tactions,\n\t\t\teditorInstanceKey,\n\t\t\teditorSessionId,\n\t\t\ttemplateType = 'marketing',\n\t\t\ttemplateId,\n\t\t\trequestExecutor,\n\t\t\tbaseUrl,\n\t\t\tendpointPath,\n\t\t\tuseCase,\n\t\t\tstoreId,\n\t\t\tapiAdapter,\n\t\t\tconversationId = 'whatsapp-template-editor',\n\t\t\tsystemId = 'whatsapp-writer',\n\t\t\tintent = 'default',\n\t\t\tenabledAIActions = [\n\t\t\t\tAIEditorActionTypes.REPHRASE,\n\t\t\t\tAIEditorActionTypes.SHORTEN,\n\t\t\t\tAIEditorActionTypes.EXPAND,\n\t\t\t\tAIEditorActionTypes.EMOJIFY,\n\t\t\t],\n\t\t\tdisableBuiltInAIActions = false,\n\t\t\tpromptOverrides,\n\t\t\trephraseTones,\n\t\t\taiActionMinChars,\n\t\t\tinstructionSuggestions = DEFAULT_INSTRUCTION_SUGGESTIONS,\n\t\t\tonAnalyticsEvent,\n\t\t\tonAITagComputed,\n\t\t\tprefillWasAiGenerated = false,\n\t\t\teditorHeader,\n\t\t\tonAIToneSelect,\n\t\t\tonAIActionRequest,\n\t\t\tonBuildAIPrompt,\n\t\t\tonBlur: textAreaOnBlur,\n\t\t\t...textAreaProps\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst textSpaceRef = useRef<HTMLTextAreaElement>(null);\n\t\tconst [currentText, setCurrentText] = useState(inputValue || '');\n\t\tconst [isRephraseHighlighted, setIsRephraseHighlighted] = useState(false);\n\t\tconst [rephraseHighlightCount, setRephraseHighlightCount] = useState(0);\n\t\tconst [isGenerating, setIsGenerating] = useState(false);\n\t\tconst [isInstructionInputVisible, setIsInstructionInputVisible] =\n\t\t\tuseState(false);\n\t\tconst [instructionText, setInstructionText] = useState('');\n\t\tconst [toneByAction, setToneByAction] = useState<\n\t\t\tPartial<Record<AIEditorActionType, string>>\n\t\t>({});\n\t\tconst [suggestionBaseText, setSuggestionBaseText] = useState<string | null>(\n\t\t\tnull,\n\t\t);\n\t\tconst [suggestionCandidates, setSuggestionCandidates] = useState<string[]>(\n\t\t\t[],\n\t\t);\n\t\tconst [suggestionIndex, setSuggestionIndex] = useState(0);\n\t\tconst [suggestionActionType, setSuggestionActionType] =\n\t\t\tuseState<AIEditorActionType | null>(null);\n\t\tconst suggestionScrollRef = useRef<HTMLDivElement | null>(null);\n\t\tconst rephraseIdleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\t\tconst highlightResetRef = useRef<ReturnType<typeof setTimeout> | null>(\n\t\t\tnull,\n\t\t);\n\t\tconst aiTagRecomputeRef = useRef<ReturnType<typeof setTimeout> | null>(\n\t\t\tnull,\n\t\t);\n\t\t/**\n\t\t * Prior eligibility for rephrase nudge (null = not initialized).\n\t\t * Matches the chip: non-empty trim and length ≥ min — same as `aiHeaderActions` disabled rules.\n\t\t */\n\t\tconst prevRephraseEligibleRef = useRef<boolean | null>(null);\n\t\tconst deferredHtmlRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\t\tconst lastEmittedEditorErrorRef = useRef<string | null>(null);\n\t\t/** First accept after full-AI prefill (`prefillWasAiGenerated`); cleared after one accept. */\n\t\tconst initialAiPrefillPhaseRef = useRef(!!prefillWasAiGenerated);\n\t\tconst acceptedSuggestionStateRef = useRef<{\n\t\t\tacceptedText: string;\n\t\t\tbaselineText: string;\n\t\t\tactionType: AIEditorActionType;\n\t\t\teditedEventEmitted: boolean;\n\t\t} | null>(null);\n\t\t/** Original prefill body for AI tag recompute; seeded once, never the live `currentText` fallback. */\n\t\tconst prefillBaselineTextRef = useRef('');\n\t\tconst prefillBaselineCapturedRef = useRef(false);\n\t\tconst [feedbackVotesByCandidate, setFeedbackVotesByCandidate] = useState<\n\t\t\tPartial<Record<string, AIFeedbackRating>>\n\t\t>({});\n\t\tconst mountSessionIdRef = useRef(\n\t\t\t`mount-${Date.now().toString(36)}-${Math.random()\n\t\t\t\t.toString(36)\n\t\t\t\t.slice(2, 8)}`,\n\t\t);\n\t\tconst highlightStorageKey = useMemo(() => {\n\t\t\treturn getHighlightStorageKey(\n\t\t\t\t`${editorInstanceKey || 'default'}-${\n\t\t\t\t\teditorSessionId || mountSessionIdRef.current\n\t\t\t\t}`,\n\t\t\t);\n\t\t}, [editorInstanceKey, editorSessionId]);\n\n\t\tuseEffect(() => {\n\t\t\tinitialAiPrefillPhaseRef.current = !!prefillWasAiGenerated;\n\t\t}, [prefillWasAiGenerated, editorInstanceKey]);\n\n\t\tuseEffect(() => {\n\t\t\tprefillBaselineCapturedRef.current = false;\n\t\t\tprefillBaselineTextRef.current = '';\n\t\t}, [editorInstanceKey, editorSessionId]);\n\n\t\tuseEffect(() => {\n\t\t\tif (!prefillWasAiGenerated) {\n\t\t\t\tprefillBaselineCapturedRef.current = false;\n\t\t\t\tprefillBaselineTextRef.current = '';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (prefillBaselineCapturedRef.current) return;\n\t\t\tconst seed = inputValue ?? '';\n\t\t\tif (seed.length > 0) {\n\t\t\t\tprefillBaselineTextRef.current = seed;\n\t\t\t\tprefillBaselineCapturedRef.current = true;\n\t\t\t}\n\t\t}, [prefillWasAiGenerated, inputValue, editorInstanceKey, editorSessionId]);\n\n\t\tconst activeActionPrompts = useMemo(() => {\n\t\t\treturn resolveActionPrompts(templateType, promptOverrides, rephraseTones);\n\t\t}, [promptOverrides, rephraseTones, templateType]);\n\n\t\tconst filteredInstructionSuggestions = useMemo(() => {\n\t\t\tconst query = instructionText.trim().toLowerCase();\n\t\t\tif (!query) return [];\n\t\t\treturn instructionSuggestions.filter((suggestion) =>\n\t\t\t\tsuggestion.toLowerCase().includes(query),\n\t\t\t);\n\t\t}, [instructionSuggestions, instructionText]);\n\n\t\tconst minCharsByAction = useMemo(() => {\n\t\t\treturn {\n\t\t\t\t...DEFAULT_AI_ACTION_MIN_CHARS,\n\t\t\t\t...(aiActionMinChars || {}),\n\t\t\t};\n\t\t}, [aiActionMinChars]);\n\n\t\tconst rephraseMinChars =\n\t\t\tminCharsByAction[AIEditorActionTypes.REPHRASE] ||\n\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[AIEditorActionTypes.REPHRASE];\n\n\t\tconst anonymizeInstructionText = useCallback((value: string) => {\n\t\t\tconst normalized = value.trim().replace(/\\s+/g, ' ');\n\t\t\tif (!normalized) return '';\n\t\t\tconst words = normalized.split(' ').length;\n\t\t\treturn `[anonymized:length_${normalized.length}:words_${words}]`;\n\t\t}, []);\n\n\t\tconst emitAIEvent = useCallback(\n\t\t\t(name: AIEventName, payload: AIEventPayload) => {\n\t\t\t\tonAnalyticsEvent?.(name, payload);\n\t\t\t},\n\t\t\t[onAnalyticsEvent],\n\t\t);\n\n\t\tconst setEditorText = useCallback((nextText: string) => {\n\t\t\tsetCurrentText((prev) => (prev === nextText ? prev : nextText));\n\t\t}, []);\n\n\t\tconst emitChangeWithGuard = useCallback(\n\t\t\t(nextText: string) => {\n\t\t\t\tif (deferredHtmlRef.current) {\n\t\t\t\t\tclearTimeout(deferredHtmlRef.current);\n\t\t\t\t}\n\t\t\t\tif (nextText.length > LARGE_INPUT_THRESHOLD) {\n\t\t\t\t\tonChange?.(nextText, nextText);\n\t\t\t\t\tdeferredHtmlRef.current = setTimeout(() => {\n\t\t\t\t\t\tonChange?.(nextText, baseWhatsappContentLang.getHTML(nextText));\n\t\t\t\t\t}, 16);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonChange?.(nextText, baseWhatsappContentLang.getHTML(nextText));\n\t\t\t},\n\t\t\t[onChange],\n\t\t);\n\n\t\tconst emitPostEditAiTagRecompute = useCallback(\n\t\t\t(nextText: string) => {\n\t\t\t\tconst latest = acceptedSuggestionStateRef.current;\n\t\t\t\tconst latestBaseline =\n\t\t\t\t\tlatest?.acceptedText ||\n\t\t\t\t\t(prefillWasAiGenerated ? prefillBaselineTextRef.current : '');\n\t\t\t\tif (!latestBaseline) return;\n\t\t\t\tif (nextText === latestBaseline) return;\n\t\t\t\tconst recomputePayload = computeAiTagOnPostEdit({\n\t\t\t\t\tacceptedAiText: latestBaseline,\n\t\t\t\t\tcurrentEditedText: nextText,\n\t\t\t\t});\n\t\t\t\tonAITagComputed?.({\n\t\t\t\t\t...recomputePayload,\n\t\t\t\t\tsource: 'post_edit_debounce',\n\t\t\t\t});\n\t\t\t},\n\t\t\t[onAITagComputed, prefillWasAiGenerated],\n\t\t);\n\n\t\tconst clearSuggestionSession = useCallback(() => {\n\t\t\tsetSuggestionBaseText(null);\n\t\t\tsetSuggestionCandidates([]);\n\t\t\tsetSuggestionIndex(0);\n\t\t\tsetSuggestionActionType(null);\n\t\t\tsetFeedbackVotesByCandidate({});\n\t\t}, []);\n\n\t\tconst triggerRephraseHighlight = useCallback(() => {\n\t\t\tif (isGenerating) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!!suggestionBaseText && suggestionCandidates.length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (rephraseHighlightCount >= MAX_REPHRASE_HIGHLIGHTS) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextCount = rephraseHighlightCount + 1;\n\t\t\tsetRephraseHighlightCount(nextCount);\n\t\t\tif (typeof window !== 'undefined' && editorInstanceKey) {\n\t\t\t\tsessionStorage.setItem(highlightStorageKey, String(nextCount));\n\t\t\t}\n\t\t\tsetIsRephraseHighlighted(true);\n\t\t\tif (highlightResetRef.current) {\n\t\t\t\tclearTimeout(highlightResetRef.current);\n\t\t\t}\n\t\t\thighlightResetRef.current = setTimeout(() => {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t}, 1200);\n\t\t}, [\n\t\t\teditorInstanceKey,\n\t\t\thighlightStorageKey,\n\t\t\tisGenerating,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionCandidates,\n\t\t\trephraseHighlightCount,\n\t\t]);\n\n\t\tconst triggerRephraseHighlightRef = useRef(triggerRephraseHighlight);\n\t\ttriggerRephraseHighlightRef.current = triggerRephraseHighlight;\n\n\t\tfunction handleOnChange(e: React.ChangeEvent<HTMLTextAreaElement>) {\n\t\t\tconst text = stripHtmlTags(e.target.value);\n\t\t\tconst acceptedSuggestion = acceptedSuggestionStateRef.current;\n\t\t\tif (\n\t\t\t\tacceptedSuggestion &&\n\t\t\t\t!acceptedSuggestion.editedEventEmitted &&\n\t\t\t\ttext !== acceptedSuggestion.acceptedText\n\t\t\t) {\n\t\t\t\tacceptedSuggestionStateRef.current = {\n\t\t\t\t\t...acceptedSuggestion,\n\t\t\t\t\teditedEventEmitted: true,\n\t\t\t\t};\n\t\t\t\temitAIEvent('ai_suggestion_edited', {\n\t\t\t\t\taction_type: acceptedSuggestion.actionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (aiTagRecomputeRef.current) {\n\t\t\t\tclearTimeout(aiTagRecomputeRef.current);\n\t\t\t\taiTagRecomputeRef.current = null;\n\t\t\t}\n\t\t\tconst baselineAiTextForRecompute =\n\t\t\t\tacceptedSuggestion?.acceptedText ||\n\t\t\t\t(prefillWasAiGenerated ? prefillBaselineTextRef.current : '');\n\t\t\tif (baselineAiTextForRecompute && text !== baselineAiTextForRecompute) {\n\t\t\t\taiTagRecomputeRef.current = setTimeout(() => {\n\t\t\t\t\temitPostEditAiTagRecompute(text);\n\t\t\t\t}, AI_TAG_RECOMPUTE_IDLE_MS);\n\t\t\t}\n\t\t\tsetEditorText(text);\n\t\t\temitChangeWithGuard(text);\n\t\t}\n\n\t\tfunction setCaretPosition(caretPos: number) {\n\t\t\tconst elem = textSpaceRef?.current;\n\n\t\t\tif (elem != null) {\n\t\t\t\tif (elem.selectionStart) {\n\t\t\t\t\telem.focus();\n\t\t\t\t\telem.selectionEnd = caretPos;\n\t\t\t\t} else elem.focus();\n\t\t\t}\n\t\t}\n\n\t\tfunction onActionSelect(actionType: EditorActionTypes) {\n\t\t\tconst wildCard = WildCardMap[actionType];\n\t\t\tif (wildCard && textSpaceRef.current) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\n\t\t\t\tif (start === end) {\n\t\t\t\t\tconst { text } = insertTextAtIndex(wildCard, start);\n\t\t\t\t\tsetCaretPosition(start + 1);\n\t\t\t\t\temitChangeWithGuard(text);\n\t\t\t\t} else {\n\t\t\t\t\tconst { text } = addTextOrWrap(wildCard);\n\t\t\t\t\temitChangeWithGuard(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction onEmojiAddition(emoji: string) {\n\t\t\tconst { text } = addText(emoji);\n\t\t\temitChangeWithGuard(text);\n\t\t}\n\n\t\tfunction addTextOrWrap(textToAdd?: string) {\n\t\t\tlet text = textSpaceRef.current?.value ?? '';\n\n\t\t\tif (textSpaceRef.current && textToAdd) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\n\t\t\t\tconst wildCard = textToAdd;\n\t\t\t\tif (start === end) {\n\t\t\t\t\t/** nothing is selected */\n\t\t\t\t\t/** so append the wildcard at the end */\n\n\t\t\t\t\treturn addText(wildCard);\n\t\t\t\t} else {\n\t\t\t\t\ttext = baseWhatsappContentLang.wrappWildcard(\n\t\t\t\t\t\tstart,\n\t\t\t\t\t\tend,\n\t\t\t\t\t\twildCard,\n\t\t\t\t\t\ttext!,\n\t\t\t\t\t);\n\t\t\t\t\tconst html = baseWhatsappContentLang.getHTML(text);\n\t\t\t\t\tsetEditorText(text);\n\t\t\t\t\treturn { text, html };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { text: text!, html: text! };\n\t\t}\n\n\t\tfunction addText(textToAdd: string) {\n\t\t\tconst text = textSpaceRef.current?.value ?? '';\n\n\t\t\tif (textSpaceRef.current && textToAdd) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\t\t\t\tif (start === end) {\n\t\t\t\t\treturn insertTextAtIndex(textToAdd, start);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { text: text!, html: text! };\n\t\t}\n\n\t\tfunction insertTextAtIndex(textToAdd: string, index: number) {\n\t\t\tlet text = textSpaceRef.current?.value ?? '';\n\n\t\t\ttext = text.slice(0, index) + textToAdd + text.slice(index);\n\t\t\tconst html = baseWhatsappContentLang.getHTML(text);\n\t\t\tsetEditorText(text);\n\t\t\treturn { text, html };\n\t\t}\n\n\t\tuseEffect(() => {\n\t\t\tif (typeof window === 'undefined' || !editorInstanceKey) return;\n\t\t\tconst cached = Number(sessionStorage.getItem(highlightStorageKey) || '0');\n\t\t\tif (!Number.isNaN(cached)) {\n\t\t\t\tsetRephraseHighlightCount(cached);\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\tsessionStorage.removeItem(highlightStorageKey);\n\t\t\t};\n\t\t}, [editorInstanceKey, highlightStorageKey]);\n\n\t\tuseEffect(() => {\n\t\t\tif (isGenerating) {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!!suggestionBaseText && suggestionCandidates.length > 0) {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst eligible =\n\t\t\t\t!!currentText.trim() && currentText.length >= rephraseMinChars;\n\n\t\t\tif (prevRephraseEligibleRef.current === null) {\n\t\t\t\tprevRephraseEligibleRef.current = eligible;\n\t\t\t\tif (eligible) {\n\t\t\t\t\trephraseIdleRef.current = setTimeout(() => {\n\t\t\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t\t\t}, REPHRASE_IDLE_MS);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!eligible) {\n\t\t\t\tprevRephraseEligibleRef.current = false;\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst crossedThreshold = !prevRephraseEligibleRef.current && eligible;\n\t\t\tprevRephraseEligibleRef.current = true;\n\n\t\t\tif (crossedThreshold) {\n\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t}\n\n\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t}\n\t\t\trephraseIdleRef.current = setTimeout(() => {\n\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t}, REPHRASE_IDLE_MS);\n\t\t}, [\n\t\t\tcurrentText,\n\t\t\tisGenerating,\n\t\t\trephraseMinChars,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionCandidates,\n\t\t]);\n\n\t\tuseEffect(() => {\n\t\t\treturn () => {\n\t\t\t\tif (rephraseIdleRef.current) clearTimeout(rephraseIdleRef.current);\n\t\t\t\tif (highlightResetRef.current) clearTimeout(highlightResetRef.current);\n\t\t\t\tif (deferredHtmlRef.current) clearTimeout(deferredHtmlRef.current);\n\t\t\t\tif (aiTagRecomputeRef.current) clearTimeout(aiTagRecomputeRef.current);\n\t\t\t};\n\t\t}, []);\n\n\t\tconst activeCandidate = suggestionCandidates[suggestionIndex] || '';\n\t\tconst activeFeedbackCandidateKey = useMemo(() => {\n\t\t\tif (!suggestionActionType || !activeCandidate) return null;\n\t\t\treturn `${suggestionActionType}-${suggestionIndex}-${activeCandidate}`;\n\t\t}, [activeCandidate, suggestionActionType, suggestionIndex]);\n\t\tconst hasFeedbackForActiveCandidate = !!(\n\t\t\tactiveFeedbackCandidateKey &&\n\t\t\tfeedbackVotesByCandidate[activeFeedbackCandidateKey]\n\t\t);\n\t\tconst suggestionBaseHtml = useMemo(\n\t\t\t() => baseWhatsappContentLang.getHTML(suggestionBaseText || ''),\n\t\t\t[suggestionBaseText],\n\t\t);\n\t\tconst activeCandidateHtml = useMemo(\n\t\t\t() => baseWhatsappContentLang.getHTML(activeCandidate),\n\t\t\t[activeCandidate],\n\t\t);\n\t\tconst canRegenerate = suggestionCandidates.length < MAX_SUGGESTIONS;\n\t\tconst shouldShowSuggestionSession =\n\t\t\t!!suggestionBaseText && suggestionCandidates.length > 0;\n\t\tconst isPrevSuggestionDisabled =\n\t\t\tsuggestionCandidates.length <= 1 || suggestionIndex <= 0;\n\t\tconst isNextSuggestionDisabled =\n\t\t\tsuggestionCandidates.length <= 1 ||\n\t\t\tsuggestionIndex >= suggestionCandidates.length - 1;\n\n\t\tuseEffect(() => {\n\t\t\tif (!shouldShowSuggestionSession) return;\n\t\t\tconst node = suggestionScrollRef.current;\n\t\t\tif (!node) return;\n\t\t\tnode.scrollTop = node.scrollHeight;\n\t\t}, [activeCandidate, shouldShowSuggestionSession, isGenerating]);\n\n\t\tconst executeAIAction = useCallback(\n\t\t\tasync (\n\t\t\t\tactionType: AIEditorActionType,\n\t\t\t\tregenerateExisting = false,\n\t\t\t\tinstructionOverride?: string,\n\t\t\t\ttoneOverrideId?: string,\n\t\t\t\tactionVariant: AIActionVariant = AIActionVariant.DEFAULT,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\t!onAIActionRequest &&\n\t\t\t\t\t!apiAdapter &&\n\t\t\t\t\t(!requestExecutor || !baseUrl)\n\t\t\t\t) {\n\t\t\t\t\tonError?.('AI configuration missing');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!currentText.trim()) return;\n\t\t\t\tconst minCharsForAction =\n\t\t\t\t\tminCharsByAction[actionType] ||\n\t\t\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[actionType] ||\n\t\t\t\t\t50;\n\t\t\t\tif (currentText.length < minCharsForAction) return;\n\t\t\t\tif (isGenerating) return;\n\t\t\t\tif (regenerateExisting && !canRegenerate) return;\n\n\t\t\t\tconst baseConfig = activeActionPrompts[actionType];\n\t\t\t\tconst config =\n\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\ttemplateType === 'utility' &&\n\t\t\t\t\tactionVariant === AIActionVariant.REPHRASE\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t...baseConfig,\n\t\t\t\t\t\t\t\tlabel: 'Rephrase',\n\t\t\t\t\t\t\t\tbasePrompt: UTILITY_REPHRASE_PROMPT,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: baseConfig;\n\t\t\t\t// Tone is sent only after explicit user selection (or explicit override),\n\t\t\t\t// not from default tone metadata.\n\t\t\t\tconst selectedToneId = toneOverrideId || toneByAction[actionType];\n\t\t\t\tconst selectedTone = config.tones?.find(\n\t\t\t\t\t(tone) => tone.id === selectedToneId,\n\t\t\t\t);\n\t\t\t\tconst instructionForPrompt =\n\t\t\t\t\tinstructionOverride !== undefined\n\t\t\t\t\t\t? instructionOverride\n\t\t\t\t\t\t: instructionText;\n\t\t\t\tconst prompt =\n\t\t\t\t\tonBuildAIPrompt?.({\n\t\t\t\t\t\tactionType,\n\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\ttemplateType,\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\ttoneId: selectedToneId,\n\t\t\t\t\t\ttoneLabel: selectedTone?.label,\n\t\t\t\t\t\tinstructionText: instructionForPrompt || undefined,\n\t\t\t\t\t}) ||\n\t\t\t\t\tbuildActionPrompt({\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\tselectedToneId,\n\t\t\t\t\t\tinstructionText: instructionForPrompt,\n\t\t\t\t\t});\n\n\t\t\t\tsetIsGenerating(true);\n\t\t\t\temitAIEvent('ai_action_triggered', {\n\t\t\t\t\taction_type: actionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\ttemplate_category: templateType,\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tconst result = onAIActionRequest\n\t\t\t\t\t\t? await onAIActionRequest({\n\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\t\t\ttemplateType,\n\t\t\t\t\t\t\t\ttoneId: selectedToneId,\n\t\t\t\t\t\t\t\ttoneLabel: selectedTone?.label,\n\t\t\t\t\t\t\t\tinstructionText: instructionForPrompt || undefined,\n\t\t\t\t\t\t\t\tprompt,\n\t\t\t\t\t\t })\n\t\t\t\t\t\t: await requestAISuggestion({\n\t\t\t\t\t\t\t\tapiAdapter,\n\t\t\t\t\t\t\t\trequestExecutor,\n\t\t\t\t\t\t\t\tbaseUrl,\n\t\t\t\t\t\t\t\tendpointPath,\n\t\t\t\t\t\t\t\tprompt,\n\t\t\t\t\t\t\t\tintent,\n\t\t\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\t\t\tsystemId,\n\t\t\t\t\t\t\t\tuseCase,\n\t\t\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\t });\n\t\t\t\t\tconst candidate =\n\t\t\t\t\t\ttypeof result === 'string'\n\t\t\t\t\t\t\t? result.trim()\n\t\t\t\t\t\t\t: (result?.body || '').trim();\n\t\t\t\t\tif (!candidate) return;\n\t\t\t\t\tif (!regenerateExisting) {\n\t\t\t\t\t\tsetSuggestionBaseText(currentText);\n\t\t\t\t\t\tsetSuggestionActionType(actionType);\n\t\t\t\t\t\tsetSuggestionCandidates([candidate]);\n\t\t\t\t\t\tsetSuggestionIndex(0);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tsetSuggestionCandidates((prev) => {\n\t\t\t\t\t\tconst next = [...prev, candidate].slice(0, MAX_SUGGESTIONS);\n\t\t\t\t\t\tsetSuggestionIndex(next.length - 1);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tonError?.('Failed to generate AI suggestion');\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsGenerating(false);\n\t\t\t\t}\n\t\t\t},\n\t\t\t[\n\t\t\t\trequestExecutor,\n\t\t\t\tbaseUrl,\n\t\t\t\tcurrentText,\n\t\t\t\tisGenerating,\n\t\t\t\tcanRegenerate,\n\t\t\t\tactiveActionPrompts,\n\t\t\t\ttoneByAction,\n\t\t\t\tinstructionText,\n\t\t\t\temitAIEvent,\n\t\t\t\ttemplateId,\n\t\t\t\tendpointPath,\n\t\t\t\tapiAdapter,\n\t\t\t\tintent,\n\t\t\t\tconversationId,\n\t\t\t\tsystemId,\n\t\t\t\tuseCase,\n\t\t\t\tstoreId,\n\t\t\t\ttemplateType,\n\t\t\t\tonError,\n\t\t\t\tminCharsByAction,\n\t\t\t\tonAIActionRequest,\n\t\t\t\tonBuildAIPrompt,\n\t\t\t],\n\t\t);\n\n\t\tconst handleAcceptSuggestion = useCallback(() => {\n\t\t\tif (!activeCandidate || !suggestionBaseText || !suggestionActionType)\n\t\t\t\treturn;\n\t\t\tsetEditorText(activeCandidate);\n\t\t\temitChangeWithGuard(activeCandidate);\n\t\t\temitAIEvent('ai_suggestion_accepted', {\n\t\t\t\taction_type: suggestionActionType,\n\t\t\t\ttemplate_id: templateId,\n\t\t\t});\n\t\t\tacceptedSuggestionStateRef.current = {\n\t\t\t\tacceptedText: activeCandidate,\n\t\t\t\tbaselineText: suggestionBaseText,\n\t\t\t\tactionType: suggestionActionType,\n\t\t\t\teditedEventEmitted: false,\n\t\t\t};\n\n\t\t\tconst inInitialAiPhase = initialAiPrefillPhaseRef.current;\n\t\t\tconst tagPayload = computeAiTagOnAccept({\n\t\t\t\tbaselineText: suggestionBaseText,\n\t\t\t\tacceptedText: activeCandidate,\n\t\t\t\tinitialAiPrefillPhase: inInitialAiPhase,\n\t\t\t});\n\t\t\tif (inInitialAiPhase) {\n\t\t\t\tinitialAiPrefillPhaseRef.current = false;\n\t\t\t}\n\t\t\tonAITagComputed?.({\n\t\t\t\t...tagPayload,\n\t\t\t\tsource: 'accept',\n\t\t\t});\n\t\t\tclearSuggestionSession();\n\t\t}, [\n\t\t\tactiveCandidate,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionActionType,\n\t\t\tsetEditorText,\n\t\t\temitChangeWithGuard,\n\t\t\temitAIEvent,\n\t\t\ttemplateId,\n\t\t\tonAITagComputed,\n\t\t\tclearSuggestionSession,\n\t\t]);\n\n\t\tconst handleRejectSuggestion = useCallback(() => {\n\t\t\tif (!suggestionActionType) return;\n\t\t\temitAIEvent('ai_suggestion_discarded', {\n\t\t\t\taction_type: suggestionActionType,\n\t\t\t\ttemplate_id: templateId,\n\t\t\t});\n\t\t\tclearSuggestionSession();\n\t\t}, [clearSuggestionSession, emitAIEvent, suggestionActionType, templateId]);\n\n\t\tconst handleFeedback = useCallback(\n\t\t\t(rating: AIFeedbackRating) => {\n\t\t\t\tif (!suggestionActionType || !activeFeedbackCandidateKey) return;\n\t\t\t\tif (feedbackVotesByCandidate[activeFeedbackCandidateKey]) return;\n\t\t\t\tsetFeedbackVotesByCandidate((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t[activeFeedbackCandidateKey]: rating,\n\t\t\t\t}));\n\t\t\t\temitAIEvent('ai_feedback_submitted', {\n\t\t\t\t\taction_type: suggestionActionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\trating,\n\t\t\t\t\tcandidate_index: suggestionIndex + 1,\n\t\t\t\t});\n\t\t\t},\n\t\t\t[\n\t\t\t\tactiveFeedbackCandidateKey,\n\t\t\t\temitAIEvent,\n\t\t\t\tfeedbackVotesByCandidate,\n\t\t\t\tsuggestionActionType,\n\t\t\t\tsuggestionIndex,\n\t\t\t\ttemplateId,\n\t\t\t],\n\t\t);\n\n\t\tconst aiHeaderActions: AIHeaderAction[] = useMemo(() => {\n\t\t\tif (disableBuiltInAIActions) return [];\n\t\t\treturn enabledAIActions.map((actionType) => {\n\t\t\t\tconst actionConfig = activeActionPrompts[actionType];\n\t\t\t\tconst toneId = toneByAction[actionType];\n\t\t\t\treturn {\n\t\t\t\t\ttype: actionType,\n\t\t\t\t\tlabel: actionConfig.label,\n\t\t\t\t\tisPrimary: actionType === AIEditorActionTypes.REPHRASE,\n\t\t\t\t\tloading: isGenerating && suggestionActionType === actionType,\n\t\t\t\t\thighlighted:\n\t\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\t\tisRephraseHighlighted,\n\t\t\t\t\tdisabled:\n\t\t\t\t\t\t!currentText.trim() ||\n\t\t\t\t\t\tcurrentText.length <\n\t\t\t\t\t\t\t(minCharsByAction[actionType] ||\n\t\t\t\t\t\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[actionType] ||\n\t\t\t\t\t\t\t\t50) ||\n\t\t\t\t\t\tisGenerating ||\n\t\t\t\t\t\t(shouldShowSuggestionSession &&\n\t\t\t\t\t\t\tsuggestionActionType === actionType),\n\t\t\t\t\tshowToneDropdown:\n\t\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\t\t!!actionConfig.tones?.length,\n\t\t\t\t\ttones: actionConfig.tones,\n\t\t\t\t\tselectedToneId: toneId,\n\t\t\t\t};\n\t\t\t});\n\t\t}, [\n\t\t\tenabledAIActions,\n\t\t\tdisableBuiltInAIActions,\n\t\t\tactiveActionPrompts,\n\t\t\ttoneByAction,\n\t\t\tisGenerating,\n\t\t\tsuggestionActionType,\n\t\t\tshouldShowSuggestionSession,\n\t\t\tisRephraseHighlighted,\n\t\t\tcurrentText,\n\t\t\tminCharsByAction,\n\t\t]);\n\n\t\tuseImperativeHandle(\n\t\t\tref,\n\t\t\t() => {\n\t\t\t\treturn {\n\t\t\t\t\taddTextOrWrap,\n\t\t\t\t\taddText,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn currentText;\n\t\t\t\t\t},\n\t\t\t\t\tsetCaretPosition,\n\t\t\t\t};\n\t\t\t},\n\t\t\t[addTextOrWrap, addText, currentText],\n\t\t);\n\n\t\tuseEffect(() => {\n\t\t\tif (inputValue === undefined) return;\n\t\t\tsetEditorText(inputValue || '');\n\t\t}, [inputValue, setEditorText]);\n\n\t\tuseEffect(() => {\n\t\t\tif (!limit || !onError) return;\n\t\t\tconst nextError =\n\t\t\t\tcurrentText.length > limit ? LIMIT_REACHED : error ?? '';\n\t\t\tif (lastEmittedEditorErrorRef.current === nextError) return;\n\t\t\tlastEmittedEditorErrorRef.current = nextError;\n\t\t\tonError(nextError);\n\t\t}, [currentText, error, limit, onError]);\n\n\t\treturn (\n\t\t\t<OuterContainer>\n\t\t\t\t<EditorFooterRow>\n\t\t\t\t\t<EditorFooterTitle>\n\t\t\t\t\t\t{editorHeader ? (\n\t\t\t\t\t\t\t<TitleSmall data-test=\"body-text-for-edit-template\">\n\t\t\t\t\t\t\t\t{editorHeader}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</EditorFooterTitle>\n\t\t\t\t\t<EditorFooterRight>\n\t\t\t\t\t\t{error && error !== LIMIT_REACHED ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<InfoIcon\n\t\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\t\tcolor={COLORS.content.negative}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{limit ? (\n\t\t\t\t\t\t\t<BodyCaption\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\t\terror === LIMIT_REACHED || currentText.length > limit\n\t\t\t\t\t\t\t\t\t\t\t? COLORS.content.negative\n\t\t\t\t\t\t\t\t\t\t\t: COLORS.content.secondary,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{currentText.length}/{limit}\n\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</EditorFooterRight>\n\t\t\t\t</EditorFooterRow>\n\t\t\t\t<Container isError={!!error}>\n\t\t\t\t\t{shouldShowSuggestionSession ? (\n\t\t\t\t\t\t<SuggestionSessionContainer ref={suggestionScrollRef}>\n\t\t\t\t\t\t\t<SuggestionBaselineText\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: suggestionBaseHtml }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{isGenerating ? (\n\t\t\t\t\t\t\t\t<SuggestionCandidateText aria-busy=\"true\">\n\t\t\t\t\t\t\t\t\t<SuggestionCandidateSkeleton>\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"96%\" />\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"84%\" />\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"68%\" />\n\t\t\t\t\t\t\t\t\t</SuggestionCandidateSkeleton>\n\t\t\t\t\t\t\t\t</SuggestionCandidateText>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<SuggestionCandidateText\n\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t__html: activeCandidateHtml,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<SuggestionControlsRow>\n\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\taria-label=\"Previous suggestion\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isPrevSuggestionDisabled}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tsetSuggestionIndex((idx) => Math.max(0, idx - 1))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ChevronLeftIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t<SuggestionCounter>\n\t\t\t\t\t\t\t\t\t{suggestionIndex + 1}/{suggestionCandidates.length}\n\t\t\t\t\t\t\t\t</SuggestionCounter>\n\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\taria-label=\"Next suggestion\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isNextSuggestionDisabled}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tsetSuggestionIndex((idx) =>\n\t\t\t\t\t\t\t\t\t\t\tMath.min(suggestionCandidates.length - 1, idx + 1),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ChevronRightIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Like\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Like suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdisabled={hasFeedbackForActiveCandidate}\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(AIFeedbackRating.LIKE)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ThumbsUpIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Dislike\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Dislike suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdisabled={hasFeedbackForActiveCandidate}\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(AIFeedbackRating.DISLIKE)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ThumbsDownIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t{canRegenerate ? (\n\t\t\t\t\t\t\t\t\t<Tooltip\n\t\t\t\t\t\t\t\t\t\tbody={isGenerating ? 'Regenerating…' : 'Regenerate'}\n\t\t\t\t\t\t\t\t\t\tplacement=\"top\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<SuggestionRegenerateButton\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Regenerate suggestion\"\n\t\t\t\t\t\t\t\t\t\t\taria-busy={isGenerating}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isGenerating}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (suggestionActionType) {\n\t\t\t\t\t\t\t\t\t\t\t\t\texecuteAIAction(suggestionActionType, true);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{isGenerating ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<RegenerateIconShimmer aria-hidden />\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<RewindIcon width={14} height={14} />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</SuggestionRegenerateButton>\n\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<Tooltip body=\"Discard\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Discard suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleRejectSuggestion}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CrossIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Accept\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Accept suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleAcceptSuggestion}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CheckIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t</SuggestionControlsRow>\n\t\t\t\t\t\t</SuggestionSessionContainer>\n\t\t\t\t\t) : isGenerating ? (\n\t\t\t\t\t\t<EditorSkeletonContainer>\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"96%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"92%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"88%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"54%\" />\n\t\t\t\t\t\t</EditorSkeletonContainer>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<TextSpace\n\t\t\t\t\t\t\tref={textSpaceRef}\n\t\t\t\t\t\t\t{...textAreaProps}\n\t\t\t\t\t\t\tvalue={currentText}\n\t\t\t\t\t\t\tonChange={handleOnChange}\n\t\t\t\t\t\t\tonBlur={(e) => {\n\t\t\t\t\t\t\t\tif (aiTagRecomputeRef.current) {\n\t\t\t\t\t\t\t\t\tclearTimeout(aiTagRecomputeRef.current);\n\t\t\t\t\t\t\t\t\taiTagRecomputeRef.current = null;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\temitPostEditAiTagRecompute(e.target.value);\n\t\t\t\t\t\t\t\ttextAreaOnBlur?.(e);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonPaste={(e) => {\n\t\t\t\t\t\t\t\tconst pastedText = e.clipboardData.getData('text');\n\t\t\t\t\t\t\t\tif (pastedText.length > LARGE_INPUT_THRESHOLD) {\n\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\tconst el = textSpaceRef.current;\n\t\t\t\t\t\t\t\t\tconst start = el?.selectionStart ?? 0;\n\t\t\t\t\t\t\t\t\tconst end = el?.selectionEnd ?? start;\n\t\t\t\t\t\t\t\t\t// Prefer live DOM value — `currentText` can lag the textarea for big pastes.\n\t\t\t\t\t\t\t\t\tconst base = el?.value ?? currentText;\n\t\t\t\t\t\t\t\t\tconst nextText =\n\t\t\t\t\t\t\t\t\t\tbase.slice(0, start) + pastedText + base.slice(end);\n\t\t\t\t\t\t\t\t\tsetEditorText(nextText);\n\t\t\t\t\t\t\t\t\temitChangeWithGuard(nextText);\n\t\t\t\t\t\t\t\t\tconst caret = start + pastedText.length;\n\t\t\t\t\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\t\t\t\t\tconst ta = textSpaceRef.current;\n\t\t\t\t\t\t\t\t\t\tif (!ta) return;\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tta.setSelectionRange(caret, caret);\n\t\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t\t// ignore invalid range in edge browsers\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\trows={rows}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{isInstructionInputVisible ? (\n\t\t\t\t\t\t<InstructionContainer>\n\t\t\t\t\t\t\t<InstructionInputRow>\n\t\t\t\t\t\t\t\t<EditIcon\n\t\t\t\t\t\t\t\t\twidth={18}\n\t\t\t\t\t\t\t\t\theight={18}\n\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<InstructionInput\n\t\t\t\t\t\t\t\t\tvalue={instructionText}\n\t\t\t\t\t\t\t\t\tplaceholder=\"Add specific instructions to refine your message\"\n\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\tsetInstructionText(stripHtmlTags(e.target.value))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<InstructionActions>\n\t\t\t\t\t\t\t\t\t<InstructionCancel\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetInstructionText('');\n\t\t\t\t\t\t\t\t\t\t\tsetIsInstructionInputVisible(false);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t</InstructionCancel>\n\t\t\t\t\t\t\t\t\t<InstructionImprove\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tconst instructionToApply = instructionText.trim();\n\t\t\t\t\t\t\t\t\t\t\tif (instructionToApply) {\n\t\t\t\t\t\t\t\t\t\t\t\temitAIEvent('ai_instruction_used', {\n\t\t\t\t\t\t\t\t\t\t\t\t\taction_type: AIEditorActionTypes.REPHRASE,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\t\t\t\t\t\t\t\t\tinstruction_text:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tanonymizeInstructionText(instructionToApply),\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tsetIsInstructionInputVisible(false);\n\t\t\t\t\t\t\t\t\t\t\tsetInstructionText('');\n\t\t\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\t\t\tAIEditorActionTypes.REPHRASE,\n\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\tinstructionToApply,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tImprove\n\t\t\t\t\t\t\t\t\t</InstructionImprove>\n\t\t\t\t\t\t\t\t</InstructionActions>\n\t\t\t\t\t\t\t</InstructionInputRow>\n\t\t\t\t\t\t\t{instructionText.trim().length > 0 &&\n\t\t\t\t\t\t\tfilteredInstructionSuggestions.length > 0 ? (\n\t\t\t\t\t\t\t\t<InstructionSuggestionList>\n\t\t\t\t\t\t\t\t\t{filteredInstructionSuggestions.map((suggestion) => (\n\t\t\t\t\t\t\t\t\t\t<InstructionSuggestionButton\n\t\t\t\t\t\t\t\t\t\t\tkey={suggestion}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tselected={instructionText === suggestion}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setInstructionText(suggestion)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{suggestion}\n\t\t\t\t\t\t\t\t\t\t</InstructionSuggestionButton>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</InstructionSuggestionList>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</InstructionContainer>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<WhatsAppTextEditorHeader\n\t\t\t\t\t\t\tactions={actions}\n\t\t\t\t\t\t\tref={textSpaceRef}\n\t\t\t\t\t\t\tonActionSelect={onActionSelect}\n\t\t\t\t\t\t\tRightComponent={RightComponent}\n\t\t\t\t\t\t\trightActionsDisabled={shouldShowSuggestionSession || isGenerating}\n\t\t\t\t\t\t\tonEmojiClick={onEmojiAddition}\n\t\t\t\t\t\t\taiActions={aiHeaderActions}\n\t\t\t\t\t\t\tdisableAllActions={shouldShowSuggestionSession || isGenerating}\n\t\t\t\t\t\t\tinstructionActive={isInstructionInputVisible}\n\t\t\t\t\t\t\tonAIInstructionsClick={() => setIsInstructionInputVisible(true)}\n\t\t\t\t\t\t\tonAIToneChange={(actionType, toneId) => {\n\t\t\t\t\t\t\t\tsetToneByAction((prev) => ({ ...prev, [actionType]: toneId }));\n\t\t\t\t\t\t\t\tonAIToneSelect?.(actionType, toneId);\n\t\t\t\t\t\t\t\tif (actionType === AIEditorActionTypes.REPHRASE) {\n\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\ttoneId,\n\t\t\t\t\t\t\t\t\t\tAIActionVariant.DEFAULT,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonAIActionClick={(\n\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\tactionVariant = AIActionVariant.DEFAULT,\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\tif (isGenerating) return;\n\n\t\t\t\t\t\t\t\tif (shouldShowSuggestionSession) {\n\t\t\t\t\t\t\t\t\tif (suggestionActionType === actionType) {\n\t\t\t\t\t\t\t\t\t\t// Same action should not retrigger from chip;\n\t\t\t\t\t\t\t\t\t\t// regenerate is only via explicit regenerate control.\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// New action starts a fresh suggestion session.\n\t\t\t\t\t\t\t\t\tclearSuggestionSession();\n\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</Container>\n\t\t\t</OuterContainer>\n\t\t);\n\t},\n);\n\nWhatsAppTextEditor.displayName = 'WhatsAppTextEditor';\n\nexport type { AITagPayload } from './ai/aiTag';\nexport {\n\tAI_TAG_CHANGE_RATIO_THRESHOLD,\n\tcomputeAiTagOnAccept,\n\tlevenshteinDistance,\n} from './ai/aiTag';\n"],"names":["LIMIT_REACHED","REPHRASE_IDLE_MS","MAX_REPHRASE_HIGHLIGHTS","MAX_SUGGESTIONS","LARGE_INPUT_THRESHOLD","AI_TAG_RECOMPUTE_IDLE_MS","UTILITY_REPHRASE_PROMPT","skeletonPulse","keyframes","EditorSkeletonContainer","styled","EditorSkeletonLine","props","SuggestionSessionContainer","SuggestionBaselineText","COLORS","SuggestionCandidateText","SuggestionCandidateSkeleton","SuggestionControlsRow","SuggestionCounter","SuggestionIconButton","SuggestionRegenerateButton","RegenerateIconShimmer","InstructionContainer","InstructionInputRow","InstructionInput","InstructionActions","InstructionCancel","InstructionImprove","InstructionSuggestionList","InstructionSuggestionButton","baseWhatsappContentLang","BaseWhatsappContentLangHelper","WildCardMap","EditorActionTypes","getHighlightStorageKey","editorInstanceKey","WhatsAppTextEditor","React","onChange","onClickVariable","inputValue","RightComponent","error","limit","onError","rows","actions","editorSessionId","templateType","templateId","requestExecutor","baseUrl","endpointPath","useCase","storeId","apiAdapter","conversationId","systemId","intent","enabledAIActions","AIEditorActionTypes","disableBuiltInAIActions","promptOverrides","rephraseTones","aiActionMinChars","instructionSuggestions","DEFAULT_INSTRUCTION_SUGGESTIONS","onAnalyticsEvent","onAITagComputed","prefillWasAiGenerated","editorHeader","onAIToneSelect","onAIActionRequest","onBuildAIPrompt","textAreaOnBlur","textAreaProps","ref","textSpaceRef","useRef","currentText","setCurrentText","useState","isRephraseHighlighted","setIsRephraseHighlighted","rephraseHighlightCount","setRephraseHighlightCount","isGenerating","setIsGenerating","isInstructionInputVisible","setIsInstructionInputVisible","instructionText","setInstructionText","toneByAction","setToneByAction","suggestionBaseText","setSuggestionBaseText","suggestionCandidates","setSuggestionCandidates","suggestionIndex","setSuggestionIndex","suggestionActionType","setSuggestionActionType","suggestionScrollRef","rephraseIdleRef","highlightResetRef","aiTagRecomputeRef","prevRephraseEligibleRef","deferredHtmlRef","lastEmittedEditorErrorRef","initialAiPrefillPhaseRef","acceptedSuggestionStateRef","prefillBaselineTextRef","prefillBaselineCapturedRef","feedbackVotesByCandidate","setFeedbackVotesByCandidate","mountSessionIdRef","highlightStorageKey","useMemo","useEffect","seed","activeActionPrompts","resolveActionPrompts","filteredInstructionSuggestions","query","suggestion","minCharsByAction","DEFAULT_AI_ACTION_MIN_CHARS","rephraseMinChars","anonymizeInstructionText","useCallback","value","normalized","words","emitAIEvent","name","payload","setEditorText","nextText","prev","emitChangeWithGuard","emitPostEditAiTagRecompute","latestBaseline","recomputePayload","computeAiTagOnPostEdit","clearSuggestionSession","triggerRephraseHighlight","nextCount","triggerRephraseHighlightRef","handleOnChange","text","stripHtmlTags","acceptedSuggestion","baselineAiTextForRecompute","setCaretPosition","caretPos","elem","onActionSelect","actionType","wildCard","start","end","insertTextAtIndex","addTextOrWrap","onEmojiAddition","emoji","addText","textToAdd","html","index","cached","eligible","crossedThreshold","activeCandidate","activeFeedbackCandidateKey","hasFeedbackForActiveCandidate","suggestionBaseHtml","activeCandidateHtml","canRegenerate","shouldShowSuggestionSession","isPrevSuggestionDisabled","isNextSuggestionDisabled","node","executeAIAction","regenerateExisting","instructionOverride","toneOverrideId","actionVariant","AIActionVariant","minCharsForAction","baseConfig","config","selectedToneId","selectedTone","tone","instructionForPrompt","prompt","buildActionPrompt","result","requestAISuggestion","candidate","next","handleAcceptSuggestion","inInitialAiPhase","tagPayload","computeAiTagOnAccept","handleRejectSuggestion","handleFeedback","rating","aiHeaderActions","actionConfig","toneId","useImperativeHandle","nextError","OuterContainer","jsxs","EditorFooterRow","jsx","EditorFooterTitle","TitleSmall","EditorFooterRight","Fragment","InfoIcon","BodyCaption","Container","idx","ChevronLeftIcon","ChevronRightIcon","Tooltip","ThumbsUpIcon","ThumbsDownIcon","RewindIcon","CrossIcon","CheckIcon","TextSpace","pastedText","el","base","caret","ta","EditIcon","instructionToApply","WhatsAppTextEditorHeader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WhatsAppTextEditor.js","sources":["../../../../src/components/WhatsAppTextEditor/WhatsAppTextEditor.tsx"],"sourcesContent":["import CheckIcon from '@src/assets/icons/check.svg';\nimport ChevronLeftIcon from '@src/assets/icons/chevronLeft.svg';\nimport ChevronRightIcon from '@src/assets/icons/chevronRight.svg';\nimport CrossIcon from '@src/assets/icons/cross.svg';\nimport EditIcon from '@src/assets/icons/edit.svg';\nimport InfoIcon from '@src/assets/icons/info.svg';\nimport RewindIcon from '@src/assets/icons/rewind.svg';\nimport ThumbsDownIcon from '@src/assets/icons/thumb-down-line.svg';\nimport ThumbsUpIcon from '@src/assets/icons/thumb-up-line.svg';\nimport { BaseWhatsappContentLangHelper } from '@src/helpers/BaseWhatsappContentLang.helper';\nimport { stripHtmlTags } from '@src/helpers/sanitize';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport styled, { keyframes } from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\nimport type { ApiRequestExecutor } from '../bik-chatbot/types';\nimport type { APIAdapter } from '../bik-chatbot/types/ai';\nimport { Tooltip } from '../tooltips/Tooltip';\nimport { BodyCaption, TitleSmall } from '../TypographyStyle';\nimport {\n\tAIActionPromptConfig,\n\tAIActionPromptRegistry,\n\tDEFAULT_AI_ACTION_MIN_CHARS,\n\tDEFAULT_INSTRUCTION_SUGGESTIONS,\n\tresolveActionPrompts,\n\tTemplateType,\n} from './ai/actionRegistry';\nimport {\n\tAITagPayload,\n\tcomputeAiTagOnAccept,\n\tcomputeAiTagOnPostEdit,\n} from './ai/aiTag';\nimport { buildActionPrompt, requestAISuggestion } from './ai/api';\nimport { AIActionToneOption } from './AIRephraseButton';\nimport {\n\tContainer,\n\tEditorFooterRight,\n\tEditorFooterRow,\n\tEditorFooterTitle,\n\tOuterContainer,\n\tTextSpace,\n} from './CustomEditor.styled';\nimport {\n\tAIActionVariant,\n\tAIEditorActionType,\n\tAIEditorActionTypes,\n\tAIHeaderAction,\n\tEditorActionTypes,\n\tWhatsAppEditorRightSlotProps,\n\tWhatsAppTextEditorHeader,\n} from './WhatsAppTextEditorHeader';\n\nconst LIMIT_REACHED = 'Character limit reached';\nconst REPHRASE_IDLE_MS = 3000;\nconst MAX_REPHRASE_HIGHLIGHTS = 5;\nconst MAX_SUGGESTIONS = 3;\nconst LARGE_INPUT_THRESHOLD = 1200;\nconst AI_TAG_RECOMPUTE_IDLE_MS = 1000;\nconst UTILITY_REPHRASE_PROMPT =\n\t'Rephrase this WhatsApp utility template to improve clarity and readability while preserving variables, intent, and compliance.';\n\nconst skeletonPulse = keyframes`\n\t0% { opacity: 0.55; }\n\t50% { opacity: 1; }\n\t100% { opacity: 0.55; }\n`;\n\nconst EditorSkeletonContainer = styled.div`\n\tpadding: 14px 12px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tmin-height: 150px;\n`;\n\nconst EditorSkeletonLine = styled.div<{ width: string }>`\n\theight: 16px;\n\tborder-radius: 6px;\n\twidth: ${(props) => props.width};\n\tbackground: #ececef;\n\tanimation: ${skeletonPulse} 1.1s ease-in-out infinite;\n`;\n\nconst SuggestionSessionContainer = styled.div`\n\tpadding: 12px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmax-height: 260px;\n\toverflow-y: scroll;\n\tscrollbar-width: thin;\n\tscrollbar-color: #c8c8cf transparent;\n\t::-webkit-scrollbar {\n\t\twidth: 8px;\n\t}\n\t::-webkit-scrollbar-thumb {\n\t\tbackground: #c8c8cf;\n\t\tborder-radius: 8px;\n\t}\n\t::-webkit-scrollbar-track {\n\t\tbackground: transparent;\n\t}\n`;\n\nconst SuggestionBaselineText = styled.div`\n\ttext-decoration: line-through;\n\tcolor: ${COLORS.content.secondary};\n`;\n\nconst SuggestionCandidateText = styled.div`\n\tcolor: ${COLORS.content.primary};\n`;\n\nconst SuggestionCandidateSkeleton = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\twidth: 100%;\n\tmin-height: 40px;\n`;\n\nconst SuggestionControlsRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n`;\n\nconst SuggestionCounter = styled.span`\n\tcolor: ${COLORS.content.primary};\n\tfont-size: 14px;\n`;\n\nconst SuggestionIconButton = styled.button`\n\tborder: 0;\n\tbackground: transparent;\n\tpadding: 6px;\n\tborder-radius: 6px;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\tcolor: ${COLORS.content.primary};\n\ttransition: background-color 0.12s ease;\n\t:not(:disabled):hover {\n\t\tbackground-color: ${COLORS.surface.hovered};\n\t}\n\t:disabled {\n\t\topacity: 0.35;\n\t\tcursor: not-allowed;\n\t}\n`;\n\n/** Regenerate stays full opacity while disabled so the loading shimmer stays visible (same pulse as editor skeleton). */\nconst SuggestionRegenerateButton = styled(SuggestionIconButton)`\n\t:disabled {\n\t\topacity: 1;\n\t\tcursor: wait;\n\t}\n`;\n\nconst RegenerateIconShimmer = styled.div`\n\twidth: 14px;\n\theight: 14px;\n\tborder-radius: 4px;\n\tbackground: #ececef;\n\tflex-shrink: 0;\n\tanimation: ${skeletonPulse} 1.1s ease-in-out infinite;\n`;\n\n/** Same bottom toolbar slot as `WhatsAppTextEditorHeader` — replaces the full icon/AI panel while open. */\nconst InstructionContainer = styled.div`\n\tbackground: ${COLORS.surface.standard};\n\tdisplay: flex;\n\tflex-direction: column;\n\tpadding: 8px 12px;\n\tgap: 10px;\n\tborder-radius: 0 0 4px 4px;\n\tposition: relative;\n`;\n\nconst InstructionInputRow = styled.div`\n\tborder: 1px solid #f5a4c0;\n\tborder-radius: 10px;\n\tpadding: 8px 10px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tbackground: ${COLORS.surface.standard};\n`;\n\nconst InstructionInput = styled.input`\n\tflex: 1;\n\tmin-width: 0;\n\tborder: 0;\n\toutline: none;\n\tfont-size: 14px;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.primary};\n`;\n\nconst InstructionActions = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n`;\n\nconst InstructionCancel = styled.button`\n\tborder: 0;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.secondary};\n\tfont-size: 14px;\n\tfont-weight: 500;\n\tpadding: 0;\n\tcursor: pointer;\n`;\n\nconst InstructionImprove = styled.button`\n\tborder: 1px solid #5d3a72;\n\tcolor: #5d3a72;\n\tbackground: ${COLORS.surface.standard};\n\tborder-radius: 8px;\n\tpadding: 8px 14px;\n\tfont-size: 14px;\n\tline-height: 1.1;\n\tfont-weight: 600;\n\tcursor: pointer;\n`;\n\nconst InstructionSuggestionList = styled.div`\n\tmargin-top: 4px;\n\tborder-radius: 12px;\n\twidth: 331px;\n\tbackground: ${COLORS.surface.standard};\n\tbox-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);\n\toverflow: hidden;\n\tpadding: 4px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n`;\n\nconst InstructionSuggestionButton = styled.button<{ selected?: boolean }>`\n\twidth: 100%;\n\tborder: 0;\n\tborder-radius: 8px;\n\tbackground: ${(props) => (props.selected ? '#e5f3e8' : 'transparent')};\n\tcolor: ${(props) => (props.selected ? '#1e6b34' : COLORS.content.primary)};\n\ttext-align: left;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tline-height: 1.2;\n\tcursor: pointer;\n\t:hover {\n\t\tbackground: ${(props) =>\n\t\t\tprops.selected ? '#d9e8db' : COLORS.surface.subdued};\n\t}\n`;\n\ntype AIEventName =\n\t| 'ai_action_triggered'\n\t| 'ai_feedback_submitted'\n\t| 'ai_suggestion_accepted'\n\t| 'ai_suggestion_discarded'\n\t| 'ai_suggestion_edited'\n\t| 'ai_instruction_used';\n\nenum AIFeedbackRating {\n\tLIKE = 'like',\n\tDISLIKE = 'dislike',\n}\n\ntype AIEventPayload = {\n\taction_type: AIEditorActionType;\n\ttemplate_id?: string | number;\n\ttemplate_category?: TemplateType;\n\trating?: AIFeedbackRating;\n\tcandidate_index?: number;\n\tinstruction_text?: string;\n};\n\ntype AIActionRequestPayload = {\n\tactionType: AIEditorActionType;\n\tactionVariant?: AIActionVariant;\n\tcurrentText: string;\n\ttemplateType: TemplateType;\n\ttoneId?: string;\n\ttoneLabel?: string;\n\tinstructionText?: string;\n\tprompt: string;\n};\n\ntype AIActionPromptBuildPayload = {\n\tactionType: AIEditorActionType;\n\tactionVariant?: AIActionVariant;\n\tcurrentText: string;\n\ttemplateType: TemplateType;\n\tconfig: AIActionPromptConfig;\n\ttoneId?: string;\n\ttoneLabel?: string;\n\tinstructionText?: string;\n};\n\nexport type CustomEditorProps =\n\tReact.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n\t\tonChange?: (text: string, html: string) => void;\n\t\ttext?: string;\n\t\tRightComponent?: React.ComponentType<WhatsAppEditorRightSlotProps>;\n\t\terror?: string;\n\t\tlimit?: number;\n\t\trows?: number;\n\t\tactions?: EditorActionTypes[];\n\n\t\t/**\n\t\t * Calls only for editor only error, not for errors coming from outside\n\t\t */\n\t\tonError?: (err: string) => void;\n\n\t\tonClickVariable?: (variable: string) => void;\n\t\teditorInstanceKey?: string;\n\t\teditorSessionId?: string;\n\t\ttemplateType?: TemplateType;\n\t\ttemplateId?: string | number;\n\t\trequestExecutor?: ApiRequestExecutor;\n\t\tbaseUrl?: string;\n\t\tendpointPath?: string;\n\t\tuseCase?: string;\n\t\tstoreId?: string;\n\t\tapiAdapter?: APIAdapter;\n\t\tconversationId?: string;\n\t\tsystemId?: string;\n\t\tintent?: string;\n\t\tenabledAIActions?: AIEditorActionType[];\n\t\tdisableBuiltInAIActions?: boolean;\n\t\tpromptOverrides?: AIActionPromptRegistry;\n\t\trephraseTones?: AIActionToneOption[];\n\t\taiActionMinChars?: Partial<Record<AIEditorActionType, number>>;\n\t\tinstructionSuggestions?: string[];\n\t\tonAnalyticsEvent?: (name: AIEventName, payload: AIEventPayload) => void;\n\t\t/**\n\t\t * Fires on AI-tag computations:\n\t\t * - `source: \"accept\"` after accepting a suggestion (addition check: >=50% => true)\n\t\t * - `source: \"post_edit_debounce\"` after edit idle/blur (retention check: <50% => true)\n\t\t * Persist `payload.isAiTagged` (or full payload) in host state and send on save.\n\t\t */\n\t\tonAITagComputed?: (payload: AITagPayload) => void;\n\t\t/**\n\t\t * When true, the editor body was loaded as fully AI-generated (prefill).\n\t\t * The first accepted suggestion will set `initialAiPrefillPhase` on the tag payload;\n\t\t * after that, only baseline vs accepted comparison applies.\n\t\t */\n\t\tprefillWasAiGenerated?: boolean;\n\t\t/**\n\t\t * Optional label above the editor (e.g. section title from the host).\n\t\t * When omitted, the left side of that top row is empty; limit/error stay on the right.\n\t\t */\n\t\teditorHeader?: React.ReactNode;\n\t\tonAIToneSelect?: (actionType: AIEditorActionType, toneId: string) => void;\n\t\tonAIActionRequest?: (\n\t\t\tpayload: AIActionRequestPayload,\n\t\t) => Promise<string | { body?: string }>;\n\t\tonBuildAIPrompt?: (payload: AIActionPromptBuildPayload) => string;\n\t\tonBlur?: React.FocusEventHandler<HTMLTextAreaElement>;\n\t};\nexport type CustomEditorRef = {\n\taddTextOrWrap: (textToAdd: string) => {\n\t\ttext: string;\n\t\thtml: string;\n\t};\n\taddText: (textToAdd: string) => {\n\t\ttext: string;\n\t\thtml: string;\n\t};\n\tget: () => string;\n\tsetCaretPosition(caretPos: number): void;\n};\n\nconst baseWhatsappContentLang = new BaseWhatsappContentLangHelper();\n\nconst WildCardMap: { [key in EditorActionTypes]?: string } = {\n\t[EditorActionTypes.BOLD]: '*',\n\t[EditorActionTypes.ITALIC]: '_',\n\t[EditorActionTypes.STRIKETHROUGH]: '~',\n};\n\nfunction getHighlightStorageKey(editorInstanceKey?: string) {\n\treturn `whatsapp-editor-rephrase-highlight-${editorInstanceKey || 'default'}`;\n}\n\nexport const WhatsAppTextEditor = React.forwardRef<\n\tCustomEditorRef,\n\tCustomEditorProps\n>(\n\t(\n\t\t{\n\t\t\tonChange,\n\t\t\tonClickVariable,\n\t\t\ttext: inputValue,\n\t\t\tRightComponent,\n\t\t\terror,\n\t\t\tlimit,\n\t\t\tonError,\n\t\t\trows,\n\t\t\tactions,\n\t\t\teditorInstanceKey,\n\t\t\teditorSessionId,\n\t\t\ttemplateType = 'marketing',\n\t\t\ttemplateId,\n\t\t\trequestExecutor,\n\t\t\tbaseUrl,\n\t\t\tendpointPath,\n\t\t\tuseCase,\n\t\t\tstoreId,\n\t\t\tapiAdapter,\n\t\t\tconversationId = 'whatsapp-template-editor',\n\t\t\tsystemId = 'whatsapp-writer',\n\t\t\tintent = 'default',\n\t\t\tenabledAIActions = [\n\t\t\t\tAIEditorActionTypes.REPHRASE,\n\t\t\t\tAIEditorActionTypes.SHORTEN,\n\t\t\t\tAIEditorActionTypes.EXPAND,\n\t\t\t\tAIEditorActionTypes.EMOJIFY,\n\t\t\t],\n\t\t\tdisableBuiltInAIActions = false,\n\t\t\tpromptOverrides,\n\t\t\trephraseTones,\n\t\t\taiActionMinChars,\n\t\t\tinstructionSuggestions = DEFAULT_INSTRUCTION_SUGGESTIONS,\n\t\t\tonAnalyticsEvent,\n\t\t\tonAITagComputed,\n\t\t\tprefillWasAiGenerated = false,\n\t\t\teditorHeader,\n\t\t\tonAIToneSelect,\n\t\t\tonAIActionRequest,\n\t\t\tonBuildAIPrompt,\n\t\t\tonBlur: textAreaOnBlur,\n\t\t\t...textAreaProps\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst textSpaceRef = useRef<HTMLTextAreaElement>(null);\n\t\tconst [currentText, setCurrentText] = useState(inputValue || '');\n\t\tconst [isRephraseHighlighted, setIsRephraseHighlighted] = useState(false);\n\t\tconst [rephraseHighlightCount, setRephraseHighlightCount] = useState(0);\n\t\tconst [isGenerating, setIsGenerating] = useState(false);\n\t\tconst [isInstructionInputVisible, setIsInstructionInputVisible] =\n\t\t\tuseState(false);\n\t\tconst [instructionText, setInstructionText] = useState('');\n\t\tconst [toneByAction, setToneByAction] = useState<\n\t\t\tPartial<Record<AIEditorActionType, string>>\n\t\t>({});\n\t\tconst [suggestionBaseText, setSuggestionBaseText] = useState<string | null>(\n\t\t\tnull,\n\t\t);\n\t\tconst [suggestionCandidates, setSuggestionCandidates] = useState<string[]>(\n\t\t\t[],\n\t\t);\n\t\tconst [suggestionIndex, setSuggestionIndex] = useState(0);\n\t\tconst [suggestionActionType, setSuggestionActionType] =\n\t\t\tuseState<AIEditorActionType | null>(null);\n\t\tconst suggestionScrollRef = useRef<HTMLDivElement | null>(null);\n\t\tconst rephraseIdleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\t\tconst highlightResetRef = useRef<ReturnType<typeof setTimeout> | null>(\n\t\t\tnull,\n\t\t);\n\t\tconst aiTagRecomputeRef = useRef<ReturnType<typeof setTimeout> | null>(\n\t\t\tnull,\n\t\t);\n\t\t/**\n\t\t * Prior eligibility for rephrase nudge (null = not initialized).\n\t\t * Matches the chip: non-empty trim and length ≥ min — same as `aiHeaderActions` disabled rules.\n\t\t */\n\t\tconst prevRephraseEligibleRef = useRef<boolean | null>(null);\n\t\tconst deferredHtmlRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\t\tconst lastEmittedEditorErrorRef = useRef<string | null>(null);\n\t\t/** First accept after full-AI prefill (`prefillWasAiGenerated`); cleared after one accept. */\n\t\tconst initialAiPrefillPhaseRef = useRef(!!prefillWasAiGenerated);\n\t\tconst acceptedSuggestionStateRef = useRef<{\n\t\t\tacceptedText: string;\n\t\t\tbaselineText: string;\n\t\t\tactionType: AIEditorActionType;\n\t\t\teditedEventEmitted: boolean;\n\t\t} | null>(null);\n\t\t/** Original prefill body for AI tag recompute; seeded once, never the live `currentText` fallback. */\n\t\tconst prefillBaselineTextRef = useRef('');\n\t\tconst prefillBaselineCapturedRef = useRef(false);\n\t\tconst [feedbackVotesByCandidate, setFeedbackVotesByCandidate] = useState<\n\t\t\tPartial<Record<string, AIFeedbackRating>>\n\t\t>({});\n\t\tconst mountSessionIdRef = useRef(\n\t\t\t`mount-${Date.now().toString(36)}-${Math.random()\n\t\t\t\t.toString(36)\n\t\t\t\t.slice(2, 8)}`,\n\t\t);\n\t\tconst highlightStorageKey = useMemo(() => {\n\t\t\treturn getHighlightStorageKey(\n\t\t\t\t`${editorInstanceKey || 'default'}-${\n\t\t\t\t\teditorSessionId || mountSessionIdRef.current\n\t\t\t\t}`,\n\t\t\t);\n\t\t}, [editorInstanceKey, editorSessionId]);\n\n\t\tuseEffect(() => {\n\t\t\tinitialAiPrefillPhaseRef.current = !!prefillWasAiGenerated;\n\t\t}, [prefillWasAiGenerated, editorInstanceKey]);\n\n\t\tuseEffect(() => {\n\t\t\tprefillBaselineCapturedRef.current = false;\n\t\t\tprefillBaselineTextRef.current = '';\n\t\t}, [editorInstanceKey, editorSessionId]);\n\n\t\tuseEffect(() => {\n\t\t\tif (!prefillWasAiGenerated) {\n\t\t\t\tprefillBaselineCapturedRef.current = false;\n\t\t\t\tprefillBaselineTextRef.current = '';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (prefillBaselineCapturedRef.current) return;\n\t\t\tconst seed = inputValue ?? '';\n\t\t\tif (seed.length > 0) {\n\t\t\t\tprefillBaselineTextRef.current = seed;\n\t\t\t\tprefillBaselineCapturedRef.current = true;\n\t\t\t}\n\t\t}, [prefillWasAiGenerated, inputValue, editorInstanceKey, editorSessionId]);\n\n\t\tconst activeActionPrompts = useMemo(() => {\n\t\t\treturn resolveActionPrompts(templateType, promptOverrides, rephraseTones);\n\t\t}, [promptOverrides, rephraseTones, templateType]);\n\n\t\tconst filteredInstructionSuggestions = useMemo(() => {\n\t\t\tconst query = instructionText.trim().toLowerCase();\n\t\t\tif (!query) return [];\n\t\t\treturn instructionSuggestions.filter((suggestion) =>\n\t\t\t\tsuggestion.toLowerCase().includes(query),\n\t\t\t);\n\t\t}, [instructionSuggestions, instructionText]);\n\n\t\tconst minCharsByAction = useMemo(() => {\n\t\t\treturn {\n\t\t\t\t...DEFAULT_AI_ACTION_MIN_CHARS,\n\t\t\t\t...(aiActionMinChars || {}),\n\t\t\t};\n\t\t}, [aiActionMinChars]);\n\n\t\tconst rephraseMinChars =\n\t\t\tminCharsByAction[AIEditorActionTypes.REPHRASE] ||\n\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[AIEditorActionTypes.REPHRASE];\n\n\t\tconst anonymizeInstructionText = useCallback((value: string) => {\n\t\t\tconst normalized = value.trim().replace(/\\s+/g, ' ');\n\t\t\tif (!normalized) return '';\n\t\t\tconst words = normalized.split(' ').length;\n\t\t\treturn `[anonymized:length_${normalized.length}:words_${words}]`;\n\t\t}, []);\n\n\t\tconst emitAIEvent = useCallback(\n\t\t\t(name: AIEventName, payload: AIEventPayload) => {\n\t\t\t\tonAnalyticsEvent?.(name, payload);\n\t\t\t},\n\t\t\t[onAnalyticsEvent],\n\t\t);\n\n\t\tconst setEditorText = useCallback((nextText: string) => {\n\t\t\tsetCurrentText((prev) => (prev === nextText ? prev : nextText));\n\t\t}, []);\n\n\t\tconst emitChangeWithGuard = useCallback(\n\t\t\t(nextText: string) => {\n\t\t\t\tif (deferredHtmlRef.current) {\n\t\t\t\t\tclearTimeout(deferredHtmlRef.current);\n\t\t\t\t}\n\t\t\t\tif (nextText.length > LARGE_INPUT_THRESHOLD) {\n\t\t\t\t\tonChange?.(nextText, nextText);\n\t\t\t\t\tdeferredHtmlRef.current = setTimeout(() => {\n\t\t\t\t\t\tonChange?.(nextText, baseWhatsappContentLang.getHTML(nextText));\n\t\t\t\t\t}, 16);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonChange?.(nextText, baseWhatsappContentLang.getHTML(nextText));\n\t\t\t},\n\t\t\t[onChange],\n\t\t);\n\n\t\tconst emitPostEditAiTagRecompute = useCallback(\n\t\t\t(nextText: string) => {\n\t\t\t\tconst latest = acceptedSuggestionStateRef.current;\n\t\t\t\tconst latestBaseline =\n\t\t\t\t\tlatest?.acceptedText ||\n\t\t\t\t\t(prefillWasAiGenerated ? prefillBaselineTextRef.current : '');\n\t\t\t\tif (!latestBaseline) return;\n\t\t\t\tif (nextText === latestBaseline) return;\n\t\t\t\tconst recomputePayload = computeAiTagOnPostEdit({\n\t\t\t\t\tacceptedAiText: latestBaseline,\n\t\t\t\t\tcurrentEditedText: nextText,\n\t\t\t\t});\n\t\t\t\tonAITagComputed?.({\n\t\t\t\t\t...recomputePayload,\n\t\t\t\t\tsource: 'post_edit_debounce',\n\t\t\t\t});\n\t\t\t},\n\t\t\t[onAITagComputed, prefillWasAiGenerated],\n\t\t);\n\n\t\tconst clearSuggestionSession = useCallback(() => {\n\t\t\tsetSuggestionBaseText(null);\n\t\t\tsetSuggestionCandidates([]);\n\t\t\tsetSuggestionIndex(0);\n\t\t\tsetSuggestionActionType(null);\n\t\t\tsetFeedbackVotesByCandidate({});\n\t\t}, []);\n\n\t\tconst triggerRephraseHighlight = useCallback(() => {\n\t\t\tif (isGenerating) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!!suggestionBaseText && suggestionCandidates.length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (rephraseHighlightCount >= MAX_REPHRASE_HIGHLIGHTS) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextCount = rephraseHighlightCount + 1;\n\t\t\tsetRephraseHighlightCount(nextCount);\n\t\t\tif (typeof window !== 'undefined' && editorInstanceKey) {\n\t\t\t\tsessionStorage.setItem(highlightStorageKey, String(nextCount));\n\t\t\t}\n\t\t\tsetIsRephraseHighlighted(true);\n\t\t\tif (highlightResetRef.current) {\n\t\t\t\tclearTimeout(highlightResetRef.current);\n\t\t\t}\n\t\t\thighlightResetRef.current = setTimeout(() => {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t}, 1200);\n\t\t}, [\n\t\t\teditorInstanceKey,\n\t\t\thighlightStorageKey,\n\t\t\tisGenerating,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionCandidates,\n\t\t\trephraseHighlightCount,\n\t\t]);\n\n\t\tconst triggerRephraseHighlightRef = useRef(triggerRephraseHighlight);\n\t\ttriggerRephraseHighlightRef.current = triggerRephraseHighlight;\n\n\t\tfunction handleOnChange(e: React.ChangeEvent<HTMLTextAreaElement>) {\n\t\t\tconst text = stripHtmlTags(e.target.value);\n\t\t\tconst acceptedSuggestion = acceptedSuggestionStateRef.current;\n\t\t\tif (\n\t\t\t\tacceptedSuggestion &&\n\t\t\t\t!acceptedSuggestion.editedEventEmitted &&\n\t\t\t\ttext !== acceptedSuggestion.acceptedText\n\t\t\t) {\n\t\t\t\tacceptedSuggestionStateRef.current = {\n\t\t\t\t\t...acceptedSuggestion,\n\t\t\t\t\teditedEventEmitted: true,\n\t\t\t\t};\n\t\t\t\temitAIEvent('ai_suggestion_edited', {\n\t\t\t\t\taction_type: acceptedSuggestion.actionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (aiTagRecomputeRef.current) {\n\t\t\t\tclearTimeout(aiTagRecomputeRef.current);\n\t\t\t\taiTagRecomputeRef.current = null;\n\t\t\t}\n\t\t\tconst baselineAiTextForRecompute =\n\t\t\t\tacceptedSuggestion?.acceptedText ||\n\t\t\t\t(prefillWasAiGenerated ? prefillBaselineTextRef.current : '');\n\t\t\tif (baselineAiTextForRecompute && text !== baselineAiTextForRecompute) {\n\t\t\t\taiTagRecomputeRef.current = setTimeout(() => {\n\t\t\t\t\temitPostEditAiTagRecompute(text);\n\t\t\t\t}, AI_TAG_RECOMPUTE_IDLE_MS);\n\t\t\t}\n\t\t\tsetEditorText(text);\n\t\t\temitChangeWithGuard(text);\n\t\t}\n\n\t\tfunction setCaretPosition(caretPos: number) {\n\t\t\tconst elem = textSpaceRef?.current;\n\n\t\t\tif (elem != null) {\n\t\t\t\tif (elem.selectionStart) {\n\t\t\t\t\telem.focus();\n\t\t\t\t\telem.selectionEnd = caretPos;\n\t\t\t\t} else elem.focus();\n\t\t\t}\n\t\t}\n\n\t\tfunction onActionSelect(actionType: EditorActionTypes) {\n\t\t\tconst wildCard = WildCardMap[actionType];\n\t\t\tif (wildCard && textSpaceRef.current) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\n\t\t\t\tif (start === end) {\n\t\t\t\t\tconst { text } = insertTextAtIndex(wildCard, start);\n\t\t\t\t\tsetCaretPosition(start + 1);\n\t\t\t\t\temitChangeWithGuard(text);\n\t\t\t\t} else {\n\t\t\t\t\tconst { text } = addTextOrWrap(wildCard);\n\t\t\t\t\temitChangeWithGuard(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction onEmojiAddition(emoji: string) {\n\t\t\tconst { text } = addText(emoji);\n\t\t\temitChangeWithGuard(text);\n\t\t}\n\n\t\tfunction addTextOrWrap(textToAdd?: string) {\n\t\t\tlet text = textSpaceRef.current?.value ?? '';\n\n\t\t\tif (textSpaceRef.current && textToAdd) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\n\t\t\t\tconst wildCard = textToAdd;\n\t\t\t\tif (start === end) {\n\t\t\t\t\t/** nothing is selected */\n\t\t\t\t\t/** so append the wildcard at the end */\n\n\t\t\t\t\treturn addText(wildCard);\n\t\t\t\t} else {\n\t\t\t\t\ttext = baseWhatsappContentLang.wrappWildcard(\n\t\t\t\t\t\tstart,\n\t\t\t\t\t\tend,\n\t\t\t\t\t\twildCard,\n\t\t\t\t\t\ttext!,\n\t\t\t\t\t);\n\t\t\t\t\tconst html = baseWhatsappContentLang.getHTML(text);\n\t\t\t\t\tsetEditorText(text);\n\t\t\t\t\treturn { text, html };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { text: text!, html: text! };\n\t\t}\n\n\t\tfunction addText(textToAdd: string) {\n\t\t\tconst text = textSpaceRef.current?.value ?? '';\n\n\t\t\tif (textSpaceRef.current && textToAdd) {\n\t\t\t\tconst start = textSpaceRef.current.selectionStart;\n\t\t\t\tconst end = textSpaceRef.current.selectionEnd;\n\t\t\t\tif (start === end) {\n\t\t\t\t\treturn insertTextAtIndex(textToAdd, start);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { text: text!, html: text! };\n\t\t}\n\n\t\tfunction insertTextAtIndex(textToAdd: string, index: number) {\n\t\t\tlet text = textSpaceRef.current?.value ?? '';\n\n\t\t\ttext = text.slice(0, index) + textToAdd + text.slice(index);\n\t\t\tconst html = baseWhatsappContentLang.getHTML(text);\n\t\t\tsetEditorText(text);\n\t\t\treturn { text, html };\n\t\t}\n\n\t\tuseEffect(() => {\n\t\t\tif (typeof window === 'undefined' || !editorInstanceKey) return;\n\t\t\tconst cached = Number(sessionStorage.getItem(highlightStorageKey) || '0');\n\t\t\tif (!Number.isNaN(cached)) {\n\t\t\t\tsetRephraseHighlightCount(cached);\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\tsessionStorage.removeItem(highlightStorageKey);\n\t\t\t};\n\t\t}, [editorInstanceKey, highlightStorageKey]);\n\n\t\tuseEffect(() => {\n\t\t\tif (isGenerating) {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!!suggestionBaseText && suggestionCandidates.length > 0) {\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst eligible =\n\t\t\t\t!!currentText.trim() && currentText.length >= rephraseMinChars;\n\n\t\t\tif (prevRephraseEligibleRef.current === null) {\n\t\t\t\tprevRephraseEligibleRef.current = eligible;\n\t\t\t\tif (eligible) {\n\t\t\t\t\trephraseIdleRef.current = setTimeout(() => {\n\t\t\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t\t\t}, REPHRASE_IDLE_MS);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!eligible) {\n\t\t\t\tprevRephraseEligibleRef.current = false;\n\t\t\t\tsetIsRephraseHighlighted(false);\n\t\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t\t\trephraseIdleRef.current = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst crossedThreshold = !prevRephraseEligibleRef.current && eligible;\n\t\t\tprevRephraseEligibleRef.current = true;\n\n\t\t\tif (crossedThreshold) {\n\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t}\n\n\t\t\tif (rephraseIdleRef.current) {\n\t\t\t\tclearTimeout(rephraseIdleRef.current);\n\t\t\t}\n\t\t\trephraseIdleRef.current = setTimeout(() => {\n\t\t\t\ttriggerRephraseHighlightRef.current();\n\t\t\t}, REPHRASE_IDLE_MS);\n\t\t}, [\n\t\t\tcurrentText,\n\t\t\tisGenerating,\n\t\t\trephraseMinChars,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionCandidates,\n\t\t]);\n\n\t\tuseEffect(() => {\n\t\t\treturn () => {\n\t\t\t\tif (rephraseIdleRef.current) clearTimeout(rephraseIdleRef.current);\n\t\t\t\tif (highlightResetRef.current) clearTimeout(highlightResetRef.current);\n\t\t\t\tif (deferredHtmlRef.current) clearTimeout(deferredHtmlRef.current);\n\t\t\t\tif (aiTagRecomputeRef.current) clearTimeout(aiTagRecomputeRef.current);\n\t\t\t};\n\t\t}, []);\n\n\t\tconst activeCandidate = suggestionCandidates[suggestionIndex] || '';\n\t\tconst activeFeedbackCandidateKey = useMemo(() => {\n\t\t\tif (!suggestionActionType || !activeCandidate) return null;\n\t\t\treturn `${suggestionActionType}-${suggestionIndex}-${activeCandidate}`;\n\t\t}, [activeCandidate, suggestionActionType, suggestionIndex]);\n\t\tconst hasFeedbackForActiveCandidate = !!(\n\t\t\tactiveFeedbackCandidateKey &&\n\t\t\tfeedbackVotesByCandidate[activeFeedbackCandidateKey]\n\t\t);\n\t\tconst suggestionBaseHtml = useMemo(\n\t\t\t() => baseWhatsappContentLang.getHTML(suggestionBaseText || ''),\n\t\t\t[suggestionBaseText],\n\t\t);\n\t\tconst activeCandidateHtml = useMemo(\n\t\t\t() => baseWhatsappContentLang.getHTML(activeCandidate),\n\t\t\t[activeCandidate],\n\t\t);\n\t\tconst canRegenerate = suggestionCandidates.length < MAX_SUGGESTIONS;\n\t\tconst shouldShowSuggestionSession =\n\t\t\t!!suggestionBaseText && suggestionCandidates.length > 0;\n\t\tconst isPrevSuggestionDisabled =\n\t\t\tsuggestionCandidates.length <= 1 || suggestionIndex <= 0;\n\t\tconst isNextSuggestionDisabled =\n\t\t\tsuggestionCandidates.length <= 1 ||\n\t\t\tsuggestionIndex >= suggestionCandidates.length - 1;\n\n\t\tuseEffect(() => {\n\t\t\tif (!shouldShowSuggestionSession) return;\n\t\t\tconst node = suggestionScrollRef.current;\n\t\t\tif (!node) return;\n\t\t\tnode.scrollTop = node.scrollHeight;\n\t\t}, [activeCandidate, shouldShowSuggestionSession, isGenerating]);\n\n\t\tconst executeAIAction = useCallback(\n\t\t\tasync (\n\t\t\t\tactionType: AIEditorActionType,\n\t\t\t\tregenerateExisting = false,\n\t\t\t\tinstructionOverride?: string,\n\t\t\t\ttoneOverrideId?: string,\n\t\t\t\tactionVariant: AIActionVariant = AIActionVariant.DEFAULT,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\t!onAIActionRequest &&\n\t\t\t\t\t!apiAdapter &&\n\t\t\t\t\t(!requestExecutor || !baseUrl)\n\t\t\t\t) {\n\t\t\t\t\tonError?.('AI configuration missing');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!currentText.trim()) return;\n\t\t\t\tconst minCharsForAction =\n\t\t\t\t\tminCharsByAction[actionType] ||\n\t\t\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[actionType] ||\n\t\t\t\t\t50;\n\t\t\t\tif (currentText.length < minCharsForAction) return;\n\t\t\t\tif (isGenerating) return;\n\t\t\t\tif (regenerateExisting && !canRegenerate) return;\n\n\t\t\t\tconst baseConfig = activeActionPrompts[actionType];\n\t\t\t\tconst config =\n\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\ttemplateType === 'utility' &&\n\t\t\t\t\tactionVariant === AIActionVariant.REPHRASE\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t...baseConfig,\n\t\t\t\t\t\t\t\tlabel: 'Rephrase',\n\t\t\t\t\t\t\t\tbasePrompt: UTILITY_REPHRASE_PROMPT,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: baseConfig;\n\t\t\t\t// Tone is sent only after explicit user selection (or explicit override),\n\t\t\t\t// not from default tone metadata.\n\t\t\t\tconst selectedToneId = toneOverrideId || toneByAction[actionType];\n\t\t\t\tconst selectedTone = config.tones?.find(\n\t\t\t\t\t(tone) => tone.id === selectedToneId,\n\t\t\t\t);\n\t\t\t\tconst instructionForPrompt =\n\t\t\t\t\tinstructionOverride !== undefined\n\t\t\t\t\t\t? instructionOverride\n\t\t\t\t\t\t: instructionText;\n\t\t\t\tconst prompt =\n\t\t\t\t\tonBuildAIPrompt?.({\n\t\t\t\t\t\tactionType,\n\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\ttemplateType,\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\ttoneId: selectedToneId,\n\t\t\t\t\t\ttoneLabel: selectedTone?.label,\n\t\t\t\t\t\tinstructionText: instructionForPrompt || undefined,\n\t\t\t\t\t}) ||\n\t\t\t\t\tbuildActionPrompt({\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\tselectedToneId,\n\t\t\t\t\t\tinstructionText: instructionForPrompt,\n\t\t\t\t\t});\n\n\t\t\t\tsetIsGenerating(true);\n\t\t\t\temitAIEvent('ai_action_triggered', {\n\t\t\t\t\taction_type: actionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\ttemplate_category: templateType,\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tconst result = onAIActionRequest\n\t\t\t\t\t\t? await onAIActionRequest({\n\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\tcurrentText,\n\t\t\t\t\t\t\t\ttemplateType,\n\t\t\t\t\t\t\t\ttoneId: selectedToneId,\n\t\t\t\t\t\t\t\ttoneLabel: selectedTone?.label,\n\t\t\t\t\t\t\t\tinstructionText: instructionForPrompt || undefined,\n\t\t\t\t\t\t\t\tprompt,\n\t\t\t\t\t\t })\n\t\t\t\t\t\t: await requestAISuggestion({\n\t\t\t\t\t\t\t\tapiAdapter,\n\t\t\t\t\t\t\t\trequestExecutor,\n\t\t\t\t\t\t\t\tbaseUrl,\n\t\t\t\t\t\t\t\tendpointPath,\n\t\t\t\t\t\t\t\tprompt,\n\t\t\t\t\t\t\t\tintent,\n\t\t\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\t\t\tsystemId,\n\t\t\t\t\t\t\t\tuseCase,\n\t\t\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\t });\n\t\t\t\t\tconst candidate =\n\t\t\t\t\t\ttypeof result === 'string'\n\t\t\t\t\t\t\t? result.trim()\n\t\t\t\t\t\t\t: (result?.body || '').trim();\n\t\t\t\t\tif (!candidate) return;\n\t\t\t\t\tif (!regenerateExisting) {\n\t\t\t\t\t\tsetSuggestionBaseText(currentText);\n\t\t\t\t\t\tsetSuggestionActionType(actionType);\n\t\t\t\t\t\tsetSuggestionCandidates([candidate]);\n\t\t\t\t\t\tsetSuggestionIndex(0);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tsetSuggestionCandidates((prev) => {\n\t\t\t\t\t\tconst next = [...prev, candidate].slice(0, MAX_SUGGESTIONS);\n\t\t\t\t\t\tsetSuggestionIndex(next.length - 1);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tonError?.('Failed to generate AI suggestion');\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsGenerating(false);\n\t\t\t\t}\n\t\t\t},\n\t\t\t[\n\t\t\t\trequestExecutor,\n\t\t\t\tbaseUrl,\n\t\t\t\tcurrentText,\n\t\t\t\tisGenerating,\n\t\t\t\tcanRegenerate,\n\t\t\t\tactiveActionPrompts,\n\t\t\t\ttoneByAction,\n\t\t\t\tinstructionText,\n\t\t\t\temitAIEvent,\n\t\t\t\ttemplateId,\n\t\t\t\tendpointPath,\n\t\t\t\tapiAdapter,\n\t\t\t\tintent,\n\t\t\t\tconversationId,\n\t\t\t\tsystemId,\n\t\t\t\tuseCase,\n\t\t\t\tstoreId,\n\t\t\t\ttemplateType,\n\t\t\t\tonError,\n\t\t\t\tminCharsByAction,\n\t\t\t\tonAIActionRequest,\n\t\t\t\tonBuildAIPrompt,\n\t\t\t],\n\t\t);\n\n\t\tconst handleAcceptSuggestion = useCallback(() => {\n\t\t\tif (!activeCandidate || !suggestionBaseText || !suggestionActionType)\n\t\t\t\treturn;\n\t\t\tsetEditorText(activeCandidate);\n\t\t\temitChangeWithGuard(activeCandidate);\n\t\t\temitAIEvent('ai_suggestion_accepted', {\n\t\t\t\taction_type: suggestionActionType,\n\t\t\t\ttemplate_id: templateId,\n\t\t\t});\n\t\t\tacceptedSuggestionStateRef.current = {\n\t\t\t\tacceptedText: activeCandidate,\n\t\t\t\tbaselineText: suggestionBaseText,\n\t\t\t\tactionType: suggestionActionType,\n\t\t\t\teditedEventEmitted: false,\n\t\t\t};\n\n\t\t\tconst inInitialAiPhase = initialAiPrefillPhaseRef.current;\n\t\t\tconst tagPayload = computeAiTagOnAccept({\n\t\t\t\tbaselineText: suggestionBaseText,\n\t\t\t\tacceptedText: activeCandidate,\n\t\t\t\tinitialAiPrefillPhase: inInitialAiPhase,\n\t\t\t});\n\t\t\tif (inInitialAiPhase) {\n\t\t\t\tinitialAiPrefillPhaseRef.current = false;\n\t\t\t}\n\t\t\tonAITagComputed?.({\n\t\t\t\t...tagPayload,\n\t\t\t\tsource: 'accept',\n\t\t\t});\n\t\t\tclearSuggestionSession();\n\t\t}, [\n\t\t\tactiveCandidate,\n\t\t\tsuggestionBaseText,\n\t\t\tsuggestionActionType,\n\t\t\tsetEditorText,\n\t\t\temitChangeWithGuard,\n\t\t\temitAIEvent,\n\t\t\ttemplateId,\n\t\t\tonAITagComputed,\n\t\t\tclearSuggestionSession,\n\t\t]);\n\n\t\tconst handleRejectSuggestion = useCallback(() => {\n\t\t\tif (!suggestionActionType) return;\n\t\t\temitAIEvent('ai_suggestion_discarded', {\n\t\t\t\taction_type: suggestionActionType,\n\t\t\t\ttemplate_id: templateId,\n\t\t\t});\n\t\t\tclearSuggestionSession();\n\t\t}, [clearSuggestionSession, emitAIEvent, suggestionActionType, templateId]);\n\n\t\tconst handleFeedback = useCallback(\n\t\t\t(rating: AIFeedbackRating) => {\n\t\t\t\tif (!suggestionActionType || !activeFeedbackCandidateKey) return;\n\t\t\t\tif (feedbackVotesByCandidate[activeFeedbackCandidateKey]) return;\n\t\t\t\tsetFeedbackVotesByCandidate((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\t[activeFeedbackCandidateKey]: rating,\n\t\t\t\t}));\n\t\t\t\temitAIEvent('ai_feedback_submitted', {\n\t\t\t\t\taction_type: suggestionActionType,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\trating,\n\t\t\t\t\tcandidate_index: suggestionIndex + 1,\n\t\t\t\t});\n\t\t\t},\n\t\t\t[\n\t\t\t\tactiveFeedbackCandidateKey,\n\t\t\t\temitAIEvent,\n\t\t\t\tfeedbackVotesByCandidate,\n\t\t\t\tsuggestionActionType,\n\t\t\t\tsuggestionIndex,\n\t\t\t\ttemplateId,\n\t\t\t],\n\t\t);\n\n\t\tconst aiHeaderActions: AIHeaderAction[] = useMemo(() => {\n\t\t\tif (disableBuiltInAIActions) return [];\n\t\t\treturn enabledAIActions.map((actionType) => {\n\t\t\t\tconst actionConfig = activeActionPrompts[actionType];\n\t\t\t\tconst toneId = toneByAction[actionType];\n\t\t\t\treturn {\n\t\t\t\t\ttype: actionType,\n\t\t\t\t\tlabel: actionConfig.label,\n\t\t\t\t\tisPrimary: actionType === AIEditorActionTypes.REPHRASE,\n\t\t\t\t\tloading: isGenerating && suggestionActionType === actionType,\n\t\t\t\t\thighlighted:\n\t\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\t\tisRephraseHighlighted,\n\t\t\t\t\tdisabled:\n\t\t\t\t\t\t!currentText.trim() ||\n\t\t\t\t\t\tcurrentText.length <\n\t\t\t\t\t\t\t(minCharsByAction[actionType] ||\n\t\t\t\t\t\t\t\tDEFAULT_AI_ACTION_MIN_CHARS[actionType] ||\n\t\t\t\t\t\t\t\t50) ||\n\t\t\t\t\t\tisGenerating ||\n\t\t\t\t\t\t(shouldShowSuggestionSession &&\n\t\t\t\t\t\t\tsuggestionActionType === actionType),\n\t\t\t\t\tshowToneDropdown:\n\t\t\t\t\t\tactionType === AIEditorActionTypes.REPHRASE &&\n\t\t\t\t\t\t!!actionConfig.tones?.length,\n\t\t\t\t\ttones: actionConfig.tones,\n\t\t\t\t\tselectedToneId: toneId,\n\t\t\t\t};\n\t\t\t});\n\t\t}, [\n\t\t\tenabledAIActions,\n\t\t\tdisableBuiltInAIActions,\n\t\t\tactiveActionPrompts,\n\t\t\ttoneByAction,\n\t\t\tisGenerating,\n\t\t\tsuggestionActionType,\n\t\t\tshouldShowSuggestionSession,\n\t\t\tisRephraseHighlighted,\n\t\t\tcurrentText,\n\t\t\tminCharsByAction,\n\t\t]);\n\n\t\tuseImperativeHandle(\n\t\t\tref,\n\t\t\t() => {\n\t\t\t\treturn {\n\t\t\t\t\taddTextOrWrap,\n\t\t\t\t\taddText,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn currentText;\n\t\t\t\t\t},\n\t\t\t\t\tsetCaretPosition,\n\t\t\t\t};\n\t\t\t},\n\t\t\t[addTextOrWrap, addText, currentText],\n\t\t);\n\n\t\tuseEffect(() => {\n\t\t\tif (inputValue === undefined) return;\n\t\t\tsetEditorText(inputValue || '');\n\t\t}, [inputValue, setEditorText]);\n\n\t\tuseEffect(() => {\n\t\t\tif (!limit || !onError) return;\n\t\t\tconst nextError =\n\t\t\t\tcurrentText.length > limit ? LIMIT_REACHED : error ?? '';\n\t\t\tif (lastEmittedEditorErrorRef.current === nextError) return;\n\t\t\tlastEmittedEditorErrorRef.current = nextError;\n\t\t\tonError(nextError);\n\t\t}, [currentText, error, limit, onError]);\n\n\t\treturn (\n\t\t\t<OuterContainer>\n\t\t\t\t<EditorFooterRow>\n\t\t\t\t\t<EditorFooterTitle>\n\t\t\t\t\t\t{editorHeader ? (\n\t\t\t\t\t\t\t<TitleSmall data-test=\"body-text-for-edit-template\">\n\t\t\t\t\t\t\t\t{editorHeader}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</EditorFooterTitle>\n\t\t\t\t\t<EditorFooterRight>\n\t\t\t\t\t\t{error && error !== LIMIT_REACHED ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<InfoIcon\n\t\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\t\tcolor={COLORS.content.negative}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{limit ? (\n\t\t\t\t\t\t\t<BodyCaption\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\t\terror === LIMIT_REACHED || currentText.length > limit\n\t\t\t\t\t\t\t\t\t\t\t? COLORS.content.negative\n\t\t\t\t\t\t\t\t\t\t\t: COLORS.content.secondary,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{currentText.length}/{limit}\n\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</EditorFooterRight>\n\t\t\t\t</EditorFooterRow>\n\t\t\t\t<Container isError={!!error}>\n\t\t\t\t\t{shouldShowSuggestionSession ? (\n\t\t\t\t\t\t<SuggestionSessionContainer ref={suggestionScrollRef}>\n\t\t\t\t\t\t\t<SuggestionBaselineText\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: suggestionBaseHtml }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{isGenerating ? (\n\t\t\t\t\t\t\t\t<SuggestionCandidateText aria-busy=\"true\">\n\t\t\t\t\t\t\t\t\t<SuggestionCandidateSkeleton>\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"96%\" />\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"84%\" />\n\t\t\t\t\t\t\t\t\t\t<EditorSkeletonLine width=\"68%\" />\n\t\t\t\t\t\t\t\t\t</SuggestionCandidateSkeleton>\n\t\t\t\t\t\t\t\t</SuggestionCandidateText>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<SuggestionCandidateText\n\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t__html: activeCandidateHtml,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<SuggestionControlsRow>\n\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\taria-label=\"Previous suggestion\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isPrevSuggestionDisabled}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tsetSuggestionIndex((idx) => Math.max(0, idx - 1))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ChevronLeftIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t<SuggestionCounter>\n\t\t\t\t\t\t\t\t\t{suggestionIndex + 1}/{suggestionCandidates.length}\n\t\t\t\t\t\t\t\t</SuggestionCounter>\n\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\taria-label=\"Next suggestion\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isNextSuggestionDisabled}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tsetSuggestionIndex((idx) =>\n\t\t\t\t\t\t\t\t\t\t\tMath.min(suggestionCandidates.length - 1, idx + 1),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ChevronRightIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Like\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Like suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdisabled={hasFeedbackForActiveCandidate}\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(AIFeedbackRating.LIKE)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ThumbsUpIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Dislike\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Dislike suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdisabled={hasFeedbackForActiveCandidate}\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(AIFeedbackRating.DISLIKE)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ThumbsDownIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t{canRegenerate ? (\n\t\t\t\t\t\t\t\t\t<Tooltip\n\t\t\t\t\t\t\t\t\t\tbody={isGenerating ? 'Regenerating…' : 'Regenerate'}\n\t\t\t\t\t\t\t\t\t\tplacement=\"top\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<SuggestionRegenerateButton\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Regenerate suggestion\"\n\t\t\t\t\t\t\t\t\t\t\taria-busy={isGenerating}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isGenerating}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (suggestionActionType) {\n\t\t\t\t\t\t\t\t\t\t\t\t\texecuteAIAction(suggestionActionType, true);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{isGenerating ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<RegenerateIconShimmer aria-hidden />\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<RewindIcon width={14} height={14} />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</SuggestionRegenerateButton>\n\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<Tooltip body=\"Discard\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Discard suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleRejectSuggestion}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CrossIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t<Tooltip body=\"Accept\" placement=\"top\">\n\t\t\t\t\t\t\t\t\t<SuggestionIconButton\n\t\t\t\t\t\t\t\t\t\taria-label=\"Accept suggestion\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleAcceptSuggestion}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CheckIcon\n\t\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</SuggestionIconButton>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t</SuggestionControlsRow>\n\t\t\t\t\t\t</SuggestionSessionContainer>\n\t\t\t\t\t) : isGenerating ? (\n\t\t\t\t\t\t<EditorSkeletonContainer>\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"96%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"92%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"88%\" />\n\t\t\t\t\t\t\t<EditorSkeletonLine width=\"54%\" />\n\t\t\t\t\t\t</EditorSkeletonContainer>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<TextSpace\n\t\t\t\t\t\t\tref={textSpaceRef}\n\t\t\t\t\t\t\t{...textAreaProps}\n\t\t\t\t\t\t\tvalue={currentText}\n\t\t\t\t\t\t\tonChange={handleOnChange}\n\t\t\t\t\t\t\tonBlur={(e) => {\n\t\t\t\t\t\t\t\tif (aiTagRecomputeRef.current) {\n\t\t\t\t\t\t\t\t\tclearTimeout(aiTagRecomputeRef.current);\n\t\t\t\t\t\t\t\t\taiTagRecomputeRef.current = null;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\temitPostEditAiTagRecompute(e.target.value);\n\t\t\t\t\t\t\t\ttextAreaOnBlur?.(e);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonPaste={(e) => {\n\t\t\t\t\t\t\t\tconst pastedText = e.clipboardData.getData('text');\n\t\t\t\t\t\t\t\tif (pastedText.length > LARGE_INPUT_THRESHOLD) {\n\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\tconst el = textSpaceRef.current;\n\t\t\t\t\t\t\t\t\tconst start = el?.selectionStart ?? 0;\n\t\t\t\t\t\t\t\t\tconst end = el?.selectionEnd ?? start;\n\t\t\t\t\t\t\t\t\t// Prefer live DOM value — `currentText` can lag the textarea for big pastes.\n\t\t\t\t\t\t\t\t\tconst base = el?.value ?? currentText;\n\t\t\t\t\t\t\t\t\tconst nextText =\n\t\t\t\t\t\t\t\t\t\tbase.slice(0, start) + pastedText + base.slice(end);\n\t\t\t\t\t\t\t\t\tsetEditorText(nextText);\n\t\t\t\t\t\t\t\t\temitChangeWithGuard(nextText);\n\t\t\t\t\t\t\t\t\tconst caret = start + pastedText.length;\n\t\t\t\t\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\t\t\t\t\tconst ta = textSpaceRef.current;\n\t\t\t\t\t\t\t\t\t\tif (!ta) return;\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tta.setSelectionRange(caret, caret);\n\t\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t\t// ignore invalid range in edge browsers\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\trows={rows}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{isInstructionInputVisible ? (\n\t\t\t\t\t\t<InstructionContainer>\n\t\t\t\t\t\t\t<InstructionInputRow>\n\t\t\t\t\t\t\t\t<EditIcon\n\t\t\t\t\t\t\t\t\twidth={18}\n\t\t\t\t\t\t\t\t\theight={18}\n\t\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<InstructionInput\n\t\t\t\t\t\t\t\t\tvalue={instructionText}\n\t\t\t\t\t\t\t\t\tplaceholder=\"Add specific instructions to refine your message\"\n\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\tsetInstructionText(stripHtmlTags(e.target.value))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<InstructionActions>\n\t\t\t\t\t\t\t\t\t<InstructionCancel\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetInstructionText('');\n\t\t\t\t\t\t\t\t\t\t\tsetIsInstructionInputVisible(false);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t</InstructionCancel>\n\t\t\t\t\t\t\t\t\t<InstructionImprove\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tconst instructionToApply = instructionText.trim();\n\t\t\t\t\t\t\t\t\t\t\tif (instructionToApply) {\n\t\t\t\t\t\t\t\t\t\t\t\temitAIEvent('ai_instruction_used', {\n\t\t\t\t\t\t\t\t\t\t\t\t\taction_type: AIEditorActionTypes.REPHRASE,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t\t\t\t\t\t\t\t\t\tinstruction_text:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tanonymizeInstructionText(instructionToApply),\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tsetIsInstructionInputVisible(false);\n\t\t\t\t\t\t\t\t\t\t\tsetInstructionText('');\n\t\t\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\t\t\tAIEditorActionTypes.REPHRASE,\n\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\tinstructionToApply,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tImprove\n\t\t\t\t\t\t\t\t\t</InstructionImprove>\n\t\t\t\t\t\t\t\t</InstructionActions>\n\t\t\t\t\t\t\t</InstructionInputRow>\n\t\t\t\t\t\t\t{instructionText.trim().length > 0 &&\n\t\t\t\t\t\t\tfilteredInstructionSuggestions.length > 0 ? (\n\t\t\t\t\t\t\t\t<InstructionSuggestionList>\n\t\t\t\t\t\t\t\t\t{filteredInstructionSuggestions.map((suggestion) => (\n\t\t\t\t\t\t\t\t\t\t<InstructionSuggestionButton\n\t\t\t\t\t\t\t\t\t\t\tkey={suggestion}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tselected={instructionText === suggestion}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setInstructionText(suggestion)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{suggestion}\n\t\t\t\t\t\t\t\t\t\t</InstructionSuggestionButton>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</InstructionSuggestionList>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</InstructionContainer>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<WhatsAppTextEditorHeader\n\t\t\t\t\t\t\tactions={actions}\n\t\t\t\t\t\t\tref={textSpaceRef}\n\t\t\t\t\t\t\tonActionSelect={onActionSelect}\n\t\t\t\t\t\t\tRightComponent={RightComponent}\n\t\t\t\t\t\t\trightActionsDisabled={shouldShowSuggestionSession || isGenerating}\n\t\t\t\t\t\t\tonEmojiClick={onEmojiAddition}\n\t\t\t\t\t\t\taiActions={aiHeaderActions}\n\t\t\t\t\t\t\tdisableAllActions={shouldShowSuggestionSession || isGenerating}\n\t\t\t\t\t\t\tinstructionActive={isInstructionInputVisible}\n\t\t\t\t\t\t\tonAIInstructionsClick={() => setIsInstructionInputVisible(true)}\n\t\t\t\t\t\t\tonAIToneChange={(actionType, toneId) => {\n\t\t\t\t\t\t\t\tsetToneByAction((prev) => ({ ...prev, [actionType]: toneId }));\n\t\t\t\t\t\t\t\tonAIToneSelect?.(actionType, toneId);\n\t\t\t\t\t\t\t\tif (actionType === AIEditorActionTypes.REPHRASE) {\n\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\ttoneId,\n\t\t\t\t\t\t\t\t\t\tAIActionVariant.DEFAULT,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonAIActionClick={(\n\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\tactionVariant = AIActionVariant.DEFAULT,\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\tif (isGenerating) return;\n\n\t\t\t\t\t\t\t\tif (shouldShowSuggestionSession) {\n\t\t\t\t\t\t\t\t\tif (suggestionActionType === actionType) {\n\t\t\t\t\t\t\t\t\t\t// Same action should not retrigger from chip;\n\t\t\t\t\t\t\t\t\t\t// regenerate is only via explicit regenerate control.\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// New action starts a fresh suggestion session.\n\t\t\t\t\t\t\t\t\tclearSuggestionSession();\n\t\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\texecuteAIAction(\n\t\t\t\t\t\t\t\t\tactionType,\n\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tactionVariant,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</Container>\n\t\t\t</OuterContainer>\n\t\t);\n\t},\n);\n\nWhatsAppTextEditor.displayName = 'WhatsAppTextEditor';\n\nexport type { AITagPayload } from './ai/aiTag';\nexport {\n\tAI_TAG_CHANGE_RATIO_THRESHOLD,\n\tcomputeAiTagOnAccept,\n\tlevenshteinDistance,\n} from './ai/aiTag';\n"],"names":["LIMIT_REACHED","REPHRASE_IDLE_MS","MAX_REPHRASE_HIGHLIGHTS","MAX_SUGGESTIONS","LARGE_INPUT_THRESHOLD","AI_TAG_RECOMPUTE_IDLE_MS","UTILITY_REPHRASE_PROMPT","skeletonPulse","keyframes","EditorSkeletonContainer","styled","EditorSkeletonLine","props","SuggestionSessionContainer","SuggestionBaselineText","COLORS","SuggestionCandidateText","SuggestionCandidateSkeleton","SuggestionControlsRow","SuggestionCounter","SuggestionIconButton","SuggestionRegenerateButton","RegenerateIconShimmer","InstructionContainer","InstructionInputRow","InstructionInput","InstructionActions","InstructionCancel","InstructionImprove","InstructionSuggestionList","InstructionSuggestionButton","baseWhatsappContentLang","BaseWhatsappContentLangHelper","WildCardMap","EditorActionTypes","getHighlightStorageKey","editorInstanceKey","WhatsAppTextEditor","React","onChange","onClickVariable","inputValue","RightComponent","error","limit","onError","rows","actions","editorSessionId","templateType","templateId","requestExecutor","baseUrl","endpointPath","useCase","storeId","apiAdapter","conversationId","systemId","intent","enabledAIActions","AIEditorActionTypes","disableBuiltInAIActions","promptOverrides","rephraseTones","aiActionMinChars","instructionSuggestions","DEFAULT_INSTRUCTION_SUGGESTIONS","onAnalyticsEvent","onAITagComputed","prefillWasAiGenerated","editorHeader","onAIToneSelect","onAIActionRequest","onBuildAIPrompt","textAreaOnBlur","textAreaProps","ref","textSpaceRef","useRef","currentText","setCurrentText","useState","isRephraseHighlighted","setIsRephraseHighlighted","rephraseHighlightCount","setRephraseHighlightCount","isGenerating","setIsGenerating","isInstructionInputVisible","setIsInstructionInputVisible","instructionText","setInstructionText","toneByAction","setToneByAction","suggestionBaseText","setSuggestionBaseText","suggestionCandidates","setSuggestionCandidates","suggestionIndex","setSuggestionIndex","suggestionActionType","setSuggestionActionType","suggestionScrollRef","rephraseIdleRef","highlightResetRef","aiTagRecomputeRef","prevRephraseEligibleRef","deferredHtmlRef","lastEmittedEditorErrorRef","initialAiPrefillPhaseRef","acceptedSuggestionStateRef","prefillBaselineTextRef","prefillBaselineCapturedRef","feedbackVotesByCandidate","setFeedbackVotesByCandidate","mountSessionIdRef","highlightStorageKey","useMemo","useEffect","seed","activeActionPrompts","resolveActionPrompts","filteredInstructionSuggestions","query","suggestion","minCharsByAction","DEFAULT_AI_ACTION_MIN_CHARS","rephraseMinChars","anonymizeInstructionText","useCallback","value","normalized","words","emitAIEvent","name","payload","setEditorText","nextText","prev","emitChangeWithGuard","emitPostEditAiTagRecompute","latestBaseline","recomputePayload","computeAiTagOnPostEdit","clearSuggestionSession","triggerRephraseHighlight","nextCount","triggerRephraseHighlightRef","handleOnChange","text","stripHtmlTags","acceptedSuggestion","baselineAiTextForRecompute","setCaretPosition","caretPos","elem","onActionSelect","actionType","wildCard","start","end","insertTextAtIndex","addTextOrWrap","onEmojiAddition","emoji","addText","textToAdd","html","index","cached","eligible","crossedThreshold","activeCandidate","activeFeedbackCandidateKey","hasFeedbackForActiveCandidate","suggestionBaseHtml","activeCandidateHtml","canRegenerate","shouldShowSuggestionSession","isPrevSuggestionDisabled","isNextSuggestionDisabled","node","executeAIAction","regenerateExisting","instructionOverride","toneOverrideId","actionVariant","AIActionVariant","minCharsForAction","baseConfig","config","selectedToneId","selectedTone","tone","instructionForPrompt","prompt","buildActionPrompt","result","requestAISuggestion","candidate","next","handleAcceptSuggestion","inInitialAiPhase","tagPayload","computeAiTagOnAccept","handleRejectSuggestion","handleFeedback","rating","aiHeaderActions","actionConfig","toneId","useImperativeHandle","nextError","OuterContainer","jsxs","EditorFooterRow","jsx","EditorFooterTitle","TitleSmall","EditorFooterRight","Fragment","InfoIcon","BodyCaption","Container","idx","ChevronLeftIcon","ChevronRightIcon","Tooltip","ThumbsUpIcon","ThumbsDownIcon","RewindIcon","CrossIcon","CheckIcon","TextSpace","pastedText","el","base","caret","ta","EditIcon","instructionToApply","WhatsAppTextEditorHeader"],"mappings":"+iCA0DMA,GAAgB,0BAChBC,GAAmB,IACnBC,GAA0B,EAC1BC,GAAkB,EAClBC,GAAwB,KACxBC,GAA2B,IAC3BC,GACL,iIAEKC,GAAgBC,GAAAA;AAAAA;AAAAA;AAAAA;AAAAA,EAMhBC,GAA0BC,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjCC,EAAqBD,EAAAA,QAAO;AAAA;AAAA;AAAA,UAGvBE,GAAUA,EAAM,KAAK;AAAA;AAAA,cAElBL,EAAa;AAAA,EAGrBM,GAA6BH,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBpCI,GAAyBJ,EAAAA,QAAO;AAAA;AAAA,UAE5BK,EAAAA,OAAO,QAAQ,SAAS;AAAA,EAG5BC,GAA0BN,EAAAA,QAAO;AAAA,UAC7BK,EAAAA,OAAO,QAAQ,OAAO;AAAA,EAG1BE,GAA8BP,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrCQ,GAAwBR,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAM/BS,GAAoBT,EAAAA,QAAO;AAAA,UACvBK,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA,EAI1BK,EAAuBV,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAS1BK,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA;AAAA,sBAGVA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStCM,GAA6BX,EAAAA,QAAOU,CAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxDE,GAAwBZ,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMvBH,EAAa;AAAA,EAIrBgB,GAAuBb,EAAAA,QAAO;AAAA,eACrBK,EAAAA,OAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShCS,GAAsBd,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOpBK,EAAAA,OAAO,QAAQ,QAAQ;AAAA,EAGhCU,GAAmBf,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOtBK,EAAAA,OAAO,QAAQ,OAAO;AAAA,EAG1BW,GAAqBhB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAM5BiB,GAAoBjB,EAAAA,QAAO;AAAA;AAAA;AAAA,UAGvBK,EAAAA,OAAO,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5Ba,GAAqBlB,EAAAA,QAAO;AAAA;AAAA;AAAA,eAGnBK,EAAAA,OAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShCc,GAA4BnB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,eAI1BK,EAAAA,OAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShCe,GAA8BpB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,eAI3BE,GAAWA,EAAM,SAAW,UAAY,aAAc;AAAA,UAC3DA,GAAWA,EAAM,SAAW,UAAYG,EAAAA,OAAO,QAAQ,OAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAOzDH,GACdA,EAAM,SAAW,UAAYG,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA,EA0HhDgB,EAA0B,IAAIC,GAAAA,8BAE9BC,GAAuD,CAC5D,CAACC,EAAAA,kBAAkB,IAAI,EAAG,IAC1B,CAACA,EAAAA,kBAAkB,MAAM,EAAG,IAC5B,CAACA,EAAAA,kBAAkB,aAAa,EAAG,GACpC,EAEA,SAASC,GAAuBC,EAA4B,CAC3D,MAAO,sCAAsCA,GAAqB,SAAS,EAC5E,CAEO,MAAMC,GAAqBC,GAAAA,QAAM,WAIvC,CACC,CACC,SAAAC,EACA,gBAAAC,GACA,KAAMC,EACN,eAAAC,GACA,MAAAC,EACA,MAAAC,EACA,QAAAC,EACA,KAAAC,GACA,QAAAC,GACA,kBAAAX,EACA,gBAAAY,GACA,aAAAC,EAAe,YACf,WAAAC,EACA,gBAAAC,GACA,QAAAC,GACA,aAAAC,GACA,QAAAC,GACA,QAAAC,GACA,WAAAC,GACA,eAAAC,GAAiB,2BACjB,SAAAC,GAAW,kBACX,OAAAC,GAAS,UACT,iBAAAC,GAAmB,CAClBC,EAAAA,oBAAoB,SACpBA,EAAAA,oBAAoB,QACpBA,EAAAA,oBAAoB,OACpBA,sBAAoB,OAAA,EAErB,wBAAAC,GAA0B,GAC1B,gBAAAC,GACA,cAAAC,GACA,iBAAAC,GACA,uBAAAC,GAAyBC,EAAAA,gCACzB,iBAAAC,GACA,gBAAAC,GACA,sBAAAC,EAAwB,GACxB,aAAAC,GACA,eAAAC,GACA,kBAAAC,GACA,gBAAAC,GACA,OAAQC,GACR,GAAGC,EAAA,EAEJC,KACI,CACJ,MAAMC,EAAeC,EAAAA,OAA4B,IAAI,EAC/C,CAACC,EAAaC,EAAc,EAAIC,EAAAA,SAASzC,GAAc,EAAE,EACzD,CAAC0C,GAAuBC,CAAwB,EAAIF,EAAAA,SAAS,EAAK,EAClE,CAACG,GAAwBC,EAAyB,EAAIJ,EAAAA,SAAS,CAAC,EAChE,CAACK,EAAcC,EAAe,EAAIN,EAAAA,SAAS,EAAK,EAChD,CAACO,GAA2BC,EAA4B,EAC7DR,EAAAA,SAAS,EAAK,EACT,CAACS,EAAiBC,EAAkB,EAAIV,EAAAA,SAAS,EAAE,EACnD,CAACW,GAAcC,EAAe,EAAIZ,EAAAA,SAEtC,CAAA,CAAE,EACE,CAACa,EAAoBC,EAAqB,EAAId,EAAAA,SACnD,IAAA,EAEK,CAACe,EAAsBC,EAAuB,EAAIhB,EAAAA,SACvD,CAAA,CAAC,EAEI,CAACiB,EAAiBC,CAAkB,EAAIlB,EAAAA,SAAS,CAAC,EAClD,CAACmB,EAAsBC,EAAuB,EACnDpB,EAAAA,SAAoC,IAAI,EACnCqB,GAAsBxB,EAAAA,OAA8B,IAAI,EACxDyB,EAAkBzB,EAAAA,OAA6C,IAAI,EACnE0B,EAAoB1B,EAAAA,OACzB,IAAA,EAEK2B,EAAoB3B,EAAAA,OACzB,IAAA,EAMK4B,EAA0B5B,EAAAA,OAAuB,IAAI,EACrD6B,EAAkB7B,EAAAA,OAA6C,IAAI,EACnE8B,GAA4B9B,EAAAA,OAAsB,IAAI,EAEtD+B,GAA2B/B,EAAAA,OAAO,CAAC,CAACT,CAAqB,EACzDyC,GAA6BhC,EAAAA,OAKzB,IAAI,EAERiC,EAAyBjC,EAAAA,OAAO,EAAE,EAClCkC,GAA6BlC,EAAAA,OAAO,EAAK,EACzC,CAACmC,GAA0BC,EAA2B,EAAIjC,EAAAA,SAE9D,CAAA,CAAE,EACEkC,GAAoBrC,EAAAA,OACzB,SAAS,KAAK,IAAA,EAAM,SAAS,EAAE,CAAC,IAAI,KAAK,OAAA,EACvC,SAAS,EAAE,EACX,MAAM,EAAG,CAAC,CAAC,EAAA,EAERsC,EAAsBC,EAAAA,QAAQ,IAC5BnF,GACN,GAAGC,GAAqB,SAAS,IAChCY,IAAmBoE,GAAkB,OACtC,EAAA,EAEC,CAAChF,EAAmBY,EAAe,CAAC,EAEvCuE,EAAAA,UAAU,IAAM,CACfT,GAAyB,QAAU,CAAC,CAACxC,CACtC,EAAG,CAACA,EAAuBlC,CAAiB,CAAC,EAE7CmF,EAAAA,UAAU,IAAM,CACfN,GAA2B,QAAU,GACrCD,EAAuB,QAAU,EAClC,EAAG,CAAC5E,EAAmBY,EAAe,CAAC,EAEvCuE,EAAAA,UAAU,IAAM,CACf,GAAI,CAACjD,EAAuB,CAC3B2C,GAA2B,QAAU,GACrCD,EAAuB,QAAU,GACjC,MACD,CACA,GAAIC,GAA2B,QAAS,OACxC,MAAMO,EAAO/E,GAAc,GACvB+E,EAAK,OAAS,IACjBR,EAAuB,QAAUQ,EACjCP,GAA2B,QAAU,GAEvC,EAAG,CAAC3C,EAAuB7B,EAAYL,EAAmBY,EAAe,CAAC,EAE1E,MAAMyE,GAAsBH,EAAAA,QAAQ,IAC5BI,uBAAqBzE,EAAcc,GAAiBC,EAAa,EACtE,CAACD,GAAiBC,GAAef,CAAY,CAAC,EAE3C0E,GAAiCL,EAAAA,QAAQ,IAAM,CACpD,MAAMM,EAAQjC,EAAgB,KAAA,EAAO,YAAA,EACrC,OAAKiC,EACE1D,GAAuB,OAAQ2D,GACrCA,EAAW,YAAA,EAAc,SAASD,CAAK,CAAA,EAFrB,CAAA,CAIpB,EAAG,CAAC1D,GAAwByB,CAAe,CAAC,EAEtCmC,EAAmBR,EAAAA,QAAQ,KACzB,CACN,GAAGS,EAAAA,4BACH,GAAI9D,IAAoB,CAAA,CAAC,GAExB,CAACA,EAAgB,CAAC,EAEf+D,GACLF,EAAiBjE,EAAAA,oBAAoB,QAAQ,GAC7CkE,EAAAA,4BAA4BlE,EAAAA,oBAAoB,QAAQ,EAEnDoE,GAA2BC,cAAaC,GAAkB,CAC/D,MAAMC,EAAaD,EAAM,KAAA,EAAO,QAAQ,OAAQ,GAAG,EACnD,GAAI,CAACC,EAAY,MAAO,GACxB,MAAMC,EAAQD,EAAW,MAAM,GAAG,EAAE,OACpC,MAAO,sBAAsBA,EAAW,MAAM,UAAUC,CAAK,GAC9D,EAAG,CAAA,CAAE,EAECC,EAAcJ,EAAAA,YACnB,CAACK,EAAmBC,IAA4B,CAC/CpE,KAAmBmE,EAAMC,CAAO,CACjC,EACA,CAACpE,EAAgB,CAAA,EAGZqE,EAAgBP,cAAaQ,GAAqB,CACvDzD,GAAgB0D,GAAUA,IAASD,EAAWC,EAAOD,CAAS,CAC/D,EAAG,CAAA,CAAE,EAECE,EAAsBV,EAAAA,YAC1BQ,GAAqB,CAIrB,GAHI9B,EAAgB,SACnB,aAAaA,EAAgB,OAAO,EAEjC8B,EAAS,OAAStI,GAAuB,CAC5CmC,IAAWmG,EAAUA,CAAQ,EAC7B9B,EAAgB,QAAU,WAAW,IAAM,CAC1CrE,IAAWmG,EAAU3G,EAAwB,QAAQ2G,CAAQ,CAAC,CAC/D,EAAG,EAAE,EACL,MACD,CACAnG,IAAWmG,EAAU3G,EAAwB,QAAQ2G,CAAQ,CAAC,CAC/D,EACA,CAACnG,CAAQ,CAAA,EAGJsG,GAA6BX,EAAAA,YACjCQ,GAAqB,CAErB,MAAMI,EADS/B,GAA2B,SAEjC,eACPzC,EAAwB0C,EAAuB,QAAU,IAE3D,GADI,CAAC8B,GACDJ,IAAaI,EAAgB,OACjC,MAAMC,EAAmBC,GAAAA,uBAAuB,CAC/C,eAAgBF,EAChB,kBAAmBJ,CAAA,CACnB,EACDrE,KAAkB,CACjB,GAAG0E,EACH,OAAQ,oBAAA,CACR,CACF,EACA,CAAC1E,GAAiBC,CAAqB,CAAA,EAGlC2E,EAAyBf,EAAAA,YAAY,IAAM,CAChDlC,GAAsB,IAAI,EAC1BE,GAAwB,CAAA,CAAE,EAC1BE,EAAmB,CAAC,EACpBE,GAAwB,IAAI,EAC5Ba,GAA4B,CAAA,CAAE,CAC/B,EAAG,CAAA,CAAE,EAEC+B,GAA2BhB,EAAAA,YAAY,IAAM,CAOlD,GANI3C,GAGEQ,GAAsBE,EAAqB,OAAS,GAGtDZ,IAA0BnF,GAC7B,OAED,MAAMiJ,EAAY9D,GAAyB,EAC3CC,GAA0B6D,CAAS,EAC/B,OAAO,OAAW,KAAe/G,GACpC,eAAe,QAAQiF,EAAqB,OAAO8B,CAAS,CAAC,EAE9D/D,EAAyB,EAAI,EACzBqB,EAAkB,SACrB,aAAaA,EAAkB,OAAO,EAEvCA,EAAkB,QAAU,WAAW,IAAM,CAC5CrB,EAAyB,EAAK,CAC/B,EAAG,IAAI,CACR,EAAG,CACFhD,EACAiF,EACA9B,EACAQ,EACAE,EACAZ,EAAA,CACA,EAEK+D,GAA8BrE,EAAAA,OAAOmE,EAAwB,EACnEE,GAA4B,QAAUF,GAEtC,SAASG,GAAe,EAA2C,CAClE,MAAMC,EAAOC,GAAAA,cAAc,EAAE,OAAO,KAAK,EACnCC,EAAqBzC,GAA2B,QAErDyC,GACA,CAACA,EAAmB,oBACpBF,IAASE,EAAmB,eAE5BzC,GAA2B,QAAU,CACpC,GAAGyC,EACH,mBAAoB,EAAA,EAErBlB,EAAY,uBAAwB,CACnC,YAAakB,EAAmB,WAChC,YAAatG,CAAA,CACb,GAEEwD,EAAkB,UACrB,aAAaA,EAAkB,OAAO,EACtCA,EAAkB,QAAU,MAE7B,MAAM+C,EACLD,GAAoB,eACnBlF,EAAwB0C,EAAuB,QAAU,IACvDyC,GAA8BH,IAASG,IAC1C/C,EAAkB,QAAU,WAAW,IAAM,CAC5CmC,GAA2BS,CAAI,CAChC,EAAGjJ,EAAwB,GAE5BoI,EAAca,CAAI,EAClBV,EAAoBU,CAAI,CACzB,CAEA,SAASI,GAAiBC,EAAkB,CAC3C,MAAMC,EAAO9E,GAAc,QAEvB8E,GAAQ,OACPA,EAAK,gBACRA,EAAK,MAAA,EACLA,EAAK,aAAeD,KACT,MAAA,EAEd,CAEA,SAASE,GAAeC,EAA+B,CACtD,MAAMC,EAAW9H,GAAY6H,CAAU,EACvC,GAAIC,GAAYjF,EAAa,QAAS,CACrC,MAAMkF,EAAQlF,EAAa,QAAQ,eAC7BmF,EAAMnF,EAAa,QAAQ,aAEjC,GAAIkF,IAAUC,EAAK,CAClB,KAAM,CAAE,KAAAX,CAAA,EAASY,GAAkBH,EAAUC,CAAK,EAClDN,GAAiBM,EAAQ,CAAC,EAC1BpB,EAAoBU,CAAI,CACzB,KAAO,CACN,KAAM,CAAE,KAAAA,CAAA,EAASa,GAAcJ,CAAQ,EACvCnB,EAAoBU,CAAI,CACzB,CACD,CACD,CAEA,SAASc,GAAgBC,EAAe,CACvC,KAAM,CAAE,KAAAf,CAAA,EAASgB,GAAQD,CAAK,EAC9BzB,EAAoBU,CAAI,CACzB,CAEA,SAASa,GAAcI,EAAoB,CAC1C,IAAIjB,EAAOxE,EAAa,SAAS,OAAS,GAE1C,GAAIA,EAAa,SAAWyF,EAAW,CACtC,MAAMP,EAAQlF,EAAa,QAAQ,eAC7BmF,EAAMnF,EAAa,QAAQ,aAE3BiF,EAAWQ,EACjB,GAAIP,IAAUC,EAIb,OAAOK,GAAQP,CAAQ,EACjB,CACNT,EAAOvH,EAAwB,cAC9BiI,EACAC,EACAF,EACAT,CAAA,EAED,MAAMkB,EAAOzI,EAAwB,QAAQuH,CAAI,EACjD,OAAAb,EAAca,CAAI,EACX,CAAE,KAAAA,EAAM,KAAAkB,CAAA,CAChB,CACD,CAEA,MAAO,CAAE,KAAAlB,EAAa,KAAMA,CAAA,CAC7B,CAEA,SAASgB,GAAQC,EAAmB,CACnC,MAAMjB,EAAOxE,EAAa,SAAS,OAAS,GAE5C,GAAIA,EAAa,SAAWyF,EAAW,CACtC,MAAMP,EAAQlF,EAAa,QAAQ,eAC7BmF,EAAMnF,EAAa,QAAQ,aACjC,GAAIkF,IAAUC,EACb,OAAOC,GAAkBK,EAAWP,CAAK,CAE3C,CACA,MAAO,CAAE,KAAAV,EAAa,KAAMA,CAAA,CAC7B,CAEA,SAASY,GAAkBK,EAAmBE,EAAe,CAC5D,IAAInB,EAAOxE,EAAa,SAAS,OAAS,GAE1CwE,EAAOA,EAAK,MAAM,EAAGmB,CAAK,EAAIF,EAAYjB,EAAK,MAAMmB,CAAK,EAC1D,MAAMD,EAAOzI,EAAwB,QAAQuH,CAAI,EACjD,OAAAb,EAAca,CAAI,EACX,CAAE,KAAAA,EAAM,KAAAkB,CAAA,CAChB,CAEAjD,EAAAA,UAAU,IAAM,CACf,GAAI,OAAO,OAAW,KAAe,CAACnF,EAAmB,OACzD,MAAMsI,EAAS,OAAO,eAAe,QAAQrD,CAAmB,GAAK,GAAG,EACxE,OAAK,OAAO,MAAMqD,CAAM,GACvBpF,GAA0BoF,CAAM,EAE1B,IAAM,CACZ,eAAe,WAAWrD,CAAmB,CAC9C,CACD,EAAG,CAACjF,EAAmBiF,CAAmB,CAAC,EAE3CE,EAAAA,UAAU,IAAM,CACf,GAAIhC,EAAc,CACjBH,EAAyB,EAAK,EAC1BoB,EAAgB,UACnB,aAAaA,EAAgB,OAAO,EACpCA,EAAgB,QAAU,MAE3B,MACD,CACA,GAAMT,GAAsBE,EAAqB,OAAS,EAAG,CAC5Db,EAAyB,EAAK,EAC1BoB,EAAgB,UACnB,aAAaA,EAAgB,OAAO,EACpCA,EAAgB,QAAU,MAE3B,MACD,CACA,MAAMmE,EACL,CAAC,CAAC3F,EAAY,KAAA,GAAUA,EAAY,QAAUgD,GAE/C,GAAIrB,EAAwB,UAAY,KAAM,CAC7CA,EAAwB,QAAUgE,EAC9BA,IACHnE,EAAgB,QAAU,WAAW,IAAM,CAC1C4C,GAA4B,QAAA,CAC7B,EAAGnJ,EAAgB,GAEpB,MACD,CAEA,GAAI,CAAC0K,EAAU,CACdhE,EAAwB,QAAU,GAClCvB,EAAyB,EAAK,EAC1BoB,EAAgB,UACnB,aAAaA,EAAgB,OAAO,EACpCA,EAAgB,QAAU,MAE3B,MACD,CAEA,MAAMoE,EAAmB,CAACjE,EAAwB,SAAWgE,EAC7DhE,EAAwB,QAAU,GAE9BiE,GACHxB,GAA4B,QAAA,EAGzB5C,EAAgB,SACnB,aAAaA,EAAgB,OAAO,EAErCA,EAAgB,QAAU,WAAW,IAAM,CAC1C4C,GAA4B,QAAA,CAC7B,EAAGnJ,EAAgB,CACpB,EAAG,CACF+E,EACAO,EACAyC,GACAjC,EACAE,CAAA,CACA,EAEDsB,EAAAA,UAAU,IACF,IAAM,CACRf,EAAgB,SAAS,aAAaA,EAAgB,OAAO,EAC7DC,EAAkB,SAAS,aAAaA,EAAkB,OAAO,EACjEG,EAAgB,SAAS,aAAaA,EAAgB,OAAO,EAC7DF,EAAkB,SAAS,aAAaA,EAAkB,OAAO,CACtE,EACE,CAAA,CAAE,EAEL,MAAMmE,EAAkB5E,EAAqBE,CAAe,GAAK,GAC3D2E,EAA6BxD,EAAAA,QAAQ,IACtC,CAACjB,GAAwB,CAACwE,EAAwB,KAC/C,GAAGxE,CAAoB,IAAIF,CAAe,IAAI0E,CAAe,GAClE,CAACA,EAAiBxE,EAAsBF,CAAe,CAAC,EACrD4E,GAAgC,CAAC,EACtCD,GACA5D,GAAyB4D,CAA0B,GAE9CE,GAAqB1D,EAAAA,QAC1B,IAAMvF,EAAwB,QAAQgE,GAAsB,EAAE,EAC9D,CAACA,CAAkB,CAAA,EAEdkF,GAAsB3D,EAAAA,QAC3B,IAAMvF,EAAwB,QAAQ8I,CAAe,EACrD,CAACA,CAAe,CAAA,EAEXK,GAAgBjF,EAAqB,OAAS9F,GAC9CgL,EACL,CAAC,CAACpF,GAAsBE,EAAqB,OAAS,EACjDmF,GACLnF,EAAqB,QAAU,GAAKE,GAAmB,EAClDkF,GACLpF,EAAqB,QAAU,GAC/BE,GAAmBF,EAAqB,OAAS,EAElDsB,EAAAA,UAAU,IAAM,CACf,GAAI,CAAC4D,EAA6B,OAClC,MAAMG,EAAO/E,GAAoB,QAC5B+E,IACLA,EAAK,UAAYA,EAAK,aACvB,EAAG,CAACT,EAAiBM,EAA6B5F,CAAY,CAAC,EAE/D,MAAMgG,EAAkBrD,EAAAA,YACvB,MACC4B,EACA0B,EAAqB,GACrBC,EACAC,EACAC,EAAiCC,EAAAA,gBAAgB,UAC7C,CACJ,GACC,CAACnH,IACD,CAACjB,KACA,CAACL,IAAmB,CAACC,IACrB,CACDP,IAAU,0BAA0B,EACpC,MACD,CACA,GAAI,CAACmC,EAAY,OAAQ,OACzB,MAAM6G,EACL/D,EAAiBgC,CAAU,GAC3B/B,EAAAA,4BAA4B+B,CAAU,GACtC,GAGD,GAFI9E,EAAY,OAAS6G,GACrBtG,GACAiG,GAAsB,CAACN,GAAe,OAE1C,MAAMY,GAAarE,GAAoBqC,CAAU,EAC3CiC,EACLjC,IAAejG,EAAAA,oBAAoB,UACnCZ,IAAiB,WACjB0I,IAAkBC,EAAAA,gBAAgB,SAC/B,CACA,GAAGE,GACH,MAAO,WACP,WAAYxL,EAAA,EAEZwL,GAGEE,EAAiBN,GAAkB7F,GAAaiE,CAAU,EAC1DmC,GAAeF,EAAO,OAAO,KACjCG,GAASA,EAAK,KAAOF,CAAA,EAEjBG,GACLV,IAAwB,OACrBA,EACA9F,EACEyG,GACL1H,KAAkB,CACjB,WAAAoF,EACA,cAAA6B,EACA,YAAA3G,EACA,aAAA/B,EACA,OAAA8I,EACA,OAAQC,EACR,UAAWC,IAAc,MACzB,gBAAiBE,IAAwB,MAAA,CACzC,GACDE,GAAAA,kBAAkB,CACjB,OAAAN,EACA,YAAA/G,EACA,eAAAgH,EACA,gBAAiBG,EAAA,CACjB,EAEF3G,GAAgB,EAAI,EACpB8C,EAAY,sBAAuB,CAClC,YAAawB,EACb,YAAa5G,EACb,kBAAmBD,CAAA,CACnB,EACD,GAAI,CACH,MAAMqJ,EAAS7H,GACZ,MAAMA,GAAkB,CACxB,WAAAqF,EACA,cAAA6B,EACA,YAAA3G,EACA,aAAA/B,EACA,OAAQ+I,EACR,UAAWC,IAAc,MACzB,gBAAiBE,IAAwB,OACzC,OAAAC,EAAA,CACC,EACD,MAAMG,GAAAA,oBAAoB,CAC1B,WAAA/I,GACA,gBAAAL,GACA,QAAAC,GACA,aAAAC,GACA,OAAA+I,GACA,OAAAzI,GACA,eAAAF,GACA,SAAAC,GACA,QAAAJ,GACA,QAAAC,EAAA,CACC,EACEiJ,GACL,OAAOF,GAAW,SACfA,EAAO,QACNA,GAAQ,MAAQ,IAAI,KAAA,EACzB,GAAI,CAACE,GAAW,OAChB,GAAI,CAAChB,EAAoB,CACxBxF,GAAsBhB,CAAW,EACjCsB,GAAwBwD,CAAU,EAClC5D,GAAwB,CAACsG,EAAS,CAAC,EACnCpG,EAAmB,CAAC,EACpB,MACD,CACAF,GAAyByC,IAAS,CACjC,MAAM8D,GAAO,CAAC,GAAG9D,GAAM6D,EAAS,EAAE,MAAM,EAAGrM,EAAe,EAC1D,OAAAiG,EAAmBqG,GAAK,OAAS,CAAC,EAC3BA,EACR,CAAC,CACF,MAAY,CACX5J,IAAU,kCAAkC,CAC7C,QAAA,CACC2C,GAAgB,EAAK,CACtB,CACD,EACA,CACCrC,GACAC,GACA4B,EACAO,EACA2F,GACAzD,GACA5B,GACAF,EACA2C,EACApF,EACAG,GACAG,GACAG,GACAF,GACAC,GACAJ,GACAC,GACAN,EACAJ,EACAiF,EACArD,GACAC,EAAA,CACD,EAGKgI,GAAyBxE,EAAAA,YAAY,IAAM,CAChD,GAAI,CAAC2C,GAAmB,CAAC9E,GAAsB,CAACM,EAC/C,OACDoC,EAAcoC,CAAe,EAC7BjC,EAAoBiC,CAAe,EACnCvC,EAAY,yBAA0B,CACrC,YAAajC,EACb,YAAanD,CAAA,CACb,EACD6D,GAA2B,QAAU,CACpC,aAAc8D,EACd,aAAc9E,EACd,WAAYM,EACZ,mBAAoB,EAAA,EAGrB,MAAMsG,EAAmB7F,GAAyB,QAC5C8F,EAAaC,GAAAA,qBAAqB,CACvC,aAAc9G,EACd,aAAc8E,EACd,sBAAuB8B,CAAA,CACvB,EACGA,IACH7F,GAAyB,QAAU,IAEpCzC,KAAkB,CACjB,GAAGuI,EACH,OAAQ,QAAA,CACR,EACD3D,EAAA,CACD,EAAG,CACF4B,EACA9E,EACAM,EACAoC,EACAG,EACAN,EACApF,EACAmB,GACA4E,CAAA,CACA,EAEK6D,GAAyB5E,EAAAA,YAAY,IAAM,CAC3C7B,IACLiC,EAAY,0BAA2B,CACtC,YAAajC,EACb,YAAanD,CAAA,CACb,EACD+F,EAAA,EACD,EAAG,CAACA,EAAwBX,EAAajC,EAAsBnD,CAAU,CAAC,EAEpE6J,GAAiB7E,EAAAA,YACrB8E,GAA6B,CACzB,CAAC3G,GAAwB,CAACyE,GAC1B5D,GAAyB4D,CAA0B,IACvD3D,GAA6BwB,IAAU,CACtC,GAAGA,EACH,CAACmC,CAA0B,EAAGkC,CAAA,EAC7B,EACF1E,EAAY,wBAAyB,CACpC,YAAajC,EACb,YAAanD,EACb,OAAA8J,EACA,gBAAiB7G,EAAkB,CAAA,CACnC,EACF,EACA,CACC2E,EACAxC,EACApB,GACAb,EACAF,EACAjD,CAAA,CACD,EAGK+J,GAAoC3F,EAAAA,QAAQ,IAC7CxD,GAAgC,CAAA,EAC7BF,GAAiB,IAAKkG,GAAe,CAC3C,MAAMoD,EAAezF,GAAoBqC,CAAU,EAC7CqD,EAAStH,GAAaiE,CAAU,EACtC,MAAO,CACN,KAAMA,EACN,MAAOoD,EAAa,MACpB,UAAWpD,IAAejG,EAAAA,oBAAoB,SAC9C,QAAS0B,GAAgBc,IAAyByD,EAClD,YACCA,IAAejG,sBAAoB,UACnCsB,GACD,SACC,CAACH,EAAY,KAAA,GACbA,EAAY,QACV8C,EAAiBgC,CAAU,GAC3B/B,EAAAA,4BAA4B+B,CAAU,GACtC,KACFvE,GACC4F,GACA9E,IAAyByD,EAC3B,iBACCA,IAAejG,sBAAoB,UACnC,CAAC,CAACqJ,EAAa,OAAO,OACvB,MAAOA,EAAa,MACpB,eAAgBC,CAAA,CAElB,CAAC,EACC,CACFvJ,GACAE,GACA2D,GACA5B,GACAN,EACAc,EACA8E,EACAhG,GACAH,EACA8C,CAAA,CACA,EAEDsF,OAAAA,EAAAA,oBACCvI,GACA,KACQ,CACN,cAAAsF,GACA,QAAAG,GACA,KAAM,CACL,OAAOtF,CACR,EACA,iBAAA0E,EAAA,GAGF,CAACS,GAAeG,GAAStF,CAAW,CAAA,EAGrCuC,EAAAA,UAAU,IAAM,CACX9E,IAAe,QACnBgG,EAAchG,GAAc,EAAE,CAC/B,EAAG,CAACA,EAAYgG,CAAa,CAAC,EAE9BlB,EAAAA,UAAU,IAAM,CACf,GAAI,CAAC3E,GAAS,CAACC,EAAS,OACxB,MAAMwK,EACLrI,EAAY,OAASpC,EAAQ5C,GAAgB2C,GAAS,GACnDkE,GAA0B,UAAYwG,IAC1CxG,GAA0B,QAAUwG,EACpCxK,EAAQwK,CAAS,EAClB,EAAG,CAACrI,EAAarC,EAAOC,EAAOC,CAAO,CAAC,SAGrCyK,iBAAA,CACA,SAAA,CAAAC,OAACC,EAAAA,gBAAA,CACA,SAAA,CAAAC,EAAAA,IAACC,EAAAA,kBAAA,CACC,YACAD,EAAAA,IAACE,GAAAA,WAAA,CAAW,YAAU,8BACpB,SAAApJ,EAAA,CACF,EACG,IAAA,CACL,SACCqJ,EAAAA,kBAAA,CACC,SAAA,CAAAjL,GAASA,IAAU3C,GACnBuN,EAAAA,KAAAM,EAAAA,SAAA,CACC,SAAA,CAAAJ,EAAAA,IAACK,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAO/M,EAAAA,OAAO,QAAQ,QAAA,CAAA,QAEtBgN,GAAAA,YAAA,CAAY,MAAOhN,EAAAA,OAAO,QAAQ,SACjC,SAAA4B,CAAA,CACF,CAAA,CAAA,CACD,EACG,KACHC,EACA2K,EAAAA,KAACQ,GAAAA,YAAA,CACA,MAAO,CACN,MACCpL,IAAU3C,IAAiBgF,EAAY,OAASpC,EAC7C7B,EAAAA,OAAO,QAAQ,SACfA,EAAAA,OAAO,QAAQ,SAAA,EAGnB,SAAA,CAAAiE,EAAY,OAAO,IAAEpC,CAAA,CAAA,CAAA,EAEpB,IAAA,CAAA,CACL,CAAA,EACD,EACA2K,EAAAA,KAACS,EAAAA,UAAA,CAAU,QAAS,CAAC,CAACrL,EACpB,SAAA,CAAAwI,EACAoC,EAAAA,KAAC1M,GAAA,CAA2B,IAAK0F,GAChC,SAAA,CAAAkH,EAAAA,IAAC3M,GAAA,CACA,wBAAyB,CAAE,OAAQkK,EAAA,CAAmB,CAAA,EAEtDzF,EACAkI,EAAAA,IAACzM,GAAA,CAAwB,YAAU,OAClC,gBAACC,GAAA,CACA,SAAA,CAAAwM,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,EAChC8M,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,EAChC8M,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,CAAA,CAAA,CACjC,EACD,EAEA8M,EAAAA,IAACzM,GAAA,CACA,wBAAyB,CACxB,OAAQiK,EAAA,CACT,CAAA,SAGD/J,GAAA,CACA,SAAA,CAAAuM,EAAAA,IAACrM,EAAA,CACA,aAAW,sBACX,KAAK,SACL,SAAUgK,GACV,QAAS,IACRhF,EAAoB6H,GAAQ,KAAK,IAAI,EAAGA,EAAM,CAAC,CAAC,EAGjD,SAAAR,EAAAA,IAACS,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOnN,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,SAEAI,GAAA,CACC,SAAA,CAAAgF,EAAkB,EAAE,IAAEF,EAAqB,MAAA,EAC7C,EACAwH,EAAAA,IAACrM,EAAA,CACA,aAAW,kBACX,KAAK,SACL,SAAUiK,GACV,QAAS,IACRjF,EAAoB6H,GACnB,KAAK,IAAIhI,EAAqB,OAAS,EAAGgI,EAAM,CAAC,CAAA,EAInD,SAAAR,EAAAA,IAACU,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOpN,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,EAED0M,EAAAA,IAACW,GAAAA,QAAA,CAAQ,KAAK,OAAO,UAAU,MAC9B,SAAAX,EAAAA,IAACrM,EAAA,CACA,aAAW,kBACX,KAAK,SACL,SAAU2J,GACV,QAAS,IAAMgC,GAAe,MAAA,EAE9B,SAAAU,EAAAA,IAACY,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOtN,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,EAEF,EACA0M,EAAAA,IAACW,GAAAA,QAAA,CAAQ,KAAK,UAAU,UAAU,MACjC,SAAAX,EAAAA,IAACrM,EAAA,CACA,aAAW,qBACX,KAAK,SACL,SAAU2J,GACV,QAAS,IAAMgC,GAAe,SAAA,EAE9B,SAAAU,EAAAA,IAACa,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOvN,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,EAEF,EACCmK,GACAuC,EAAAA,IAACW,GAAAA,QAAA,CACA,KAAM7I,EAAe,gBAAkB,aACvC,UAAU,MAEV,SAAAkI,EAAAA,IAACpM,GAAA,CACA,aAAW,wBACX,YAAWkE,EACX,KAAK,SACL,SAAUA,EACV,QAAS,IAAM,CACVc,GACHkF,EAAgBlF,EAAsB,EAAI,CAE5C,EAEC,SAAAd,EACAkI,EAAAA,IAACnM,GAAA,CAAsB,cAAW,EAAA,CAAC,EAEnCmM,EAAAA,IAACc,GAAAA,QAAA,CAAW,MAAO,GAAI,OAAQ,EAAA,CAAI,CAAA,CAAA,CAErC,CAAA,EAEE,KACJd,EAAAA,IAACW,GAAAA,QAAA,CAAQ,KAAK,UAAU,UAAU,MACjC,SAAAX,EAAAA,IAACrM,EAAA,CACA,aAAW,qBACX,KAAK,SACL,QAAS0L,GAET,SAAAW,EAAAA,IAACe,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOzN,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,EAEF,EACA0M,EAAAA,IAACW,GAAAA,QAAA,CAAQ,KAAK,SAAS,UAAU,MAChC,SAAAX,EAAAA,IAACrM,EAAA,CACA,aAAW,oBACX,KAAK,SACL,QAASsL,GAET,SAAAe,EAAAA,IAACgB,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAO1N,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,CACD,CACD,CAAA,CAAA,CACD,CAAA,CAAA,CACD,EACGwE,EACHgI,EAAAA,KAAC9M,GAAA,CACA,SAAA,CAAAgN,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,EAChC8M,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,EAChC8M,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,EAChC8M,EAAAA,IAAC9M,EAAA,CAAmB,MAAM,KAAA,CAAM,CAAA,CAAA,CACjC,EAEA8M,EAAAA,IAACiB,EAAAA,UAAA,CACA,IAAK5J,EACJ,GAAGF,GACJ,MAAOI,EACP,SAAUqE,GACV,OAAS,GAAM,CACV3C,EAAkB,UACrB,aAAaA,EAAkB,OAAO,EACtCA,EAAkB,QAAU,MAE7BmC,GAA2B,EAAE,OAAO,KAAK,EACzClE,KAAiB,CAAC,CACnB,EACA,QAAU,GAAM,CACf,MAAMgK,EAAa,EAAE,cAAc,QAAQ,MAAM,EACjD,GAAIA,EAAW,OAASvO,GAAuB,CAC9C,EAAE,eAAA,EACF,MAAMwO,EAAK9J,EAAa,QAClBkF,EAAQ4E,GAAI,gBAAkB,EAC9B3E,EAAM2E,GAAI,cAAgB5E,EAE1B6E,EAAOD,GAAI,OAAS5J,EACpB0D,GACLmG,EAAK,MAAM,EAAG7E,CAAK,EAAI2E,EAAaE,EAAK,MAAM5E,CAAG,EACnDxB,EAAcC,EAAQ,EACtBE,EAAoBF,EAAQ,EAC5B,MAAMoG,EAAQ9E,EAAQ2E,EAAW,OACjC,sBAAsB,IAAM,CAC3B,MAAMI,EAAKjK,EAAa,QACxB,GAAKiK,EACL,GAAI,CACHA,EAAG,kBAAkBD,EAAOA,CAAK,CAClC,MAAQ,CAER,CACD,CAAC,CACF,CACD,EACA,KAAAhM,EAAA,CAAA,EAGD2C,UACClE,GAAA,CACA,SAAA,CAAAgM,OAAC/L,GAAA,CACA,SAAA,CAAAiM,EAAAA,IAACuB,GAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOjO,EAAAA,OAAO,QAAQ,SAAA,CAAA,EAEvB0M,EAAAA,IAAChM,GAAA,CACA,MAAOkE,EACP,YAAY,mDACZ,SAAW,GACVC,GAAmB2D,GAAAA,cAAc,EAAE,OAAO,KAAK,CAAC,CAAA,CAAA,SAGjD7H,GAAA,CACA,SAAA,CAAA+L,EAAAA,IAAC9L,GAAA,CACA,KAAK,SACL,QAAS,IAAM,CACdiE,GAAmB,EAAE,EACrBF,GAA6B,EAAK,CACnC,EACA,SAAA,QAAA,CAAA,EAGD+H,EAAAA,IAAC7L,GAAA,CACA,KAAK,SACL,QAAS,IAAM,CACd,MAAMqN,EAAqBtJ,EAAgB,KAAA,EACvCsJ,GACH3G,EAAY,sBAAuB,CAClC,YAAazE,EAAAA,oBAAoB,SACjC,YAAaX,EACb,iBACC+E,GAAyBgH,CAAkB,CAAA,CAC5C,EAEFvJ,GAA6B,EAAK,EAClCE,GAAmB,EAAE,EACrB2F,EACC1H,EAAAA,oBAAoB,SACpB,GACAoL,CAAA,CAEF,EACA,SAAA,SAAA,CAAA,CAED,CAAA,CACD,CAAA,EACD,EACCtJ,EAAgB,KAAA,EAAO,OAAS,GACjCgC,GAA+B,OAAS,EACvC8F,EAAAA,IAAC5L,GAAA,CACC,SAAA8F,GAA+B,IAAKE,GACpC4F,EAAAA,IAAC3L,GAAA,CAEA,KAAK,SACL,SAAU6D,IAAoBkC,EAC9B,QAAS,IAAMjC,GAAmBiC,CAAU,EAE3C,SAAAA,CAAA,EALIA,CAAA,CAON,EACF,EACG,IAAA,CAAA,CACL,EAEA4F,EAAAA,IAACyB,EAAAA,yBAAA,CACA,QAAAnM,GACA,IAAK+B,EACL,eAAA+E,GACA,eAAAnH,GACA,qBAAsByI,GAA+B5F,EACrD,aAAc6E,GACd,UAAW6C,GACX,kBAAmB9B,GAA+B5F,EAClD,kBAAmBE,GACnB,sBAAuB,IAAMC,GAA6B,EAAI,EAC9D,eAAgB,CAACoE,EAAYqD,IAAW,CACvCrH,GAAiB6C,IAAU,CAAE,GAAGA,EAAM,CAACmB,CAAU,EAAGqD,CAAA,EAAS,EAC7D3I,KAAiBsF,EAAYqD,CAAM,EAC/BrD,IAAejG,EAAAA,oBAAoB,UACtC0H,EACCzB,EACA,GACA,OACAqD,EACAvB,kBAAgB,OAAA,CAGnB,EACA,gBAAiB,CAChB9B,EACA6B,EAAgBC,EAAAA,gBAAgB,UAC5B,CACJ,GAAI,CAAArG,EAEJ,IAAI4F,EAA6B,CAChC,GAAI9E,IAAyByD,EAG5B,OAGDb,EAAA,EACAsC,EACCzB,EACA,GACA,OACA,OACA6B,CAAA,EAED,MACD,CAEAJ,EACCzB,EACA,GACA,OACA,OACA6B,CAAA,EAEF,CAAA,CAAA,CACD,CAAA,CAEF,CAAA,EACD,CAEF,CACD,EAEAtJ,GAAmB,YAAc"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
cursor: ${e=>e.disabled?"not-allowed":"pointer"};
|
|
19
19
|
opacity: ${e=>e.disabled?.45:1};
|
|
20
20
|
display: flex;
|
|
21
|
-
|
|
21
|
+
:hover {
|
|
22
22
|
background-color: rgba(0, 0, 0, 0.03);
|
|
23
23
|
padding: 3px 6px;
|
|
24
24
|
}
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
display: flex;
|
|
58
58
|
align-items: center;
|
|
59
59
|
gap: 4px;
|
|
60
|
-
|
|
60
|
+
:hover {
|
|
61
61
|
background: ${e=>e.disabled?void 0:l.COLORS.surface.subdued};
|
|
62
62
|
}
|
|
63
63
|
`;var C=(e=>(e.BOLD="BOLD",e.ITALIC="ITALIC",e.STRIKETHROUGH="STRIKETHROUGH",e.EMOJI="EMOJI",e))(C||{}),T=(e=>(e.REPHRASE="rephrase",e.SHORTEN="shorten",e.EXPAND="expand",e.EMOJIFY="emojify",e))(T||{}),y=(e=>(e.DEFAULT="default",e.REPHRASE="rephrase",e))(y||{});const L=z.default.forwardRef(({onActionSelect:e,RightComponent:i,onEmojiClick:u,actions:a,aiActions:o,onAIActionClick:O,onAIToneChange:S,onAIInstructionsClick:k,instructionActive:v,disableAllActions:d,rightActionsDisabled:H},re)=>{const m=h.useRef(null),[n,I]=h.useState({BOLD:!1,ITALIC:!1,STRIKETHROUGH:!1,EMOJI:!1}),j=h.useCallback(()=>{I(r=>r.EMOJI?{...r,EMOJI:!1}:r)},[]);P.useOutside(m,()=>{j()}),h.useEffect(()=>{d&&I(r=>r.EMOJI?{...r,EMOJI:!1}:r)},[d]);function f(r,p){if(r.preventDefault?.(),p==="EMOJI"){if(d)return;I(M=>({...M,EMOJI:!n.EMOJI}))}e(p)}return!a?.length&&!i&&!o?.length?t.jsx(t.Fragment,{}):t.jsxs(X,{children:[a?.includes("EMOJI")&&t.jsxs(t.Fragment,{children:[t.jsx(c.Tooltip,{body:"Emoji",placement:"bottom",children:t.jsx(x,{style:{marginLeft:0},disabled:d,active:!!n.EMOJI,onClick:r=>{d||f(r,"EMOJI")},children:t.jsx(K.default,{width:16,height:16,color:g(n.EMOJI)})})}),n.EMOJI&&t.jsx(V,{ref:m,children:t.jsx(E,{onEmojiClick:r=>{j(),u?.(r.emoji)}})})]}),a?.includes("BOLD")&&t.jsx(t.Fragment,{children:t.jsx(c.Tooltip,{body:"Bold",placement:"bottom",children:t.jsx(x,{disabled:d,active:!!n.BOLD,onClick:r=>{d||f(r,"BOLD")},children:t.jsx(U.default,{width:10,height:17,color:g(n.BOLD)})})})}),a?.includes("ITALIC")&&t.jsx(t.Fragment,{children:t.jsx(c.Tooltip,{body:"Italics",placement:"bottom",children:t.jsx(x,{disabled:d,onClick:r=>{d||f(r,"ITALIC")},active:!!n.ITALIC,children:t.jsx(_.default,{width:9,height:16,color:g(n.ITALIC)})})})}),a?.includes("STRIKETHROUGH")&&t.jsx(t.Fragment,{children:t.jsx(c.Tooltip,{body:"Strikethrough",placement:"bottom",children:t.jsx(x,{disabled:d,active:!!n.STRIKETHROUGH,style:{borderRight:0},onClick:r=>{d||f(r,"STRIKETHROUGH")},children:t.jsx(N.default,{width:12,height:18,color:g(n.STRIKETHROUGH)})})})}),o?.length?t.jsx(Z,{children:o.map(r=>r.type==="rephrase"?t.jsx(W.AIRephraseButton,{label:r.label,disabled:d||r.disabled,loading:r.loading,highlighted:r.highlighted,tones:r.tones,selectedToneId:r.selectedToneId,instructionActive:v,onClick:()=>{d||O?.(r.type,"default")},onToneChange:p=>{d||S?.(r.type,p)},onInstructionsClick:()=>{d||k?.()},showSecondaryRephraseOption:r.label.toLowerCase()==="meta safe rewrite",onSecondaryRephraseClick:()=>{d||O?.(r.type,"rephrase")}},r.type):t.jsx("div",{children:t.jsx(A,{disabled:d||r.disabled||r.loading,children:t.jsx(ee,{type:"button",highlighted:!!r.highlighted||!!r.isPrimary,disabled:r.disabled||r.loading,onClick:()=>{d||O?.(r.type,"default")},children:r.loading?"...":r.label})})},r.type))}):null,t.jsx(Q,{children:i&&t.jsx(i,{rightActionsDisabled:!!H})})]})});L.displayName="WhatsAppTextEditorHeader";exports.AIActionVariant=y;exports.AIEditorActionTypes=T;exports.CustomRightBorder=Y;exports.EditorActionTypes=C;exports.WhatsAppTextEditorHeader=L;
|