@gravity-ui/markdown-editor 15.29.0 → 15.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/build/cjs/core/types/serializer.d.ts +5 -0
  2. package/build/cjs/core/types/serializer.js.map +1 -1
  3. package/build/cjs/extensions/behavior/Search/SearchViewPlugin.js +24 -0
  4. package/build/cjs/extensions/behavior/Search/SearchViewPlugin.js.map +1 -1
  5. package/build/cjs/extensions/markdown/Breaks/index.d.ts +2 -0
  6. package/build/cjs/extensions/markdown/Breaks/index.js +7 -4
  7. package/build/cjs/extensions/markdown/Breaks/index.js.map +1 -1
  8. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.d.ts +9 -0
  9. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  10. package/build/cjs/extensions/markdown/CodeBlock/const.d.ts +2 -1
  11. package/build/cjs/extensions/markdown/CodeBlock/const.js +6 -1
  12. package/build/cjs/extensions/markdown/CodeBlock/const.js.map +1 -1
  13. package/build/cjs/extensions/markdown/CodeBlock/index.d.ts +1 -2
  14. package/build/cjs/extensions/markdown/CodeBlock/index.js +5 -7
  15. package/build/cjs/extensions/markdown/CodeBlock/index.js.map +1 -1
  16. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/const.d.ts +3 -0
  17. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/const.js +5 -1
  18. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/const.js.map +1 -1
  19. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/index.d.ts +2 -6
  20. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
  21. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/index.js.map +1 -1
  22. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/parser.js +27 -1
  23. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/parser.js.map +1 -1
  24. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/schema.d.ts +8 -2
  25. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/schema.js +3 -1
  26. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/schema.js.map +1 -1
  27. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/serializer.js +14 -2
  28. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/serializer.js.map +1 -1
  29. package/build/cjs/extensions/yfm/Checkbox/index.css +5 -9
  30. package/build/cjs/extensions/yfm/Checkbox/index.d.ts +8 -1
  31. package/build/cjs/extensions/yfm/Checkbox/index.js +1 -1
  32. package/build/cjs/extensions/yfm/Checkbox/index.js.map +1 -1
  33. package/build/cjs/extensions/yfm/Checkbox/plugin.d.ts +5 -1
  34. package/build/cjs/extensions/yfm/Checkbox/plugin.js +8 -3
  35. package/build/cjs/extensions/yfm/Checkbox/plugin.js.map +1 -1
  36. package/build/cjs/extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.js +5 -1
  37. package/build/cjs/extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.js.map +1 -1
  38. package/build/cjs/markup/codemirror/search-plugin/plugin.js +10 -0
  39. package/build/cjs/markup/codemirror/search-plugin/plugin.js.map +1 -1
  40. package/build/cjs/modules/search/components/SearchPopup.d.ts +2 -0
  41. package/build/cjs/modules/search/components/SearchPopup.js +11 -2
  42. package/build/cjs/modules/search/components/SearchPopup.js.map +1 -1
  43. package/build/cjs/modules/search/components/hooks/useObserveIntersection.d.ts +10 -0
  44. package/build/cjs/modules/search/components/hooks/useObserveIntersection.js +44 -0
  45. package/build/cjs/modules/search/components/hooks/useObserveIntersection.js.map +1 -0
  46. package/build/cjs/react-utils/hooks/useRAF.d.ts +1 -0
  47. package/build/cjs/react-utils/hooks/useRAF.js +24 -0
  48. package/build/cjs/react-utils/hooks/useRAF.js.map +1 -0
  49. package/build/cjs/react-utils/useSticky.js +3 -12
  50. package/build/cjs/react-utils/useSticky.js.map +1 -1
  51. package/build/cjs/utils/dom.d.ts +3 -0
  52. package/build/cjs/utils/dom.js +32 -0
  53. package/build/cjs/utils/dom.js.map +1 -0
  54. package/build/cjs/version.js +1 -1
  55. package/build/cjs/version.js.map +1 -1
  56. package/build/esm/core/types/serializer.d.ts +5 -0
  57. package/build/esm/core/types/serializer.js.map +1 -1
  58. package/build/esm/extensions/behavior/Search/SearchViewPlugin.js +25 -1
  59. package/build/esm/extensions/behavior/Search/SearchViewPlugin.js.map +1 -1
  60. package/build/esm/extensions/markdown/Breaks/index.d.ts +2 -0
  61. package/build/esm/extensions/markdown/Breaks/index.js +7 -5
  62. package/build/esm/extensions/markdown/Breaks/index.js.map +1 -1
  63. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.d.ts +9 -0
  64. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  65. package/build/esm/extensions/markdown/CodeBlock/const.d.ts +2 -1
  66. package/build/esm/extensions/markdown/CodeBlock/const.js +5 -0
  67. package/build/esm/extensions/markdown/CodeBlock/const.js.map +1 -1
  68. package/build/esm/extensions/markdown/CodeBlock/index.d.ts +1 -2
  69. package/build/esm/extensions/markdown/CodeBlock/index.js +3 -5
  70. package/build/esm/extensions/markdown/CodeBlock/index.js.map +1 -1
  71. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/const.d.ts +3 -0
  72. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/const.js +4 -0
  73. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/const.js.map +1 -1
  74. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/index.d.ts +2 -6
  75. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
  76. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/index.js.map +1 -1
  77. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/parser.js +28 -2
  78. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/parser.js.map +1 -1
  79. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/schema.d.ts +8 -2
  80. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/schema.js +3 -1
  81. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/schema.js.map +1 -1
  82. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/serializer.js +14 -2
  83. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/serializer.js.map +1 -1
  84. package/build/esm/extensions/yfm/Checkbox/index.css +5 -9
  85. package/build/esm/extensions/yfm/Checkbox/index.d.ts +8 -1
  86. package/build/esm/extensions/yfm/Checkbox/index.js +1 -1
  87. package/build/esm/extensions/yfm/Checkbox/index.js.map +1 -1
  88. package/build/esm/extensions/yfm/Checkbox/plugin.d.ts +5 -1
  89. package/build/esm/extensions/yfm/Checkbox/plugin.js +8 -3
  90. package/build/esm/extensions/yfm/Checkbox/plugin.js.map +1 -1
  91. package/build/esm/extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.js +5 -1
  92. package/build/esm/extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.js.map +1 -1
  93. package/build/esm/markup/codemirror/search-plugin/plugin.js +10 -0
  94. package/build/esm/markup/codemirror/search-plugin/plugin.js.map +1 -1
  95. package/build/esm/modules/search/components/SearchPopup.d.ts +2 -0
  96. package/build/esm/modules/search/components/SearchPopup.js +11 -2
  97. package/build/esm/modules/search/components/SearchPopup.js.map +1 -1
  98. package/build/esm/modules/search/components/hooks/useObserveIntersection.d.ts +10 -0
  99. package/build/esm/modules/search/components/hooks/useObserveIntersection.js +41 -0
  100. package/build/esm/modules/search/components/hooks/useObserveIntersection.js.map +1 -0
  101. package/build/esm/react-utils/hooks/useRAF.d.ts +1 -0
  102. package/build/esm/react-utils/hooks/useRAF.js +21 -0
  103. package/build/esm/react-utils/hooks/useRAF.js.map +1 -0
  104. package/build/esm/react-utils/useSticky.js +3 -12
  105. package/build/esm/react-utils/useSticky.js.map +1 -1
  106. package/build/esm/utils/dom.d.ts +3 -0
  107. package/build/esm/utils/dom.js +27 -0
  108. package/build/esm/utils/dom.js.map +1 -0
  109. package/build/esm/version.js +1 -1
  110. package/build/esm/version.js.map +1 -1
  111. package/build/styles.css +5 -9
  112. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type NodeSpec, type Schema} from 'prosemirror-model';\n\nimport type {PlaceholderOptions} from '../../../../utils/placeholder';\n\nimport {CheckboxAttr, CheckboxNode, b, checkboxInputType, checkboxLabelType} from './const';\n\nimport type {CheckboxSpecsOptions} from './index';\n\nconst DEFAULT_LABEL_PLACEHOLDER = 'Checkbox';\n\nexport const getSchemaSpecs = (\n opts?: Pick<CheckboxSpecsOptions, 'checkboxLabelPlaceholder'>,\n placeholder?: PlaceholderOptions,\n): Record<CheckboxNode, NodeSpec> => ({\n [CheckboxNode.Checkbox]: {\n group: 'block checkbox',\n content: `${CheckboxNode.Input} ${CheckboxNode.Label}`,\n selectable: true,\n allowSelection: false,\n attrs: {\n [CheckboxAttr.Class]: {default: b()},\n [CheckboxAttr.Line]: {default: null},\n },\n parseDOM: [\n {\n tag: 'div.checkbox',\n priority: 100,\n getContent(node, schema) {\n if (node instanceof HTMLElement) {\n const input = node.querySelector<HTMLInputElement>('input[type=checkbox]');\n\n if (input && input instanceof HTMLInputElement) {\n const label = findLabelForInput(input);\n return createCheckboxFragment(\n schema,\n input.checked,\n label?.textContent,\n );\n }\n }\n return Fragment.empty;\n },\n },\n {\n tag: 'input[type=checkbox]',\n priority: 50,\n getContent(input, schema) {\n if (input instanceof HTMLInputElement) {\n const label = findLabelForInput(input);\n return createCheckboxFragment(schema, input.checked, label?.textContent);\n }\n return Fragment.empty;\n },\n },\n ],\n toDOM(node) {\n return ['div', node.attrs, 0];\n },\n complex: 'root',\n },\n\n [CheckboxNode.Input]: {\n group: 'block checkbox',\n parseDOM: [],\n attrs: {\n [CheckboxAttr.Type]: {default: 'checkbox'},\n [CheckboxAttr.Id]: {default: null},\n [CheckboxAttr.Checked]: {default: null},\n },\n toDOM(node) {\n return ['div', node.attrs];\n },\n selectable: false,\n allowSelection: false,\n complex: 'leaf',\n },\n\n [CheckboxNode.Label]: {\n content: 'inline*',\n group: 'block checkbox',\n parseDOM: [\n {\n tag: `span[class=\"${b('label')}\"]`,\n getAttrs: (node) => ({\n [CheckboxAttr.For]: (node as Element).getAttribute(CheckboxAttr.For) || '',\n }),\n },\n {\n // input handled by checkbox node parse rule\n // ignore label\n tag: 'input[type=checkbox] ~ label',\n ignore: true,\n consuming: true,\n },\n ],\n attrs: {\n [CheckboxAttr.For]: {default: null},\n },\n escapeText: false,\n placeholder: {\n content:\n placeholder?.[CheckboxNode.Label] ??\n opts?.checkboxLabelPlaceholder ??\n DEFAULT_LABEL_PLACEHOLDER,\n alwaysVisible: true,\n },\n toDOM(node) {\n return ['span', {...node.attrs, class: b('label')}, 0];\n },\n selectable: false,\n allowSelection: false,\n disableGapCursor: true,\n complex: 'leaf',\n },\n});\n\n// fallback for invalid HTML (input without id + label without for)\nfunction findNextSiblingLabel(element: HTMLInputElement): HTMLLabelElement | null {\n const nextSibling = element.nextElementSibling;\n return nextSibling instanceof HTMLLabelElement ? nextSibling : null;\n}\n\nfunction findLabelForInput(element: HTMLInputElement): HTMLLabelElement | null {\n return element.labels?.[0] || findNextSiblingLabel(element);\n}\n\nfunction createCheckboxFragment(\n schema: Schema<any, any>,\n checked: boolean | null,\n labelText: string | null | undefined,\n): Fragment {\n return Fragment.from([\n checkboxInputType(schema).create({[CheckboxAttr.Checked]: checked ? 'true' : null}),\n checkboxLabelType(schema).create(null, labelText ? schema.text(labelText) : null),\n ]);\n}\n"]}
1
+ {"version":3,"file":"schema.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type NodeSpec, type Schema} from 'prosemirror-model';\n\nimport type {PlaceholderOptions} from 'src/utils/placeholder';\n\nimport {CheckboxAttr, CheckboxNode, b, checkboxInputType, checkboxLabelType} from './const';\n\nconst DEFAULT_LABEL_PLACEHOLDER = 'Checkbox';\n\nexport type GetSchemaSpecsOptions = {\n multiline?: boolean;\n /**\n * @deprecated use placeholder option in BehaviorPreset instead.\n */\n checkboxLabelPlaceholder?: NonNullable<NodeSpec['placeholder']>['content'];\n};\n\nexport const getSchemaSpecs = (\n opts?: GetSchemaSpecsOptions,\n placeholder?: PlaceholderOptions,\n): Record<CheckboxNode, NodeSpec> => ({\n [CheckboxNode.Checkbox]: {\n group: 'block checkbox',\n content: `${CheckboxNode.Input} ${CheckboxNode.Label}`,\n selectable: true,\n allowSelection: false,\n attrs: {\n [CheckboxAttr.Class]: {default: b(null, 'checkbox')},\n [CheckboxAttr.Line]: {default: null},\n ...(opts?.multiline ? {[CheckboxAttr.Tight]: {default: null}} : undefined),\n },\n parseDOM: [\n {\n tag: 'div.checkbox',\n priority: 100,\n getContent(node, schema) {\n if (node instanceof HTMLElement) {\n const input = node.querySelector<HTMLInputElement>('input[type=checkbox]');\n\n if (input && input instanceof HTMLInputElement) {\n const label = findLabelForInput(input);\n return createCheckboxFragment(\n schema,\n input.checked,\n label?.textContent,\n );\n }\n }\n return Fragment.empty;\n },\n },\n {\n tag: 'input[type=checkbox]',\n priority: 50,\n getContent(input, schema) {\n if (input instanceof HTMLInputElement) {\n const label = findLabelForInput(input);\n return createCheckboxFragment(schema, input.checked, label?.textContent);\n }\n return Fragment.empty;\n },\n },\n ],\n toDOM(node) {\n return ['div', node.attrs, 0];\n },\n complex: 'root',\n },\n\n [CheckboxNode.Input]: {\n group: 'block checkbox',\n parseDOM: [],\n attrs: {\n [CheckboxAttr.Type]: {default: 'checkbox'},\n [CheckboxAttr.Id]: {default: null},\n [CheckboxAttr.Checked]: {default: null},\n },\n toDOM(node) {\n return ['div', node.attrs];\n },\n selectable: false,\n allowSelection: false,\n complex: 'leaf',\n },\n\n [CheckboxNode.Label]: {\n content: 'inline*',\n group: 'block checkbox',\n parseDOM: [\n {\n tag: `span[class=\"${b('label')}\"]`,\n getAttrs: (node) => ({\n [CheckboxAttr.For]: (node as Element).getAttribute(CheckboxAttr.For) || '',\n }),\n },\n {\n // input handled by checkbox node parse rule\n // ignore label\n tag: 'input[type=checkbox] ~ label',\n ignore: true,\n consuming: true,\n },\n ],\n attrs: {\n [CheckboxAttr.For]: {default: null},\n },\n escapeText: false,\n placeholder: {\n content:\n placeholder?.[CheckboxNode.Label] ??\n opts?.checkboxLabelPlaceholder ??\n DEFAULT_LABEL_PLACEHOLDER,\n alwaysVisible: true,\n },\n toDOM(node) {\n return ['span', {...node.attrs, class: b('label')}, 0];\n },\n selectable: false,\n allowSelection: false,\n disableGapCursor: true,\n canContainBreaks: Boolean(opts?.multiline),\n complex: 'leaf',\n },\n});\n\n// fallback for invalid HTML (input without id + label without for)\nfunction findNextSiblingLabel(element: HTMLInputElement): HTMLLabelElement | null {\n const nextSibling = element.nextElementSibling;\n return nextSibling instanceof HTMLLabelElement ? nextSibling : null;\n}\n\nfunction findLabelForInput(element: HTMLInputElement): HTMLLabelElement | null {\n return element.labels?.[0] || findNextSiblingLabel(element);\n}\n\nfunction createCheckboxFragment(\n schema: Schema<any, any>,\n checked: boolean | null,\n labelText: string | null | undefined,\n): Fragment {\n return Fragment.from([\n checkboxInputType(schema).create({[CheckboxAttr.Checked]: checked ? 'true' : null}),\n checkboxLabelType(schema).create(null, labelText ? schema.text(labelText) : null),\n ]);\n}\n"]}
@@ -4,9 +4,21 @@ exports.serializerTokens = void 0;
4
4
  const placeholder_1 = require("../../../../utils/placeholder.js");
5
5
  const const_1 = require("./const.js");
6
6
  exports.serializerTokens = {
7
- [const_1.CheckboxNode.Checkbox]: (state, node) => {
7
+ [const_1.CheckboxNode.Checkbox]: (state, node, parent, index) => {
8
8
  state.renderInline(node);
9
- state.closeBlock(node);
9
+ // TODO [MAJOR]: remove this check after removing `multiline` option
10
+ if (!node.type.spec.attrs?.[const_1.CheckboxAttr.Tight]) {
11
+ state.closeBlock(node);
12
+ return;
13
+ }
14
+ const tight = node.attrs[const_1.CheckboxAttr.Tight];
15
+ const nextIsCheckbox = parent.maybeChild(index + 1)?.type.name === const_1.CheckboxNode.Checkbox;
16
+ if (tight === false || !nextIsCheckbox) {
17
+ state.closeBlock(node);
18
+ }
19
+ else {
20
+ state.ensureNewLine();
21
+ }
10
22
  },
11
23
  [const_1.CheckboxNode.Input]: (state, node) => {
12
24
  const checked = node.attrs[const_1.CheckboxAttr.Checked] === 'true';
@@ -1 +1 @@
1
- {"version":3,"file":"serializer.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/serializer.ts"],"names":[],"mappings":";;;AACA,kEAAoE;AAEpE,sCAAmD;AAEtC,QAAA,gBAAgB,GAA8C;IACvE,CAAC,oBAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAY,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC;QAC5D,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;QAC1C,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YAC5E,KAAK,CAAC,KAAK,CAAC,IAAA,mCAAqB,EAAC,IAAI,CAAC,CAAC,CAAC;YACzC,OAAO;QACX,CAAC;QAED,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACJ,CAAC","sourcesContent":["import type {SerializerNodeToken} from '../../../../core';\nimport {getPlaceholderContent} from '../../../../utils/placeholder';\n\nimport {CheckboxAttr, CheckboxNode} from './const';\n\nexport const serializerTokens: Record<CheckboxNode, SerializerNodeToken> = {\n [CheckboxNode.Checkbox]: (state, node) => {\n state.renderInline(node);\n state.closeBlock(node);\n },\n\n [CheckboxNode.Input]: (state, node) => {\n const checked = node.attrs[CheckboxAttr.Checked] === 'true';\n state.write(`[${checked ? 'X' : ' '}] `);\n },\n\n [CheckboxNode.Label]: (state, node, _, idx) => {\n if ((!node.content.size || node.textContent.trim().length === 0) && idx !== 0) {\n state.write(getPlaceholderContent(node));\n return;\n }\n\n if (!idx) {\n state.write('[ ] ');\n }\n\n state.renderInline(node);\n },\n};\n"]}
1
+ {"version":3,"file":"serializer.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/serializer.ts"],"names":[],"mappings":";;;AACA,kEAAoE;AAEpE,sCAAmD;AAEtC,QAAA,gBAAgB,GAA8C;IACvE,CAAC,oBAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QACpD,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACvB,OAAO;QACX,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAY,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,oBAAY,CAAC,QAAQ,CAAC;QAEzF,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YACrC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAY,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC;QAC5D,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;QAC1C,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YAC5E,KAAK,CAAC,KAAK,CAAC,IAAA,mCAAqB,EAAC,IAAI,CAAC,CAAC,CAAC;YACzC,OAAO;QACX,CAAC;QAED,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACJ,CAAC","sourcesContent":["import type {SerializerNodeToken} from '../../../../core';\nimport {getPlaceholderContent} from '../../../../utils/placeholder';\n\nimport {CheckboxAttr, CheckboxNode} from './const';\n\nexport const serializerTokens: Record<CheckboxNode, SerializerNodeToken> = {\n [CheckboxNode.Checkbox]: (state, node, parent, index) => {\n state.renderInline(node);\n\n // TODO [MAJOR]: remove this check after removing `multiline` option\n if (!node.type.spec.attrs?.[CheckboxAttr.Tight]) {\n state.closeBlock(node);\n return;\n }\n\n const tight = node.attrs[CheckboxAttr.Tight];\n const nextIsCheckbox = parent.maybeChild(index + 1)?.type.name === CheckboxNode.Checkbox;\n\n if (tight === false || !nextIsCheckbox) {\n state.closeBlock(node);\n } else {\n state.ensureNewLine();\n }\n },\n\n [CheckboxNode.Input]: (state, node) => {\n const checked = node.attrs[CheckboxAttr.Checked] === 'true';\n state.write(`[${checked ? 'X' : ' '}] `);\n },\n\n [CheckboxNode.Label]: (state, node, _, idx) => {\n if ((!node.content.size || node.textContent.trim().length === 0) && idx !== 0) {\n state.write(getPlaceholderContent(node));\n return;\n }\n\n if (!idx) {\n state.write('[ ] ');\n }\n\n state.renderInline(node);\n },\n};\n"]}
@@ -1,12 +1,8 @@
1
- .g-md-checkbox {
1
+ .yfm-editor .g-md-checkbox {
2
2
  display: flex;
3
- align-items: center;
4
- /* Increasing selector specificity to override yfm styles with zero padding */
5
3
  }
6
- .g-md-checkbox__label {
7
- display: inline-block;
8
- }
9
- .g-md-checkbox__input {
10
- /* stylelint-disable declaration-no-important */
11
- margin-right: 5px !important;
4
+ .yfm-editor .g-md-checkbox__input[type=checkbox] {
5
+ top: 3px;
6
+ align-self: flex-start;
7
+ margin-right: 5px;
12
8
  }
@@ -3,7 +3,14 @@ import { type CheckboxSpecsOptions } from "./CheckboxSpecs/index.js";
3
3
  import "./index.css";
4
4
  declare const checkboxAction = "addCheckbox";
5
5
  export { CheckboxAttr, CheckboxNode, checkboxType, checkboxLabelType, checkboxInputType, } from "./CheckboxSpecs/index.js";
6
- export type CheckboxOptions = Pick<CheckboxSpecsOptions, 'checkboxLabelPlaceholder'> & {};
6
+ export type CheckboxOptions = Pick<CheckboxSpecsOptions, 'checkboxLabelPlaceholder'> & {
7
+ /**
8
+ * Allow multiline label in checkboxes.
9
+ * Available with @diplodoc/transform v4.68.0 or higher.
10
+ * @default false
11
+ */
12
+ multiline?: boolean;
13
+ };
7
14
  export declare const Checkbox: ExtensionAuto<CheckboxOptions>;
8
15
  declare global {
9
16
  namespace WysiwygEditor {
@@ -22,7 +22,7 @@ const Checkbox = (builder, opts) => {
22
22
  inputView: () => nodeviews_1.CheckboxInputView.create,
23
23
  });
24
24
  builder
25
- .addPlugin(plugin_1.keymapPlugin, builder.Priority.High)
25
+ .addPlugin(() => (0, plugin_1.keymapPlugin)(opts), builder.Priority.High)
26
26
  .addPlugin(fix_paste_1.fixPastePlugin)
27
27
  .addAction(checkboxAction, () => (0, actions_1.addCheckbox)())
28
28
  .addInputRules(({ schema }) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/yfm/Checkbox/index.ts"],"names":[],"mappings":";;;AACA,6DAAwD;AAExD,4DAAyE;AACzE,0CAAsC;AACtC,8CAA8C;AAC9C,wCAAsC;AACtC,sDAAmD;AACnD,sCAAwD;AAExD,uBAAsB;AAEtB,MAAM,cAAc,GAAG,aAAa,CAAC;AAErC,0DAMyB;AALrB,6GAAA,YAAY,OAAA;AACZ,6GAAA,YAAY,OAAA;AACZ,6GAAA,YAAY,OAAA;AACZ,kHAAA,iBAAiB,OAAA;AACjB,kHAAA,iBAAiB,OAAA;AAKd,MAAM,QAAQ,GAAmC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACtE,OAAO,CAAC,GAAG,CAAC,6BAAa,EAAE;QACvB,GAAG,IAAI;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,6BAAiB,CAAC,MAAM;KAC5C,CAAC,CAAC;IAEH,OAAO;SACF,SAAS,CAAC,qBAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;SAC9C,SAAS,CAAC,0BAAc,CAAC;SACzB,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC;SAC9C,aAAa,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE;YACH,IAAA,0BAAa,EACT,eAAe,EACf,IAAA,oBAAY,EAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,IAAA,yBAAiB,EAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,EAC1E,CAAC,CACJ;SACJ;KACJ,CAAC,CAAC,CAAC;AACZ,CAAC,CAAC;AAnBW,QAAA,QAAQ,YAmBnB","sourcesContent":["import type {Action, ExtensionAuto} from '../../../core';\nimport {nodeInputRule} from '../../../utils/inputrules';\n\nimport {CheckboxSpecs, type CheckboxSpecsOptions} from './CheckboxSpecs';\nimport {addCheckbox} from './actions';\nimport {CheckboxInputView} from './nodeviews';\nimport {keymapPlugin} from './plugin';\nimport {fixPastePlugin} from './plugins/fix-paste';\nimport {checkboxInputType, checkboxType} from './utils';\n\nimport './index.scss';\n\nconst checkboxAction = 'addCheckbox';\n\nexport {\n CheckboxAttr,\n CheckboxNode,\n checkboxType,\n checkboxLabelType,\n checkboxInputType,\n} from './CheckboxSpecs';\n\nexport type CheckboxOptions = Pick<CheckboxSpecsOptions, 'checkboxLabelPlaceholder'> & {};\n\nexport const Checkbox: ExtensionAuto<CheckboxOptions> = (builder, opts) => {\n builder.use(CheckboxSpecs, {\n ...opts,\n inputView: () => CheckboxInputView.create,\n });\n\n builder\n .addPlugin(keymapPlugin, builder.Priority.High)\n .addPlugin(fixPastePlugin)\n .addAction(checkboxAction, () => addCheckbox())\n .addInputRules(({schema}) => ({\n rules: [\n nodeInputRule(\n /^\\[(\\s?)\\]\\s$/,\n checkboxType(schema).createAndFill({}, checkboxInputType(schema).create()),\n 2,\n ),\n ],\n }));\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [checkboxAction]: Action;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/yfm/Checkbox/index.ts"],"names":[],"mappings":";;;AACA,6DAAwD;AAExD,4DAAyE;AACzE,0CAAsC;AACtC,8CAA8C;AAC9C,wCAAsC;AACtC,sDAAmD;AACnD,sCAAwD;AAExD,uBAAsB;AAEtB,MAAM,cAAc,GAAG,aAAa,CAAC;AAErC,0DAMyB;AALrB,6GAAA,YAAY,OAAA;AACZ,6GAAA,YAAY,OAAA;AACZ,6GAAA,YAAY,OAAA;AACZ,kHAAA,iBAAiB,OAAA;AACjB,kHAAA,iBAAiB,OAAA;AAad,MAAM,QAAQ,GAAmC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACtE,OAAO,CAAC,GAAG,CAAC,6BAAa,EAAE;QACvB,GAAG,IAAI;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,6BAAiB,CAAC,MAAM;KAC5C,CAAC,CAAC;IAEH,OAAO;SACF,SAAS,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAY,EAAC,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;SAC1D,SAAS,CAAC,0BAAc,CAAC;SACzB,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC;SAC9C,aAAa,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE;YACH,IAAA,0BAAa,EACT,eAAe,EACf,IAAA,oBAAY,EAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,IAAA,yBAAiB,EAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,EAC1E,CAAC,CACJ;SACJ;KACJ,CAAC,CAAC,CAAC;AACZ,CAAC,CAAC;AAnBW,QAAA,QAAQ,YAmBnB","sourcesContent":["import type {Action, ExtensionAuto} from '../../../core';\nimport {nodeInputRule} from '../../../utils/inputrules';\n\nimport {CheckboxSpecs, type CheckboxSpecsOptions} from './CheckboxSpecs';\nimport {addCheckbox} from './actions';\nimport {CheckboxInputView} from './nodeviews';\nimport {keymapPlugin} from './plugin';\nimport {fixPastePlugin} from './plugins/fix-paste';\nimport {checkboxInputType, checkboxType} from './utils';\n\nimport './index.scss';\n\nconst checkboxAction = 'addCheckbox';\n\nexport {\n CheckboxAttr,\n CheckboxNode,\n checkboxType,\n checkboxLabelType,\n checkboxInputType,\n} from './CheckboxSpecs';\n\nexport type CheckboxOptions = Pick<CheckboxSpecsOptions, 'checkboxLabelPlaceholder'> & {\n /**\n * Allow multiline label in checkboxes.\n * Available with @diplodoc/transform v4.68.0 or higher.\n * @default false\n */\n // TODO [MAJOR]: enable by default and remove option\n multiline?: boolean;\n};\n\nexport const Checkbox: ExtensionAuto<CheckboxOptions> = (builder, opts) => {\n builder.use(CheckboxSpecs, {\n ...opts,\n inputView: () => CheckboxInputView.create,\n });\n\n builder\n .addPlugin(() => keymapPlugin(opts), builder.Priority.High)\n .addPlugin(fixPastePlugin)\n .addAction(checkboxAction, () => addCheckbox())\n .addInputRules(({schema}) => ({\n rules: [\n nodeInputRule(\n /^\\[(\\s?)\\]\\s$/,\n checkboxType(schema).createAndFill({}, checkboxInputType(schema).create()),\n 2,\n ),\n ],\n }));\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [checkboxAction]: Action;\n }\n }\n}\n"]}
@@ -1,3 +1,7 @@
1
1
  import { type Command } from 'prosemirror-state';
2
2
  export declare const splitCheckbox: (replaceWithParagraph?: boolean) => Command;
3
- export declare const keymapPlugin: () => import("prosemirror-state").Plugin<any>;
3
+ type KeymapPluginOptions = {
4
+ multiline?: boolean;
5
+ };
6
+ export declare const keymapPlugin: (props: KeymapPluginOptions) => import("prosemirror-state").Plugin<any>;
7
+ export {};
@@ -6,8 +6,9 @@ const prosemirror_model_1 = require("prosemirror-model");
6
6
  const prosemirror_state_1 = require("prosemirror-state");
7
7
  // @ts-ignore // TODO: fix cjs build
8
8
  const prosemirror_utils_1 = require("prosemirror-utils");
9
- const selection_1 = require("../../../utils/selection.js");
10
9
  const BaseSchema_1 = require("../../base/BaseSchema/index.js");
10
+ const Breaks_1 = require("../../markdown/Breaks/index.js");
11
+ const selection_1 = require("../../../utils/selection.js");
11
12
  const utils_1 = require("./utils.js");
12
13
  const splitCheckbox = (replaceWithParagraph) => (state, dispatch) => {
13
14
  const { $from, $to } = state.selection;
@@ -34,6 +35,10 @@ const splitCheckbox = (replaceWithParagraph) => (state, dispatch) => {
34
35
  tr.insert($from.after(), [node]);
35
36
  tr.replace(label.start + $from.parentOffset, label.pos + label.node.nodeSize);
36
37
  tr.setSelection(new prosemirror_state_1.TextSelection(tr.doc.resolve(tr.selection.$from.after() + (replaceWithParagraph ? 2 : 4))));
38
+ // remove break before cursor
39
+ if ((0, Breaks_1.isBreakNode)($from.nodeBefore)) {
40
+ tr.replaceWith($from.pos - 1, $from.pos, prosemirror_model_1.Fragment.empty);
41
+ }
37
42
  dispatch?.(tr);
38
43
  return true;
39
44
  }
@@ -58,10 +63,10 @@ const removeCheckbox = (state, dispatch) => {
58
63
  }
59
64
  return false;
60
65
  };
61
- const keymapPlugin = () => (0, prosemirror_keymap_1.keymap)({
66
+ const keymapPlugin = (props) => (0, prosemirror_keymap_1.keymap)({
62
67
  Enter: (0, exports.splitCheckbox)(),
63
68
  Backspace: removeCheckbox,
64
- 'Shift-Enter': (0, exports.splitCheckbox)(true),
69
+ ...(props.multiline ? undefined : { 'Shift-Enter': (0, exports.splitCheckbox)(true) }),
65
70
  });
66
71
  exports.keymapPlugin = keymapPlugin;
67
72
  //# sourceMappingURL=plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"../../../../../src","sources":["extensions/yfm/Checkbox/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {keymap} from 'prosemirror-keymap';\nimport {Fragment} from 'prosemirror-model';\nimport {type Command, TextSelection} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findParentNodeOfType} from 'prosemirror-utils';\n\nimport {isWholeSelection} from '../../../utils/selection';\nimport {pType} from '../../base/BaseSchema';\n\nimport {checkboxInputType, checkboxLabelType, checkboxType} from './utils';\n\nexport const splitCheckbox: (replaceWithParagraph?: boolean) => Command =\n (replaceWithParagraph) => (state, dispatch) => {\n const {$from, $to} = state.selection;\n const {schema} = state;\n const label = findParentNodeOfType(checkboxLabelType(schema))(state.selection);\n\n if (!label) return false;\n\n const checkbox = findParentNodeOfType(checkboxType(schema))(state.selection);\n\n if (label.node.content.size === 0 && checkbox) {\n dispatch?.(\n state.tr\n .replaceWith(\n checkbox.pos,\n checkbox.pos + checkbox.node.nodeSize,\n pType(schema).create(),\n )\n .scrollIntoView(),\n );\n\n return true;\n }\n\n if ($from.pos === $to.pos) {\n const {tr} = state;\n\n const content = Fragment.from($from.parent.cut($from.parentOffset).content);\n\n const node = replaceWithParagraph\n ? pType(state.schema).create({}, content)\n : checkboxType(schema).create({}, [\n checkboxInputType(schema).create(),\n checkboxLabelType(schema).create({}, content),\n ]);\n\n tr.insert($from.after(), [node]);\n\n tr.replace(label.start + $from.parentOffset, label.pos + label.node.nodeSize);\n tr.setSelection(\n new TextSelection(\n tr.doc.resolve(tr.selection.$from.after() + (replaceWithParagraph ? 2 : 4)),\n ),\n );\n dispatch?.(tr);\n\n return true;\n }\n\n return false;\n };\n\nconst removeCheckbox: Command = (state, dispatch) => {\n const label = findParentNodeOfType(checkboxLabelType(state.schema))(state.selection);\n const checkbox = findParentNodeOfType(checkboxType(state.schema))(state.selection);\n\n const {selection} = state;\n const {from, to} = selection;\n\n if (!label || !checkbox) {\n return false;\n }\n\n const idx = from - label.pos - 2;\n\n if (idx < 0 && from === to && !isWholeSelection(selection)) {\n const {tr} = state;\n dispatch?.(\n tr\n .replaceWith(\n checkbox.pos,\n checkbox.pos + checkbox.node.nodeSize,\n pType(state.schema).create(null, label.node.content),\n )\n .setSelection(new TextSelection(tr.doc.resolve(state.selection.from - 2))),\n );\n return true;\n }\n\n return false;\n};\n\nexport const keymapPlugin = () =>\n keymap({\n Enter: splitCheckbox(),\n Backspace: removeCheckbox,\n 'Shift-Enter': splitCheckbox(true),\n });\n"]}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"../../../../../src","sources":["extensions/yfm/Checkbox/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {keymap} from 'prosemirror-keymap';\nimport {Fragment} from 'prosemirror-model';\nimport {type Command, TextSelection} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findParentNodeOfType} from 'prosemirror-utils';\n\nimport {pType} from 'src/extensions/base/BaseSchema';\nimport {isBreakNode} from 'src/extensions/markdown/Breaks';\nimport {isWholeSelection} from 'src/utils/selection';\n\nimport {checkboxInputType, checkboxLabelType, checkboxType} from './utils';\n\nexport const splitCheckbox: (replaceWithParagraph?: boolean) => Command =\n (replaceWithParagraph) => (state, dispatch) => {\n const {$from, $to} = state.selection;\n const {schema} = state;\n const label = findParentNodeOfType(checkboxLabelType(schema))(state.selection);\n\n if (!label) return false;\n\n const checkbox = findParentNodeOfType(checkboxType(schema))(state.selection);\n\n if (label.node.content.size === 0 && checkbox) {\n dispatch?.(\n state.tr\n .replaceWith(\n checkbox.pos,\n checkbox.pos + checkbox.node.nodeSize,\n pType(schema).create(),\n )\n .scrollIntoView(),\n );\n\n return true;\n }\n\n if ($from.pos === $to.pos) {\n const {tr} = state;\n\n const content = Fragment.from($from.parent.cut($from.parentOffset).content);\n\n const node = replaceWithParagraph\n ? pType(state.schema).create({}, content)\n : checkboxType(schema).create({}, [\n checkboxInputType(schema).create(),\n checkboxLabelType(schema).create({}, content),\n ]);\n\n tr.insert($from.after(), [node]);\n\n tr.replace(label.start + $from.parentOffset, label.pos + label.node.nodeSize);\n tr.setSelection(\n new TextSelection(\n tr.doc.resolve(tr.selection.$from.after() + (replaceWithParagraph ? 2 : 4)),\n ),\n );\n\n // remove break before cursor\n if (isBreakNode($from.nodeBefore)) {\n tr.replaceWith($from.pos - 1, $from.pos, Fragment.empty);\n }\n\n dispatch?.(tr);\n\n return true;\n }\n\n return false;\n };\n\nconst removeCheckbox: Command = (state, dispatch) => {\n const label = findParentNodeOfType(checkboxLabelType(state.schema))(state.selection);\n const checkbox = findParentNodeOfType(checkboxType(state.schema))(state.selection);\n\n const {selection} = state;\n const {from, to} = selection;\n\n if (!label || !checkbox) {\n return false;\n }\n\n const idx = from - label.pos - 2;\n\n if (idx < 0 && from === to && !isWholeSelection(selection)) {\n const {tr} = state;\n dispatch?.(\n tr\n .replaceWith(\n checkbox.pos,\n checkbox.pos + checkbox.node.nodeSize,\n pType(state.schema).create(null, label.node.content),\n )\n .setSelection(new TextSelection(tr.doc.resolve(state.selection.from - 2))),\n );\n return true;\n }\n\n return false;\n};\n\ntype KeymapPluginOptions = {\n multiline?: boolean;\n};\n\nexport const keymapPlugin = (props: KeymapPluginOptions) =>\n keymap({\n Enter: splitCheckbox(),\n Backspace: removeCheckbox,\n ...(props.multiline ? undefined : {'Shift-Enter': splitCheckbox(true)}),\n });\n"]}
@@ -74,6 +74,10 @@ class EmojiHandler {
74
74
  }
75
75
  onEnter(action) {
76
76
  this.updateState(action);
77
+ const emojiDef = this._emojiCarousel?.currentItem;
78
+ if (!emojiDef) {
79
+ return false;
80
+ }
77
81
  this.select();
78
82
  return true;
79
83
  }
@@ -182,7 +186,7 @@ function filterEmojis(defs, text) {
182
186
  }
183
187
  return byShortcuts.concat(byName);
184
188
  }
185
- const CHARS_TO_HIDE = 4;
189
+ const CHARS_TO_HIDE = 1;
186
190
  function needToHide(defs, text) {
187
191
  let iter = 1;
188
192
  do {
@@ -1 +1 @@
1
- {"version":3,"file":"EmojiHandler.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Schema} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {AutocompletePopupCloser} from '../../../../utils/autocomplete-popup';\nimport {ArrayCarousel} from '../../../../utils/carousel';\nimport {type RendererItem, getReactRendererFromState} from '../../../behavior';\nimport {\n type AutocompleteAction,\n AutocompleteActionKind,\n type AutocompleteHandler,\n closeAutocomplete,\n getAutocompleteState,\n} from '../../../behavior/Autocomplete';\nimport {EmojiConsts} from '../EmojiSpecs';\n\nimport {type EmojiSuggestComponentProps, render} from './EmojiSuggestComponent';\nimport type {EmojiDef} from './types';\nimport {findDecoElem} from './utils';\n\nconst emptyArray = new Array<string>(0);\n\nexport type EmojiHandlerParams = {\n defs: Record<string, string>;\n shortcuts?: Partial<Record<string, string | string[]>>;\n};\n\nexport class EmojiHandler implements AutocompleteHandler {\n private readonly _emojis: readonly EmojiDef[];\n private _emojiCarousel?: ArrayCarousel<EmojiDef>;\n\n private _view?: EditorView;\n private _anchor: Element | null = null;\n private _popupCloser?: AutocompletePopupCloser;\n\n private _suggestProps?: EmojiSuggestComponentProps;\n private _suggestRenderItem?: RendererItem;\n\n constructor({defs, shortcuts = {}}: EmojiHandlerParams) {\n this._emojis = Object.entries(defs).map(([name, symbol]) => {\n const def: EmojiDef = {symbol, origName: name, name: name.toLowerCase()};\n const short = shortcuts[name];\n if (short) {\n def.origShortcuts = emptyArray.concat(short);\n def.shortcuts = def.origShortcuts.map((val) =>\n val.startsWith(':') ? val.slice(1) : val,\n );\n }\n return def;\n });\n }\n\n onOpen(action: AutocompleteAction): boolean {\n this.findAnchor();\n if (!this._anchor) {\n this.closeAutocomplete(action.view);\n return true;\n }\n\n this._popupCloser = new AutocompletePopupCloser(action.view);\n this.updateState(action);\n this.filterActions();\n this.render();\n\n return true;\n }\n\n onFilter(action: AutocompleteAction): boolean {\n if (action.filter?.endsWith(' ')) {\n this.closeAutocomplete(action.view);\n return true;\n }\n\n this.updateState(action);\n\n const needToClose = this.filterActions(action.filter?.trim());\n this.render();\n\n if (needToClose) {\n this.closeAutocomplete(action.view);\n }\n\n return true;\n }\n\n onArrow(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n if (!this._emojiCarousel) return false;\n\n switch (action.kind) {\n case AutocompleteActionKind.up: {\n this._emojiCarousel.prev();\n break;\n }\n case AutocompleteActionKind.down: {\n this._emojiCarousel.next();\n break;\n }\n default:\n return false;\n }\n\n this.render();\n\n return true;\n }\n\n onEnter(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n this.select();\n\n return true;\n }\n\n onClose(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n this.clear();\n\n return true;\n }\n\n onDestroy(): void {\n this.clear();\n }\n\n private closeAutocomplete(view: EditorView) {\n setTimeout(() => {\n closeAutocomplete(view);\n });\n }\n\n private select() {\n const {_view: view} = this;\n if (!view) return;\n\n const emojiDef = this._emojiCarousel?.currentItem;\n if (!emojiDef) return;\n\n const autocompleteState = getAutocompleteState(view.state);\n if (!autocompleteState || !autocompleteState.active) return;\n\n const {range} = autocompleteState;\n const {tr, schema} = view.state;\n view.dispatch(\n tr.replaceWith(range.from, range.to, createEmoji(schema, emojiDef)).scrollIntoView(),\n );\n view.focus();\n }\n\n private filterActions(inputText?: string): boolean {\n const currentItem = this._emojiCarousel?.currentItem;\n\n let filteredEmojis = this._emojis;\n let needToClose = false;\n\n if (inputText) {\n filteredEmojis = filterEmojis(filteredEmojis, inputText);\n needToClose = !filteredEmojis.length && needToHide(this._emojis, inputText);\n }\n\n this._emojiCarousel = new ArrayCarousel(filteredEmojis);\n\n if (currentItem) {\n const newIndex = this._emojiCarousel.array.findIndex((item) => item === currentItem);\n if (newIndex !== -1) {\n this._emojiCarousel.currentIndex = newIndex;\n }\n }\n\n return needToClose;\n }\n\n private render() {\n this.findAnchor();\n const viewItems = this._emojiCarousel?.array ?? [];\n this._suggestProps = {\n anchorElement: this._anchor,\n currentIndex: this._emojiCarousel?.currentIndex,\n items: viewItems,\n onClick: this.onItemClick,\n onOpenChange: this._popupCloser?.popupOpenChangeHandler,\n };\n this._suggestRenderItem = this._suggestRenderItem ?? this.createMenuRenderItem();\n this._suggestRenderItem.rerender();\n }\n\n private onItemClick = (index: number) => {\n if (this._emojiCarousel) {\n this._emojiCarousel.currentIndex = index;\n this.select();\n }\n this._view?.focus();\n };\n\n private updateState({view}: AutocompleteAction) {\n this._view = view;\n }\n\n private clear() {\n this._view = undefined;\n this._anchor = null;\n this._emojiCarousel = undefined;\n this._popupCloser?.cancelTimer();\n this._popupCloser = undefined;\n this._suggestProps = undefined;\n this._suggestRenderItem?.remove();\n this._suggestRenderItem = undefined;\n }\n\n private createMenuRenderItem(): RendererItem {\n return getReactRendererFromState(this._view!.state).createItem('emoji_suggest', () =>\n this._suggestProps ? render(this._suggestProps) : null,\n );\n }\n\n private findAnchor() {\n this._anchor = findDecoElem(this._view?.dom);\n }\n}\n\nfunction createEmoji(schema: Schema, def: EmojiDef) {\n return EmojiConsts.nodeType(schema).create(\n {[EmojiConsts.NodeAttrs.Markup]: def.name},\n schema.text(def.symbol),\n );\n}\n\nfunction filterEmojis(defs: readonly EmojiDef[], text: string): readonly EmojiDef[] {\n if (!text) return defs;\n const textLowerCase = text.toLowerCase();\n\n const byShortcuts: EmojiDef[] = [];\n const byName: EmojiDef[] = [];\n for (const emoji of defs) {\n if (emoji.shortcuts?.some((val) => val.startsWith(text))) {\n byShortcuts.push(emoji);\n } else if (emoji.name.startsWith(textLowerCase)) {\n byName.push(emoji);\n }\n }\n return byShortcuts.concat(byName);\n}\n\nconst CHARS_TO_HIDE = 4;\nfunction needToHide(defs: readonly EmojiDef[], text: string): boolean {\n let iter = 1;\n do {\n const prevInput = text.slice(0, text.length - iter);\n const prevActions = filterEmojis(defs, prevInput);\n if (prevActions.length) break;\n iter++;\n } while (iter < text.length && iter < CHARS_TO_HIDE);\n return iter >= CHARS_TO_HIDE;\n}\n"]}
1
+ {"version":3,"file":"EmojiHandler.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Emoji/EmojiSuggest/EmojiHandler.ts"],"names":[],"mappings":";;;AAGA,gFAA6E;AAC7E,kEAAyD;AACzD,yDAA+E;AAC/E,0EAMwC;AACxC,uDAA0C;AAE1C,sEAAgF;AAEhF,sCAAqC;AAErC,MAAM,UAAU,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;AAOxC,MAAa,YAAY;IACJ,OAAO,CAAsB;IACtC,cAAc,CAA2B;IAEzC,KAAK,CAAc;IACnB,OAAO,GAAmB,IAAI,CAAC;IAC/B,YAAY,CAA2B;IAEvC,aAAa,CAA8B;IAC3C,kBAAkB,CAAgB;IAE1C,YAAY,EAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAqB;QAClD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YACvD,MAAM,GAAG,GAAa,EAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAC,CAAC;YACzE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,KAAK,EAAE,CAAC;gBACR,GAAG,CAAC,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC7C,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC1C,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAC3C,CAAC;YACN,CAAC;YACD,OAAO,GAAG,CAAC;QACf,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,MAA0B;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,4CAAuB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,EAAE,CAAC;QAEd,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,QAAQ,CAAC,MAA0B;QAC/B,IAAI,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEzB,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;QAEd,IAAI,WAAW,EAAE,CAAC;YACd,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,MAA0B;QAC9B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEzB,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QAEvC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,qCAAsB,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC7B,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC3B,MAAM;YACV,CAAC;YACD,KAAK,qCAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC3B,MAAM;YACV,CAAC;YACD;gBACI,OAAO,KAAK,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;QAEd,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,MAA0B;QAC9B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,MAA0B;QAC9B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEzB,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,SAAS;QACL,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,IAAgB;QACtC,UAAU,CAAC,GAAG,EAAE;YACZ,IAAA,gCAAiB,EAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,MAAM;QACV,MAAM,EAAC,KAAK,EAAE,IAAI,EAAC,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;QAClD,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,iBAAiB,GAAG,IAAA,mCAAoB,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,iBAAiB,IAAI,CAAC,iBAAiB,CAAC,MAAM;YAAE,OAAO;QAE5D,MAAM,EAAC,KAAK,EAAC,GAAG,iBAAiB,CAAC;QAClC,MAAM,EAAC,EAAE,EAAE,MAAM,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QAChC,IAAI,CAAC,QAAQ,CACT,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,cAAc,EAAE,CACvF,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAEO,aAAa,CAAC,SAAkB;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;QAErD,IAAI,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC;QAClC,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,IAAI,SAAS,EAAE,CAAC;YACZ,cAAc,GAAG,YAAY,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YACzD,WAAW,GAAG,CAAC,cAAc,CAAC,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,wBAAa,CAAC,cAAc,CAAC,CAAC;QAExD,IAAI,WAAW,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACrF,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,IAAI,CAAC,cAAc,CAAC,YAAY,GAAG,QAAQ,CAAC;YAChD,CAAC;QACL,CAAC;QAED,OAAO,WAAW,CAAC;IACvB,CAAC;IAEO,MAAM;QACV,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,aAAa,GAAG;YACjB,aAAa,EAAE,IAAI,CAAC,OAAO;YAC3B,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY;YAC/C,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,IAAI,CAAC,WAAW;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,sBAAsB;SAC1D,CAAC;QACF,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACjF,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC;IACvC,CAAC;IAEO,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE;QACpC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,cAAc,CAAC,YAAY,GAAG,KAAK,CAAC;YACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC;IAEM,WAAW,CAAC,EAAC,IAAI,EAAqB;QAC1C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAEO,KAAK;QACT,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;IACxC,CAAC;IAEO,oBAAoB;QACxB,OAAO,IAAA,oCAAyB,EAAC,IAAI,CAAC,KAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,eAAe,EAAE,GAAG,EAAE,CACjF,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAA,8BAAM,EAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CACzD,CAAC;IACN,CAAC;IAEO,UAAU;QACd,IAAI,CAAC,OAAO,GAAG,IAAA,oBAAY,EAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;CACJ;AAtMD,oCAsMC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,GAAa;IAC9C,OAAO,wBAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CACtC,EAAC,CAAC,wBAAW,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,EAAC,EAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAC1B,CAAC;AACN,CAAC;AAED,SAAS,YAAY,CAAC,IAAyB,EAAE,IAAY;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAEzC,MAAM,WAAW,GAAe,EAAE,CAAC;IACnC,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvD,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACL,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,SAAS,UAAU,CAAC,IAAyB,EAAE,IAAY;IACvD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,GAAG,CAAC;QACA,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAClD,IAAI,WAAW,CAAC,MAAM;YAAE,MAAM;QAC9B,IAAI,EAAE,CAAC;IACX,CAAC,QAAQ,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,GAAG,aAAa,EAAE;IACrD,OAAO,IAAI,IAAI,aAAa,CAAC;AACjC,CAAC","sourcesContent":["import type {Schema} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {AutocompletePopupCloser} from '../../../../utils/autocomplete-popup';\nimport {ArrayCarousel} from '../../../../utils/carousel';\nimport {type RendererItem, getReactRendererFromState} from '../../../behavior';\nimport {\n type AutocompleteAction,\n AutocompleteActionKind,\n type AutocompleteHandler,\n closeAutocomplete,\n getAutocompleteState,\n} from '../../../behavior/Autocomplete';\nimport {EmojiConsts} from '../EmojiSpecs';\n\nimport {type EmojiSuggestComponentProps, render} from './EmojiSuggestComponent';\nimport type {EmojiDef} from './types';\nimport {findDecoElem} from './utils';\n\nconst emptyArray = new Array<string>(0);\n\nexport type EmojiHandlerParams = {\n defs: Record<string, string>;\n shortcuts?: Partial<Record<string, string | string[]>>;\n};\n\nexport class EmojiHandler implements AutocompleteHandler {\n private readonly _emojis: readonly EmojiDef[];\n private _emojiCarousel?: ArrayCarousel<EmojiDef>;\n\n private _view?: EditorView;\n private _anchor: Element | null = null;\n private _popupCloser?: AutocompletePopupCloser;\n\n private _suggestProps?: EmojiSuggestComponentProps;\n private _suggestRenderItem?: RendererItem;\n\n constructor({defs, shortcuts = {}}: EmojiHandlerParams) {\n this._emojis = Object.entries(defs).map(([name, symbol]) => {\n const def: EmojiDef = {symbol, origName: name, name: name.toLowerCase()};\n const short = shortcuts[name];\n if (short) {\n def.origShortcuts = emptyArray.concat(short);\n def.shortcuts = def.origShortcuts.map((val) =>\n val.startsWith(':') ? val.slice(1) : val,\n );\n }\n return def;\n });\n }\n\n onOpen(action: AutocompleteAction): boolean {\n this.findAnchor();\n if (!this._anchor) {\n this.closeAutocomplete(action.view);\n return true;\n }\n\n this._popupCloser = new AutocompletePopupCloser(action.view);\n this.updateState(action);\n this.filterActions();\n this.render();\n\n return true;\n }\n\n onFilter(action: AutocompleteAction): boolean {\n if (action.filter?.endsWith(' ')) {\n this.closeAutocomplete(action.view);\n return true;\n }\n\n this.updateState(action);\n\n const needToClose = this.filterActions(action.filter?.trim());\n this.render();\n\n if (needToClose) {\n this.closeAutocomplete(action.view);\n }\n\n return true;\n }\n\n onArrow(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n if (!this._emojiCarousel) return false;\n\n switch (action.kind) {\n case AutocompleteActionKind.up: {\n this._emojiCarousel.prev();\n break;\n }\n case AutocompleteActionKind.down: {\n this._emojiCarousel.next();\n break;\n }\n default:\n return false;\n }\n\n this.render();\n\n return true;\n }\n\n onEnter(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n const emojiDef = this._emojiCarousel?.currentItem;\n if (!emojiDef) {\n return false;\n }\n\n this.select();\n return true;\n }\n\n onClose(action: AutocompleteAction): boolean {\n this.updateState(action);\n\n this.clear();\n\n return true;\n }\n\n onDestroy(): void {\n this.clear();\n }\n\n private closeAutocomplete(view: EditorView) {\n setTimeout(() => {\n closeAutocomplete(view);\n });\n }\n\n private select() {\n const {_view: view} = this;\n if (!view) return;\n\n const emojiDef = this._emojiCarousel?.currentItem;\n if (!emojiDef) return;\n\n const autocompleteState = getAutocompleteState(view.state);\n if (!autocompleteState || !autocompleteState.active) return;\n\n const {range} = autocompleteState;\n const {tr, schema} = view.state;\n view.dispatch(\n tr.replaceWith(range.from, range.to, createEmoji(schema, emojiDef)).scrollIntoView(),\n );\n view.focus();\n }\n\n private filterActions(inputText?: string): boolean {\n const currentItem = this._emojiCarousel?.currentItem;\n\n let filteredEmojis = this._emojis;\n let needToClose = false;\n\n if (inputText) {\n filteredEmojis = filterEmojis(filteredEmojis, inputText);\n needToClose = !filteredEmojis.length && needToHide(this._emojis, inputText);\n }\n\n this._emojiCarousel = new ArrayCarousel(filteredEmojis);\n\n if (currentItem) {\n const newIndex = this._emojiCarousel.array.findIndex((item) => item === currentItem);\n if (newIndex !== -1) {\n this._emojiCarousel.currentIndex = newIndex;\n }\n }\n\n return needToClose;\n }\n\n private render() {\n this.findAnchor();\n const viewItems = this._emojiCarousel?.array ?? [];\n this._suggestProps = {\n anchorElement: this._anchor,\n currentIndex: this._emojiCarousel?.currentIndex,\n items: viewItems,\n onClick: this.onItemClick,\n onOpenChange: this._popupCloser?.popupOpenChangeHandler,\n };\n this._suggestRenderItem = this._suggestRenderItem ?? this.createMenuRenderItem();\n this._suggestRenderItem.rerender();\n }\n\n private onItemClick = (index: number) => {\n if (this._emojiCarousel) {\n this._emojiCarousel.currentIndex = index;\n this.select();\n }\n this._view?.focus();\n };\n\n private updateState({view}: AutocompleteAction) {\n this._view = view;\n }\n\n private clear() {\n this._view = undefined;\n this._anchor = null;\n this._emojiCarousel = undefined;\n this._popupCloser?.cancelTimer();\n this._popupCloser = undefined;\n this._suggestProps = undefined;\n this._suggestRenderItem?.remove();\n this._suggestRenderItem = undefined;\n }\n\n private createMenuRenderItem(): RendererItem {\n return getReactRendererFromState(this._view!.state).createItem('emoji_suggest', () =>\n this._suggestProps ? render(this._suggestProps) : null,\n );\n }\n\n private findAnchor() {\n this._anchor = findDecoElem(this._view?.dom);\n }\n}\n\nfunction createEmoji(schema: Schema, def: EmojiDef) {\n return EmojiConsts.nodeType(schema).create(\n {[EmojiConsts.NodeAttrs.Markup]: def.name},\n schema.text(def.symbol),\n );\n}\n\nfunction filterEmojis(defs: readonly EmojiDef[], text: string): readonly EmojiDef[] {\n if (!text) return defs;\n const textLowerCase = text.toLowerCase();\n\n const byShortcuts: EmojiDef[] = [];\n const byName: EmojiDef[] = [];\n for (const emoji of defs) {\n if (emoji.shortcuts?.some((val) => val.startsWith(text))) {\n byShortcuts.push(emoji);\n } else if (emoji.name.startsWith(textLowerCase)) {\n byName.push(emoji);\n }\n }\n return byShortcuts.concat(byName);\n}\n\nconst CHARS_TO_HIDE = 1;\nfunction needToHide(defs: readonly EmojiDef[], text: string): boolean {\n let iter = 1;\n do {\n const prevInput = text.slice(0, text.length - iter);\n const prevActions = filterEmojis(defs, prevInput);\n if (prevActions.length) break;\n iter++;\n } while (iter < text.length && iter < CHARS_TO_HIDE);\n return iter >= CHARS_TO_HIDE;\n}\n"]}
@@ -59,6 +59,16 @@ const SearchPanelPlugin = (params) => view_1.ViewPlugin.fromClass(class {
59
59
  onSearchPrev: this.handleSearchPrev,
60
60
  onReplaceNext: this.handleReplaceNext,
61
61
  onReplaceAll: this.handleReplaceAll,
62
+ intersectionTracking: {
63
+ container: this.view.contentDOM,
64
+ selector: '.cm-searchMatch-selected',
65
+ observerOptions: {
66
+ childList: true,
67
+ subtree: true,
68
+ attributes: true,
69
+ attributeFilter: ['class'],
70
+ },
71
+ },
62
72
  });
63
73
  });
64
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"../../../../../src","sources":["markup/codemirror/search-plugin/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SearchQuery,\n closeSearchPanel,\n findNext,\n findPrevious,\n getSearchQuery,\n replaceAll,\n replaceNext,\n search,\n searchKeymap,\n searchPanelOpen,\n setSearchQuery,\n} from '@codemirror/search';\nimport {\n type EditorView,\n type PluginValue,\n ViewPlugin,\n type ViewUpdate,\n keymap,\n} from '@codemirror/view';\n\nimport type {MarkdownEditorMode} from 'src/bundle';\nimport type {EventMap} from 'src/bundle/Editor';\nimport type {RendererItem} from 'src/extensions';\nimport {renderSearchPopup} from 'src/modules/search';\nimport type {Receiver} from 'src/utils';\n\nimport {ReactRendererFacet} from '../react-facet';\n\nimport {searchTheme} from './theme';\n\ntype SearchQueryConfig = ConstructorParameters<typeof SearchQuery>[0];\n\nexport interface SearchPanelPluginParams {\n anchorSelector: string;\n inputDelay?: number;\n receiver?: Receiver<EventMap>;\n}\n\nexport const SearchPanelPlugin = (params: SearchPanelPluginParams) =>\n ViewPlugin.fromClass(\n class implements PluginValue {\n readonly view: EditorView;\n readonly params: SearchPanelPluginParams;\n\n renderer: RendererItem;\n receiver: Receiver<EventMap> | undefined;\n\n panelOpened: boolean;\n searchState: SearchQuery | null;\n\n constructor(view: EditorView) {\n this.view = view;\n this.params = params;\n this.receiver = params.receiver;\n\n this.panelOpened = searchPanelOpen(view.state);\n this.searchState = getSearchQuery(view.state);\n this.renderer = this.createRenderer();\n\n this.handleClose = this.handleClose.bind(this);\n this.handleChange = this.handleChange.bind(this);\n this.handleSearchNext = this.handleSearchNext.bind(this);\n this.handleSearchPrev = this.handleSearchPrev.bind(this);\n this.handleReplaceNext = this.handleReplaceNext.bind(this);\n this.handleReplaceAll = this.handleReplaceAll.bind(this);\n this.handleEditorModeChange = this.handleEditorModeChange.bind(this);\n\n this.receiver?.on('change-editor-mode', this.handleEditorModeChange);\n }\n\n update(update: ViewUpdate): void {\n const isPanelOpen = searchPanelOpen(update.state);\n const searchQuery = getSearchQuery(update.state);\n\n if (isPanelOpen !== this.panelOpened || searchQuery !== this.searchState) {\n this.panelOpened = isPanelOpen;\n this.searchState = searchQuery;\n this.renderer.rerender();\n }\n }\n\n destroy() {\n this.renderer.remove();\n this.receiver?.off('change-editor-mode', this.handleEditorModeChange);\n }\n\n createRenderer() {\n return this.view.state.facet(ReactRendererFacet).createItem('cm-search', () => {\n if (!this.panelOpened || !this.searchState) return null;\n\n const anchor = this.view.dom.ownerDocument.querySelector(\n this.params.anchorSelector,\n );\n\n if (!anchor) return null;\n\n return renderSearchPopup({\n open: true,\n anchor: anchor,\n state: this.searchState,\n onClose: this.handleClose,\n onChange: this.handleChange,\n onSearchNext: this.handleSearchNext,\n onSearchPrev: this.handleSearchPrev,\n onReplaceNext: this.handleReplaceNext,\n onReplaceAll: this.handleReplaceAll,\n });\n });\n }\n\n handleEditorModeChange({mode}: {mode: MarkdownEditorMode}) {\n if (mode === 'wysiwyg') {\n closeSearchPanel(this.view);\n }\n }\n\n handleChange(config: SearchQueryConfig) {\n this.view.dispatch({\n effects: setSearchQuery.of(\n new SearchQuery({\n search: config.search,\n replace: config.replace,\n caseSensitive: config.caseSensitive,\n wholeWord: config.wholeWord,\n }),\n ),\n });\n }\n\n handleClose() {\n this.handleChange({search: ''});\n closeSearchPanel(this.view);\n this.view.focus();\n }\n\n handleSearchNext() {\n findNext(this.view);\n }\n\n handleSearchPrev() {\n findPrevious(this.view);\n }\n\n handleReplaceNext() {\n replaceNext(this.view);\n }\n\n handleReplaceAll() {\n replaceAll(this.view);\n }\n },\n {\n provide: () => [\n keymap.of(searchKeymap),\n searchTheme,\n search({\n createPanel: () => ({\n // Create an empty search panel\n dom: document.createElement('div'),\n }),\n }),\n ],\n },\n );\n"]}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"../../../../../src","sources":["markup/codemirror/search-plugin/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SearchQuery,\n closeSearchPanel,\n findNext,\n findPrevious,\n getSearchQuery,\n replaceAll,\n replaceNext,\n search,\n searchKeymap,\n searchPanelOpen,\n setSearchQuery,\n} from '@codemirror/search';\nimport {\n type EditorView,\n type PluginValue,\n ViewPlugin,\n type ViewUpdate,\n keymap,\n} from '@codemirror/view';\n\nimport type {MarkdownEditorMode} from 'src/bundle';\nimport type {EventMap} from 'src/bundle/Editor';\nimport type {RendererItem} from 'src/extensions';\nimport {renderSearchPopup} from 'src/modules/search';\nimport type {Receiver} from 'src/utils';\n\nimport {ReactRendererFacet} from '../react-facet';\n\nimport {searchTheme} from './theme';\n\ntype SearchQueryConfig = ConstructorParameters<typeof SearchQuery>[0];\n\nexport interface SearchPanelPluginParams {\n anchorSelector: string;\n inputDelay?: number;\n receiver?: Receiver<EventMap>;\n}\n\nexport const SearchPanelPlugin = (params: SearchPanelPluginParams) =>\n ViewPlugin.fromClass(\n class implements PluginValue {\n readonly view: EditorView;\n readonly params: SearchPanelPluginParams;\n\n renderer: RendererItem;\n receiver: Receiver<EventMap> | undefined;\n\n panelOpened: boolean;\n searchState: SearchQuery | null;\n\n constructor(view: EditorView) {\n this.view = view;\n this.params = params;\n this.receiver = params.receiver;\n\n this.panelOpened = searchPanelOpen(view.state);\n this.searchState = getSearchQuery(view.state);\n this.renderer = this.createRenderer();\n\n this.handleClose = this.handleClose.bind(this);\n this.handleChange = this.handleChange.bind(this);\n this.handleSearchNext = this.handleSearchNext.bind(this);\n this.handleSearchPrev = this.handleSearchPrev.bind(this);\n this.handleReplaceNext = this.handleReplaceNext.bind(this);\n this.handleReplaceAll = this.handleReplaceAll.bind(this);\n this.handleEditorModeChange = this.handleEditorModeChange.bind(this);\n\n this.receiver?.on('change-editor-mode', this.handleEditorModeChange);\n }\n\n update(update: ViewUpdate): void {\n const isPanelOpen = searchPanelOpen(update.state);\n const searchQuery = getSearchQuery(update.state);\n\n if (isPanelOpen !== this.panelOpened || searchQuery !== this.searchState) {\n this.panelOpened = isPanelOpen;\n this.searchState = searchQuery;\n this.renderer.rerender();\n }\n }\n\n destroy() {\n this.renderer.remove();\n this.receiver?.off('change-editor-mode', this.handleEditorModeChange);\n }\n\n createRenderer() {\n return this.view.state.facet(ReactRendererFacet).createItem('cm-search', () => {\n if (!this.panelOpened || !this.searchState) return null;\n\n const anchor = this.view.dom.ownerDocument.querySelector(\n this.params.anchorSelector,\n );\n\n if (!anchor) return null;\n\n return renderSearchPopup({\n open: true,\n anchor: anchor,\n state: this.searchState,\n onClose: this.handleClose,\n onChange: this.handleChange,\n onSearchNext: this.handleSearchNext,\n onSearchPrev: this.handleSearchPrev,\n onReplaceNext: this.handleReplaceNext,\n onReplaceAll: this.handleReplaceAll,\n intersectionTracking: {\n container: this.view.contentDOM,\n selector: '.cm-searchMatch-selected',\n observerOptions: {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['class'],\n },\n },\n });\n });\n }\n\n handleEditorModeChange({mode}: {mode: MarkdownEditorMode}) {\n if (mode === 'wysiwyg') {\n closeSearchPanel(this.view);\n }\n }\n\n handleChange(config: SearchQueryConfig) {\n this.view.dispatch({\n effects: setSearchQuery.of(\n new SearchQuery({\n search: config.search,\n replace: config.replace,\n caseSensitive: config.caseSensitive,\n wholeWord: config.wholeWord,\n }),\n ),\n });\n }\n\n handleClose() {\n this.handleChange({search: ''});\n closeSearchPanel(this.view);\n this.view.focus();\n }\n\n handleSearchNext() {\n findNext(this.view);\n }\n\n handleSearchPrev() {\n findPrevious(this.view);\n }\n\n handleReplaceNext() {\n replaceNext(this.view);\n }\n\n handleReplaceAll() {\n replaceAll(this.view);\n }\n },\n {\n provide: () => [\n keymap.of(searchKeymap),\n searchTheme,\n search({\n createPanel: () => ({\n // Create an empty search panel\n dom: document.createElement('div'),\n }),\n }),\n ],\n },\n );\n"]}
@@ -1,11 +1,13 @@
1
1
  import { type UseSearchProps } from "../hooks/use-search.js";
2
2
  import type { SearchCounter } from "../types.js";
3
+ import { type UseObserveIntersectionProps } from "./hooks/useObserveIntersection.js";
3
4
  import "./SearchPopup.css";
4
5
  export type SearchPopupProps = UseSearchProps & {
5
6
  open: boolean;
6
7
  anchor: Element;
7
8
  counter?: SearchCounter;
8
9
  onClose: () => void;
10
+ intersectionTracking: Pick<UseObserveIntersectionProps, 'container' | 'selector' | 'observerOptions'>;
9
11
  };
10
12
  export declare const SearchPopup: React.FC<SearchPopupProps>;
11
13
  interface SearchPopupWithRefProps extends Omit<SearchPopupProps, 'anchor'> {
@@ -3,17 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SearchPopup = void 0;
4
4
  exports.renderSearchPopup = renderSearchPopup;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
6
7
  const uikit_1 = require("@gravity-ui/uikit");
7
8
  const classname_1 = require("../../../classname.js");
8
9
  const use_search_1 = require("../hooks/use-search.js");
9
10
  const qa_1 = require("../qa.js");
10
11
  const SearchCardView_1 = require("./SearchCardView.js");
11
12
  const SearchCompactView_1 = require("./SearchCompactView.js");
13
+ const useObserveIntersection_1 = require("./hooks/useObserveIntersection.js");
12
14
  require("./SearchPopup.css");
13
15
  const b = (0, classname_1.cn)('search-popup');
14
- const SearchPopup = ({ open, anchor, counter, onClose, ...props }) => {
16
+ const SearchPopup = ({ open, anchor, counter, onClose, intersectionTracking, ...props }) => {
15
17
  const { isCompact, searchState, handlers } = (0, use_search_1.useSearch)(props);
16
- return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: open, qa: qa_1.SearchQA.Panel, anchorElement: anchor, placement: "bottom-end", className: b({ compact: isCompact }), onOpenChange: (_open, _event, reason) => {
18
+ const floatingRef = (0, react_1.useRef)(null);
19
+ const { intersection } = (0, useObserveIntersection_1.useObserveIntersection)({
20
+ floatingRef,
21
+ container: intersectionTracking.container,
22
+ selector: intersectionTracking.selector,
23
+ observerOptions: intersectionTracking.observerOptions,
24
+ });
25
+ return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: open, qa: qa_1.SearchQA.Panel, anchorElement: anchor, placement: "bottom-end", floatingRef: floatingRef, floatingStyles: { opacity: intersection ? 0.8 : 1 }, className: b({ compact: isCompact }), onOpenChange: (_open, _event, reason) => {
17
26
  if (reason === 'escape-key') {
18
27
  onClose();
19
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SearchPopup.js","sourceRoot":"../../../../../src","sources":["modules/search/components/SearchPopup.tsx"],"names":[],"mappings":";;;AA+EA,8CAIC;;AAnFD,6CAAwC;AAExC,qDAAiC;AAEjC,uDAAmE;AACnE,iCAA+B;AAG/B,wDAAgD;AAChD,8DAAqD;AAErD,6BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,cAAE,EAAC,cAAc,CAAC,CAAC;AAStB,MAAM,WAAW,GAA+B,CAAC,EACpD,IAAI,EACJ,MAAM,EACN,OAAO,EACP,OAAO,EACP,GAAG,KAAK,EACX,EAAE,EAAE;IACD,MAAM,EAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAC,GAAG,IAAA,sBAAS,EAAC,KAAK,CAAC,CAAC;IAE5D,OAAO,CACH,uBAAC,aAAK,IACF,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,aAAQ,CAAC,KAAK,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAC,YAAY,EACtB,SAAS,EAAE,CAAC,CAAC,EAAC,OAAO,EAAE,SAAS,EAAC,CAAC,EAClC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACpC,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC1B,OAAO,EAAE,CAAC;YACd,CAAC;QACL,CAAC,YAEA,SAAS,CAAC,CAAC,CAAC,CACT,uBAAC,oCAAgB,IACb,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,CAAC,MAAM,EACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAC3B,QAAQ,EAAE,QAAQ,CAAC,cAAc,EACjC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,cAAc,EAAE,QAAQ,CAAC,cAAc,GACzC,CACL,CAAC,CAAC,CAAC,CACA,uBAAC,+BAAc,IACX,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,QAAQ,CAAC,cAAc,EACvC,mBAAmB,EAAE,QAAQ,CAAC,eAAe,EAC7C,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,cAAc,EAAE,QAAQ,CAAC,cAAc,EACvC,SAAS,EAAE,QAAQ,CAAC,SAAS,EAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY,EACnC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAC7C,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB,GACvD,CACL,GACG,CACX,CAAC;AACN,CAAC,CAAC;AAjDW,QAAA,WAAW,eAiDtB;AAEF,mBAAW,CAAC,WAAW,GAAG,aAAa,CAAC;AAMxC,SAAgB,iBAAiB,CAAC,EAAC,MAAM,EAAE,GAAG,KAAK,EAA0B;IACzE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,uBAAC,mBAAW,IAAC,MAAM,EAAE,MAAM,KAAM,KAAK,GAAI,CAAC;AACtD,CAAC","sourcesContent":["import {Popup} from '@gravity-ui/uikit';\n\nimport {cn} from 'src/classname';\n\nimport {type UseSearchProps, useSearch} from '../hooks/use-search';\nimport {SearchQA} from '../qa';\nimport type {SearchCounter} from '../types';\n\nimport {SearchCardView} from './SearchCardView';\nimport {SeachCompactView} from './SearchCompactView';\n\nimport './SearchPopup.scss';\n\nconst b = cn('search-popup');\n\nexport type SearchPopupProps = UseSearchProps & {\n open: boolean;\n anchor: Element;\n counter?: SearchCounter;\n onClose: () => void;\n};\n\nexport const SearchPopup: React.FC<SearchPopupProps> = ({\n open,\n anchor,\n counter,\n onClose,\n ...props\n}) => {\n const {isCompact, searchState, handlers} = useSearch(props);\n\n return (\n <Popup\n open={open}\n qa={SearchQA.Panel}\n anchorElement={anchor}\n placement=\"bottom-end\"\n className={b({compact: isCompact})}\n onOpenChange={(_open, _event, reason) => {\n if (reason === 'escape-key') {\n onClose();\n }\n }}\n >\n {isCompact ? (\n <SeachCompactView\n counter={counter}\n onClose={onClose}\n value={searchState.search}\n onExpand={handlers.onExpand}\n onChange={handlers.onSearchChange}\n onFindNext={handlers.onFindNext}\n onFindPrevious={handlers.onFindPrevious}\n />\n ) : (\n <SearchCardView\n counter={counter}\n onClose={onClose}\n searchState={searchState}\n onSearchChange={handlers.onSearchChange}\n onReplacementChange={handlers.onReplaceChange}\n onFindNext={handlers.onFindNext}\n onFindPrevious={handlers.onFindPrevious}\n onReplace={handlers.onReplace}\n onReplaceAll={handlers.onReplaceAll}\n onWholeWordChange={handlers.onWholeWordChange}\n onCaseSensitiveChange={handlers.onCaseSensitiveChange}\n />\n )}\n </Popup>\n );\n};\n\nSearchPopup.displayName = 'SearchPopup';\n\ninterface SearchPopupWithRefProps extends Omit<SearchPopupProps, 'anchor'> {\n anchor: Element | null;\n}\n\nexport function renderSearchPopup({anchor, ...props}: SearchPopupWithRefProps) {\n if (!anchor) return null;\n\n return <SearchPopup anchor={anchor} {...props} />;\n}\n"]}
1
+ {"version":3,"file":"SearchPopup.js","sourceRoot":"../../../../../src","sources":["modules/search/components/SearchPopup.tsx"],"names":[],"mappings":";;;AAmGA,8CAIC;;AAvGD,iCAA6B;AAE7B,6CAAwC;AAExC,qDAAiC;AAEjC,uDAAmE;AACnE,iCAA+B;AAG/B,wDAAgD;AAChD,8DAAqD;AACrD,8EAGwC;AAExC,6BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,cAAE,EAAC,cAAc,CAAC,CAAC;AAatB,MAAM,WAAW,GAA+B,CAAC,EACpD,IAAI,EACJ,MAAM,EACN,OAAO,EACP,OAAO,EACP,oBAAoB,EACpB,GAAG,KAAK,EACX,EAAE,EAAE;IACD,MAAM,EAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAC,GAAG,IAAA,sBAAS,EAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,IAAA,cAAM,EAAiB,IAAI,CAAC,CAAC;IACjD,MAAM,EAAC,YAAY,EAAC,GAAG,IAAA,+CAAsB,EAAC;QAC1C,WAAW;QACX,SAAS,EAAE,oBAAoB,CAAC,SAAS;QACzC,QAAQ,EAAE,oBAAoB,CAAC,QAAQ;QACvC,eAAe,EAAE,oBAAoB,CAAC,eAAe;KACxD,CAAC,CAAC;IAEH,OAAO,CACH,uBAAC,aAAK,IACF,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,aAAQ,CAAC,KAAK,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAC,YAAY,EACtB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,EAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC,EACjD,SAAS,EAAE,CAAC,CAAC,EAAC,OAAO,EAAE,SAAS,EAAC,CAAC,EAClC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACpC,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC1B,OAAO,EAAE,CAAC;YACd,CAAC;QACL,CAAC,YAEA,SAAS,CAAC,CAAC,CAAC,CACT,uBAAC,oCAAgB,IACb,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,CAAC,MAAM,EACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAC3B,QAAQ,EAAE,QAAQ,CAAC,cAAc,EACjC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,cAAc,EAAE,QAAQ,CAAC,cAAc,GACzC,CACL,CAAC,CAAC,CAAC,CACA,uBAAC,+BAAc,IACX,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,QAAQ,CAAC,cAAc,EACvC,mBAAmB,EAAE,QAAQ,CAAC,eAAe,EAC7C,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,cAAc,EAAE,QAAQ,CAAC,cAAc,EACvC,SAAS,EAAE,QAAQ,CAAC,SAAS,EAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY,EACnC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAC7C,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB,GACvD,CACL,GACG,CACX,CAAC;AACN,CAAC,CAAC;AA3DW,QAAA,WAAW,eA2DtB;AAEF,mBAAW,CAAC,WAAW,GAAG,aAAa,CAAC;AAMxC,SAAgB,iBAAiB,CAAC,EAAC,MAAM,EAAE,GAAG,KAAK,EAA0B;IACzE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,uBAAC,mBAAW,IAAC,MAAM,EAAE,MAAM,KAAM,KAAK,GAAI,CAAC;AACtD,CAAC","sourcesContent":["import {useRef} from 'react';\n\nimport {Popup} from '@gravity-ui/uikit';\n\nimport {cn} from 'src/classname';\n\nimport {type UseSearchProps, useSearch} from '../hooks/use-search';\nimport {SearchQA} from '../qa';\nimport type {SearchCounter} from '../types';\n\nimport {SearchCardView} from './SearchCardView';\nimport {SeachCompactView} from './SearchCompactView';\nimport {\n type UseObserveIntersectionProps,\n useObserveIntersection,\n} from './hooks/useObserveIntersection';\n\nimport './SearchPopup.scss';\n\nconst b = cn('search-popup');\n\nexport type SearchPopupProps = UseSearchProps & {\n open: boolean;\n anchor: Element;\n counter?: SearchCounter;\n onClose: () => void;\n intersectionTracking: Pick<\n UseObserveIntersectionProps,\n 'container' | 'selector' | 'observerOptions'\n >;\n};\n\nexport const SearchPopup: React.FC<SearchPopupProps> = ({\n open,\n anchor,\n counter,\n onClose,\n intersectionTracking,\n ...props\n}) => {\n const {isCompact, searchState, handlers} = useSearch(props);\n const floatingRef = useRef<HTMLDivElement>(null);\n const {intersection} = useObserveIntersection({\n floatingRef,\n container: intersectionTracking.container,\n selector: intersectionTracking.selector,\n observerOptions: intersectionTracking.observerOptions,\n });\n\n return (\n <Popup\n open={open}\n qa={SearchQA.Panel}\n anchorElement={anchor}\n placement=\"bottom-end\"\n floatingRef={floatingRef}\n floatingStyles={{opacity: intersection ? 0.8 : 1}}\n className={b({compact: isCompact})}\n onOpenChange={(_open, _event, reason) => {\n if (reason === 'escape-key') {\n onClose();\n }\n }}\n >\n {isCompact ? (\n <SeachCompactView\n counter={counter}\n onClose={onClose}\n value={searchState.search}\n onExpand={handlers.onExpand}\n onChange={handlers.onSearchChange}\n onFindNext={handlers.onFindNext}\n onFindPrevious={handlers.onFindPrevious}\n />\n ) : (\n <SearchCardView\n counter={counter}\n onClose={onClose}\n searchState={searchState}\n onSearchChange={handlers.onSearchChange}\n onReplacementChange={handlers.onReplaceChange}\n onFindNext={handlers.onFindNext}\n onFindPrevious={handlers.onFindPrevious}\n onReplace={handlers.onReplace}\n onReplaceAll={handlers.onReplaceAll}\n onWholeWordChange={handlers.onWholeWordChange}\n onCaseSensitiveChange={handlers.onCaseSensitiveChange}\n />\n )}\n </Popup>\n );\n};\n\nSearchPopup.displayName = 'SearchPopup';\n\ninterface SearchPopupWithRefProps extends Omit<SearchPopupProps, 'anchor'> {\n anchor: Element | null;\n}\n\nexport function renderSearchPopup({anchor, ...props}: SearchPopupWithRefProps) {\n if (!anchor) return null;\n\n return <SearchPopup anchor={anchor} {...props} />;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ export type UseObserveIntersectionProps = {
2
+ floatingRef: React.RefObject<HTMLElement>;
3
+ container: Element;
4
+ selector: string;
5
+ observerOptions?: MutationObserverInit;
6
+ };
7
+ export type UseObserveIntersectionReturn = {
8
+ intersection: boolean;
9
+ };
10
+ export declare function useObserveIntersection({ floatingRef, container, selector, observerOptions, }: UseObserveIntersectionProps): UseObserveIntersectionReturn;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useObserveIntersection = useObserveIntersection;
4
+ const react_1 = require("react");
5
+ const react_use_1 = require("react-use");
6
+ const useRAF_1 = require("../../../../react-utils/hooks/useRAF.js");
7
+ const dom_1 = require("../../../../utils/dom.js");
8
+ function useObserveIntersection({ floatingRef, container, selector, observerOptions, }) {
9
+ const [intersection, setIntersection] = (0, react_1.useState)(false);
10
+ const intersectionRef = (0, react_use_1.useLatest)(intersection);
11
+ const updateFunction = (0, react_1.useCallback)(() => {
12
+ const floating = floatingRef.current;
13
+ const element = container.querySelector(selector);
14
+ if (!element || !floating) {
15
+ if (intersectionRef.current)
16
+ setIntersection(false);
17
+ return;
18
+ }
19
+ const isIntersecting = (0, dom_1.areElementsIntersecting)(element, floating);
20
+ if (isIntersecting !== intersectionRef.current)
21
+ setIntersection(isIntersecting);
22
+ }, [container, floatingRef, intersectionRef, selector]);
23
+ const observer = (0, useRAF_1.useRAF)(updateFunction);
24
+ (0, react_1.useEffect)(() => {
25
+ observer();
26
+ const containerObserver = new MutationObserver(observer);
27
+ containerObserver.observe(container, observerOptions ?? {
28
+ childList: true,
29
+ subtree: true,
30
+ attributes: true,
31
+ });
32
+ for (const event of dom_1.REFLOW_EVENTS) {
33
+ window.addEventListener(event, observer);
34
+ }
35
+ return () => {
36
+ containerObserver.disconnect();
37
+ for (const event of dom_1.REFLOW_EVENTS) {
38
+ window.removeEventListener(event, observer);
39
+ }
40
+ };
41
+ }, [container, observer, observerOptions]);
42
+ return { intersection };
43
+ }
44
+ //# sourceMappingURL=useObserveIntersection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useObserveIntersection.js","sourceRoot":"../../../../../../src","sources":["modules/search/components/hooks/useObserveIntersection.ts"],"names":[],"mappings":";;AAkBA,wDAoDC;AAtED,iCAAuD;AAEvD,yCAAoC;AAEpC,oEAAoD;AACpD,kDAAqE;AAarE,SAAgB,sBAAsB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,GACW;IAC1B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAU,KAAK,CAAC,CAAC;IACjE,MAAM,eAAe,GAAG,IAAA,qBAAS,EAAU,YAAY,CAAC,CAAC;IAEzD,MAAM,cAAc,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACrC,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAElD,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,IAAI,eAAe,CAAC,OAAO;gBAAE,eAAe,CAAC,KAAK,CAAC,CAAC;YACpD,OAAO;QACX,CAAC;QAED,MAAM,cAAc,GAAG,IAAA,6BAAuB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAClE,IAAI,cAAc,KAAK,eAAe,CAAC,OAAO;YAAE,eAAe,CAAC,cAAc,CAAC,CAAC;IACpF,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAG,IAAA,eAAM,EAAC,cAAc,CAAC,CAAC;IAExC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,QAAQ,EAAE,CAAC;QAEX,MAAM,iBAAiB,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAEzD,iBAAiB,CAAC,OAAO,CACrB,SAAS,EACT,eAAe,IAAI;YACf,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;SACnB,CACJ,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,mBAAa,EAAE,CAAC;YAChC,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,OAAO,GAAG,EAAE;YACR,iBAAiB,CAAC,UAAU,EAAE,CAAC;YAE/B,KAAK,MAAM,KAAK,IAAI,mBAAa,EAAE,CAAC;gBAChC,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;QACL,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IAE3C,OAAO,EAAC,YAAY,EAAC,CAAC;AAC1B,CAAC","sourcesContent":["import {useCallback, useEffect, useState} from 'react';\n\nimport {useLatest} from 'react-use';\n\nimport {useRAF} from 'src/react-utils/hooks/useRAF';\nimport {REFLOW_EVENTS, areElementsIntersecting} from 'src/utils/dom';\n\nexport type UseObserveIntersectionProps = {\n floatingRef: React.RefObject<HTMLElement>;\n container: Element;\n selector: string;\n observerOptions?: MutationObserverInit;\n};\n\nexport type UseObserveIntersectionReturn = {\n intersection: boolean;\n};\n\nexport function useObserveIntersection({\n floatingRef,\n container,\n selector,\n observerOptions,\n}: UseObserveIntersectionProps): UseObserveIntersectionReturn {\n const [intersection, setIntersection] = useState<boolean>(false);\n const intersectionRef = useLatest<boolean>(intersection);\n\n const updateFunction = useCallback(() => {\n const floating = floatingRef.current;\n const element = container.querySelector(selector);\n\n if (!element || !floating) {\n if (intersectionRef.current) setIntersection(false);\n return;\n }\n\n const isIntersecting = areElementsIntersecting(element, floating);\n if (isIntersecting !== intersectionRef.current) setIntersection(isIntersecting);\n }, [container, floatingRef, intersectionRef, selector]);\n\n const observer = useRAF(updateFunction);\n\n useEffect(() => {\n observer();\n\n const containerObserver = new MutationObserver(observer);\n\n containerObserver.observe(\n container,\n observerOptions ?? {\n childList: true,\n subtree: true,\n attributes: true,\n },\n );\n\n for (const event of REFLOW_EVENTS) {\n window.addEventListener(event, observer);\n }\n\n return () => {\n containerObserver.disconnect();\n\n for (const event of REFLOW_EVENTS) {\n window.removeEventListener(event, observer);\n }\n };\n }, [container, observer, observerOptions]);\n\n return {intersection};\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function useRAF(fn: () => void): () => void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRAF = useRAF;
4
+ const react_1 = require("react");
5
+ function useRAF(fn) {
6
+ const rafRef = (0, react_1.useRef)(null);
7
+ (0, react_1.useEffect)(() => {
8
+ return () => {
9
+ if (rafRef.current !== null) {
10
+ cancelAnimationFrame(rafRef.current);
11
+ rafRef.current = null;
12
+ }
13
+ };
14
+ }, [fn]);
15
+ return (0, react_1.useCallback)(() => {
16
+ if (rafRef.current === null) {
17
+ rafRef.current = requestAnimationFrame(() => {
18
+ rafRef.current = null;
19
+ fn();
20
+ });
21
+ }
22
+ }, [fn]);
23
+ }
24
+ //# sourceMappingURL=useRAF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRAF.js","sourceRoot":"../../../../src","sources":["react-utils/hooks/useRAF.ts"],"names":[],"mappings":";;AAEA,wBAoBC;AAtBD,iCAAqD;AAErD,SAAgB,MAAM,CAAC,EAAc;IACjC,MAAM,MAAM,GAAG,IAAA,cAAM,EAAgB,IAAI,CAAC,CAAC;IAE3C,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,OAAO,GAAG,EAAE;YACR,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC1B,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACrC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,CAAC;QACL,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAET,OAAO,IAAA,mBAAW,EAAC,GAAG,EAAE;QACpB,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,OAAO,GAAG,qBAAqB,CAAC,GAAG,EAAE;gBACxC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,EAAE,EAAE,CAAC;YACT,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACb,CAAC","sourcesContent":["import {useCallback, useEffect, useRef} from 'react';\n\nexport function useRAF(fn: () => void): () => void {\n const rafRef = useRef<number | null>(null);\n\n useEffect(() => {\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n };\n }, [fn]);\n\n return useCallback(() => {\n if (rafRef.current === null) {\n rafRef.current = requestAnimationFrame(() => {\n rafRef.current = null;\n fn();\n });\n }\n }, [fn]);\n}\n"]}
@@ -3,30 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useSticky = useSticky;
4
4
  const react_1 = require("react");
5
5
  const react_use_1 = require("react-use");
6
- const events = new Set([
7
- 'resize',
8
- 'scroll',
9
- 'touchstart',
10
- 'touchmove',
11
- 'touchend',
12
- 'pageshow',
13
- 'load',
14
- 'orientationchange',
15
- ]);
6
+ const dom_1 = require("../utils/dom.js");
16
7
  function useSticky(elemRef) {
17
8
  const [sticky, setSticky] = (0, react_1.useState)(false);
18
9
  const stickyRef = (0, react_use_1.useLatest)(sticky);
19
10
  (0, react_use_1.useEffectOnce)(() => {
20
11
  let rafId = null;
21
12
  observe();
22
- for (const eventName of events) {
13
+ for (const eventName of dom_1.REFLOW_EVENTS) {
23
14
  window.addEventListener(eventName, scheduleObserve, true);
24
15
  }
25
16
  return () => {
26
17
  if (rafId !== null) {
27
18
  cancelAnimationFrame(rafId);
28
19
  }
29
- for (const eventName of events) {
20
+ for (const eventName of dom_1.REFLOW_EVENTS) {
30
21
  window.removeEventListener(eventName, scheduleObserve, true);
31
22
  }
32
23
  };