@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":"parser.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,oBAAiB;AAEtC,MAAM,QAAQ,GAA4B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEpG,MAAM,CAAC,MAAM,YAAY,GAAsC;IAC3D,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAC,IAAI,EAAE,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAC;IAE/E,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAC,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAC;IAExE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAC,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAC;CAC5E,CAAC","sourcesContent":["import type {ParserToken} from '../../../../core';\nimport {CheckboxNode} from '../const';\n\nconst getAttrs: ParserToken['getAttrs'] = (tok) => (tok.attrs ? Object.fromEntries(tok.attrs) : {});\n\nexport const parserTokens: Record<CheckboxNode, ParserToken> = {\n [CheckboxNode.Checkbox]: {name: CheckboxNode.Checkbox, type: 'block', getAttrs},\n\n [CheckboxNode.Input]: {name: CheckboxNode.Input, type: 'node', getAttrs},\n\n [CheckboxNode.Label]: {name: CheckboxNode.Label, type: 'block', getAttrs},\n};\n"]}
1
+ {"version":3,"file":"parser.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/parser.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAE,YAAY,EAAC,oBAAiB;AAEpD,OAAO,EAAC,oBAAoB,EAAE,mBAAmB,EAAC,mBAAgB;AAElE,MAAM,gBAAgB,GAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IACvE,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjE,OAAO,EAAC,GAAG,KAAK,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,EAAC,CAAC;AACnD,CAAC,CAAC;AAEF,MAAM,QAAQ,GAA4B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEpG,MAAM,CAAC,MAAM,YAAY,GAAsC;IAC3D,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE;QACrB,IAAI,EAAE,YAAY,CAAC,QAAQ;QAC3B,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,gBAAgB;KAC7B;IAED,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAC,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAC;IAExE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAC,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAC;CAC5E,CAAC;AAEF,SAAS,eAAe,CAAC,MAAe,EAAE,KAAa;IACnD,IAAI,iBAAqC,CAAC;IAC1C,IAAI,sBAA0C,CAAC;IAE/C,KAAK,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YAC1C,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAEvC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBAC9C,sBAAsB,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YACpD,CAAC;YAED,MAAM;QACV,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAC/E,OAAO,IAAI,CAAC;IAEhB,OAAO,iBAAiB,KAAK,sBAAsB,CAAC;AACxD,CAAC","sourcesContent":["import type Token from 'markdown-it/lib/token';\n\nimport type {ParserToken} from '#core';\n\nimport {CheckboxAttr, CheckboxNode} from '../const';\n\nimport {CHECKBOX_CLOSE_TOKEN, CHECKBOX_OPEN_TOKEN} from './const';\n\nconst getCheckboxAttrs: ParserToken['getAttrs'] = (token, tokens, index) => {\n const tight = checkboxIsTight(tokens, index);\n const attrs = token.attrs ? Object.fromEntries(token.attrs) : {};\n\n return {...attrs, [CheckboxAttr.Tight]: tight};\n};\n\nconst getAttrs: ParserToken['getAttrs'] = (tok) => (tok.attrs ? Object.fromEntries(tok.attrs) : {});\n\nexport const parserTokens: Record<CheckboxNode, ParserToken> = {\n [CheckboxNode.Checkbox]: {\n name: CheckboxNode.Checkbox,\n type: 'block',\n getAttrs: getCheckboxAttrs,\n },\n\n [CheckboxNode.Input]: {name: CheckboxNode.Input, type: 'node', getAttrs},\n\n [CheckboxNode.Label]: {name: CheckboxNode.Label, type: 'block', getAttrs},\n};\n\nfunction checkboxIsTight(tokens: Token[], index: number): boolean | null {\n let closeTokenEndLine: number | undefined;\n let nextOpenTokenStartLine: number | undefined;\n\n for (let i = index + 1; i < tokens.length; i++) {\n if (tokens[i].type === CHECKBOX_CLOSE_TOKEN) {\n closeTokenEndLine = tokens[i].map?.[1];\n\n if (tokens[i + 1]?.type === CHECKBOX_OPEN_TOKEN) {\n nextOpenTokenStartLine = tokens[i + 1].map?.[0];\n }\n\n break;\n }\n }\n\n if (!Number.isFinite(closeTokenEndLine) || !Number.isFinite(nextOpenTokenStartLine))\n return null;\n\n return closeTokenEndLine === nextOpenTokenStartLine;\n}\n"]}
@@ -1,5 +1,11 @@
1
1
  import { type NodeSpec } from 'prosemirror-model';
2
2
  import type { PlaceholderOptions } from "../../../../utils/placeholder.js";
3
3
  import { CheckboxNode } from "./const.js";
4
- import type { CheckboxSpecsOptions } from "./index.js";
5
- export declare const getSchemaSpecs: (opts?: Pick<CheckboxSpecsOptions, "checkboxLabelPlaceholder">, placeholder?: PlaceholderOptions) => Record<CheckboxNode, NodeSpec>;
4
+ export type GetSchemaSpecsOptions = {
5
+ multiline?: boolean;
6
+ /**
7
+ * @deprecated use placeholder option in BehaviorPreset instead.
8
+ */
9
+ checkboxLabelPlaceholder?: NonNullable<NodeSpec['placeholder']>['content'];
10
+ };
11
+ export declare const getSchemaSpecs: (opts?: GetSchemaSpecsOptions, placeholder?: PlaceholderOptions) => Record<CheckboxNode, NodeSpec>;
@@ -8,8 +8,9 @@ export const getSchemaSpecs = (opts, placeholder) => ({
8
8
  selectable: true,
9
9
  allowSelection: false,
10
10
  attrs: {
11
- [CheckboxAttr.Class]: { default: b() },
11
+ [CheckboxAttr.Class]: { default: b(null, 'checkbox') },
12
12
  [CheckboxAttr.Line]: { default: null },
13
+ ...(opts?.multiline ? { [CheckboxAttr.Tight]: { default: null } } : undefined),
13
14
  },
14
15
  parseDOM: [
15
16
  {
@@ -92,6 +93,7 @@ export const getSchemaSpecs = (opts, placeholder) => ({
92
93
  selectable: false,
93
94
  allowSelection: false,
94
95
  disableGapCursor: true,
96
+ canContainBreaks: Boolean(opts?.multiline),
95
97
  complex: 'leaf',
96
98
  },
97
99
  });
@@ -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"]}
@@ -1,9 +1,21 @@
1
1
  import { getPlaceholderContent } from "../../../../utils/placeholder.js";
2
2
  import { CheckboxAttr, CheckboxNode } from "./const.js";
3
3
  export const serializerTokens = {
4
- [CheckboxNode.Checkbox]: (state, node) => {
4
+ [CheckboxNode.Checkbox]: (state, node, parent, index) => {
5
5
  state.renderInline(node);
6
- state.closeBlock(node);
6
+ // TODO [MAJOR]: remove this check after removing `multiline` option
7
+ if (!node.type.spec.attrs?.[CheckboxAttr.Tight]) {
8
+ state.closeBlock(node);
9
+ return;
10
+ }
11
+ const tight = node.attrs[CheckboxAttr.Tight];
12
+ const nextIsCheckbox = parent.maybeChild(index + 1)?.type.name === CheckboxNode.Checkbox;
13
+ if (tight === false || !nextIsCheckbox) {
14
+ state.closeBlock(node);
15
+ }
16
+ else {
17
+ state.ensureNewLine();
18
+ }
7
19
  },
8
20
  [CheckboxNode.Input]: (state, node) => {
9
21
  const checked = node.attrs[CheckboxAttr.Checked] === 'true';
@@ -1 +1 @@
1
- {"version":3,"file":"serializer.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/Checkbox/CheckboxSpecs/serializer.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,qBAAqB,EAAC,yCAAsC;AAEpE,OAAO,EAAC,YAAY,EAAE,YAAY,EAAC,mBAAgB;AAEnD,MAAM,CAAC,MAAM,gBAAgB,GAA8C;IACvE,CAAC,YAAY,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,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,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,YAAY,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,qBAAqB,CAAC,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,OAAO,EAAC,qBAAqB,EAAC,yCAAsC;AAEpE,OAAO,EAAC,YAAY,EAAE,YAAY,EAAC,mBAAgB;AAEnD,MAAM,CAAC,MAAM,gBAAgB,GAA8C;IACvE,CAAC,YAAY,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,YAAY,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,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,YAAY,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,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,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,YAAY,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,qBAAqB,CAAC,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 {
@@ -14,7 +14,7 @@ export const Checkbox = (builder, opts) => {
14
14
  inputView: () => CheckboxInputView.create,
15
15
  });
16
16
  builder
17
- .addPlugin(keymapPlugin, builder.Priority.High)
17
+ .addPlugin(() => keymapPlugin(opts), builder.Priority.High)
18
18
  .addPlugin(fixPastePlugin)
19
19
  .addAction(checkboxAction, () => addCheckbox())
20
20
  .addInputRules(({ schema }) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/yfm/Checkbox/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,qCAAkC;AAExD,OAAO,EAAC,aAAa,EAA4B,iCAAwB;AACzE,OAAO,EAAC,WAAW,EAAC,qBAAkB;AACtC,OAAO,EAAC,iBAAiB,EAAC,uBAAoB;AAC9C,OAAO,EAAC,YAAY,EAAC,oBAAiB;AACtC,OAAO,EAAC,cAAc,EAAC,+BAA4B;AACnD,OAAO,EAAC,iBAAiB,EAAE,YAAY,EAAC,mBAAgB;AAExD,qBAAsB;AAEtB,MAAM,cAAc,GAAG,aAAa,CAAC;AAErC,OAAO,EACH,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GACpB,iCAAwB;AAIzB,MAAM,CAAC,MAAM,QAAQ,GAAmC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACtE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE;QACvB,GAAG,IAAI;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM;KAC5C,CAAC,CAAC;IAEH,OAAO;SACF,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;SAC9C,SAAS,CAAC,cAAc,CAAC;SACzB,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;SAC9C,aAAa,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE;YACH,aAAa,CACT,eAAe,EACf,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,EAC1E,CAAC,CACJ;SACJ;KACJ,CAAC,CAAC,CAAC;AACZ,CAAC,CAAC","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,OAAO,EAAC,aAAa,EAAC,qCAAkC;AAExD,OAAO,EAAC,aAAa,EAA4B,iCAAwB;AACzE,OAAO,EAAC,WAAW,EAAC,qBAAkB;AACtC,OAAO,EAAC,iBAAiB,EAAC,uBAAoB;AAC9C,OAAO,EAAC,YAAY,EAAC,oBAAiB;AACtC,OAAO,EAAC,cAAc,EAAC,+BAA4B;AACnD,OAAO,EAAC,iBAAiB,EAAE,YAAY,EAAC,mBAAgB;AAExD,qBAAsB;AAEtB,MAAM,cAAc,GAAG,aAAa,CAAC;AAErC,OAAO,EACH,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GACpB,iCAAwB;AAYzB,MAAM,CAAC,MAAM,QAAQ,GAAmC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACtE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE;QACvB,GAAG,IAAI;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM;KAC5C,CAAC,CAAC;IAEH,OAAO;SACF,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;SAC1D,SAAS,CAAC,cAAc,CAAC;SACzB,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;SAC9C,aAAa,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE;YACH,aAAa,CACT,eAAe,EACf,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,EAC1E,CAAC,CACJ;SACJ;KACJ,CAAC,CAAC,CAAC;AACZ,CAAC,CAAC","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 {};
@@ -3,8 +3,9 @@ import { Fragment } from 'prosemirror-model';
3
3
  import { TextSelection } from 'prosemirror-state';
4
4
  // @ts-ignore // TODO: fix cjs build
5
5
  import { findParentNodeOfType } from 'prosemirror-utils';
6
- import { isWholeSelection } from "../../../utils/selection.js";
7
6
  import { pType } from "../../base/BaseSchema/index.js";
7
+ import { isBreakNode } from "../../markdown/Breaks/index.js";
8
+ import { isWholeSelection } from "../../../utils/selection.js";
8
9
  import { checkboxInputType, checkboxLabelType, checkboxType } from "./utils.js";
9
10
  export const splitCheckbox = (replaceWithParagraph) => (state, dispatch) => {
10
11
  const { $from, $to } = state.selection;
@@ -31,6 +32,10 @@ export const splitCheckbox = (replaceWithParagraph) => (state, dispatch) => {
31
32
  tr.insert($from.after(), [node]);
32
33
  tr.replace(label.start + $from.parentOffset, label.pos + label.node.nodeSize);
33
34
  tr.setSelection(new TextSelection(tr.doc.resolve(tr.selection.$from.after() + (replaceWithParagraph ? 2 : 4))));
35
+ // remove break before cursor
36
+ if (isBreakNode($from.nodeBefore)) {
37
+ tr.replaceWith($from.pos - 1, $from.pos, Fragment.empty);
38
+ }
34
39
  dispatch?.(tr);
35
40
  return true;
36
41
  }
@@ -54,9 +59,9 @@ const removeCheckbox = (state, dispatch) => {
54
59
  }
55
60
  return false;
56
61
  };
57
- export const keymapPlugin = () => keymap({
62
+ export const keymapPlugin = (props) => keymap({
58
63
  Enter: splitCheckbox(),
59
64
  Backspace: removeCheckbox,
60
- 'Shift-Enter': splitCheckbox(true),
65
+ ...(props.multiline ? undefined : { 'Shift-Enter': splitCheckbox(true) }),
61
66
  });
62
67
  //# 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"]}
@@ -71,6 +71,10 @@ export class EmojiHandler {
71
71
  }
72
72
  onEnter(action) {
73
73
  this.updateState(action);
74
+ const emojiDef = this._emojiCarousel?.currentItem;
75
+ if (!emojiDef) {
76
+ return false;
77
+ }
74
78
  this.select();
75
79
  return true;
76
80
  }
@@ -178,7 +182,7 @@ function filterEmojis(defs, text) {
178
182
  }
179
183
  return byShortcuts.concat(byName);
180
184
  }
181
- const CHARS_TO_HIDE = 4;
185
+ const CHARS_TO_HIDE = 1;
182
186
  function needToHide(defs, text) {
183
187
  let iter = 1;
184
188
  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":"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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 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"]}
@@ -56,6 +56,16 @@ export const SearchPanelPlugin = (params) => ViewPlugin.fromClass(class {
56
56
  onSearchPrev: this.handleSearchPrev,
57
57
  onReplaceNext: this.handleReplaceNext,
58
58
  onReplaceAll: this.handleReplaceAll,
59
+ intersectionTracking: {
60
+ container: this.view.contentDOM,
61
+ selector: '.cm-searchMatch-selected',
62
+ observerOptions: {
63
+ childList: true,
64
+ subtree: true,
65
+ attributes: true,
66
+ attributeFilter: ['class'],
67
+ },
68
+ },
59
69
  });
60
70
  });
61
71
  }
@@ -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'> {
@@ -1,15 +1,24 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef } from 'react';
2
3
  import { Popup } from '@gravity-ui/uikit';
3
4
  import { cn } from "../../../classname.js";
4
5
  import { useSearch } from "../hooks/use-search.js";
5
6
  import { SearchQA } from "../qa.js";
6
7
  import { SearchCardView } from "./SearchCardView.js";
7
8
  import { SeachCompactView } from "./SearchCompactView.js";
9
+ import { useObserveIntersection, } from "./hooks/useObserveIntersection.js";
8
10
  import "./SearchPopup.css";
9
11
  const b = cn('search-popup');
10
- export const SearchPopup = ({ open, anchor, counter, onClose, ...props }) => {
12
+ export const SearchPopup = ({ open, anchor, counter, onClose, intersectionTracking, ...props }) => {
11
13
  const { isCompact, searchState, handlers } = useSearch(props);
12
- return (_jsx(Popup, { open: open, qa: SearchQA.Panel, anchorElement: anchor, placement: "bottom-end", className: b({ compact: isCompact }), onOpenChange: (_open, _event, reason) => {
14
+ const floatingRef = useRef(null);
15
+ const { intersection } = useObserveIntersection({
16
+ floatingRef,
17
+ container: intersectionTracking.container,
18
+ selector: intersectionTracking.selector,
19
+ observerOptions: intersectionTracking.observerOptions,
20
+ });
21
+ return (_jsx(Popup, { open: open, qa: SearchQA.Panel, anchorElement: anchor, placement: "bottom-end", floatingRef: floatingRef, floatingStyles: { opacity: intersection ? 0.8 : 1 }, className: b({ compact: isCompact }), onOpenChange: (_open, _event, reason) => {
13
22
  if (reason === 'escape-key') {
14
23
  onClose();
15
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SearchPopup.js","sourceRoot":"../../../../../src","sources":["modules/search/components/SearchPopup.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAC,EAAE,EAAC,8BAAsB;AAEjC,OAAO,EAAsB,SAAS,EAAC,+BAA4B;AACnE,OAAO,EAAC,QAAQ,EAAC,iBAAc;AAG/B,OAAO,EAAC,cAAc,EAAC,4BAAyB;AAChD,OAAO,EAAC,gBAAgB,EAAC,+BAA4B;AAErD,2BAA4B;AAE5B,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;AAS7B,MAAM,CAAC,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,SAAS,CAAC,KAAK,CAAC,CAAC;IAE5D,OAAO,CACH,KAAC,KAAK,IACF,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,QAAQ,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,KAAC,gBAAgB,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,KAAC,cAAc,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;AAEF,WAAW,CAAC,WAAW,GAAG,aAAa,CAAC;AAMxC,MAAM,UAAU,iBAAiB,CAAC,EAAC,MAAM,EAAE,GAAG,KAAK,EAA0B;IACzE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,KAAC,WAAW,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":"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","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,41 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useLatest } from 'react-use';
3
+ import { useRAF } from "../../../../react-utils/hooks/useRAF.js";
4
+ import { REFLOW_EVENTS, areElementsIntersecting } from "../../../../utils/dom.js";
5
+ export function useObserveIntersection({ floatingRef, container, selector, observerOptions, }) {
6
+ const [intersection, setIntersection] = useState(false);
7
+ const intersectionRef = useLatest(intersection);
8
+ const updateFunction = useCallback(() => {
9
+ const floating = floatingRef.current;
10
+ const element = container.querySelector(selector);
11
+ if (!element || !floating) {
12
+ if (intersectionRef.current)
13
+ setIntersection(false);
14
+ return;
15
+ }
16
+ const isIntersecting = areElementsIntersecting(element, floating);
17
+ if (isIntersecting !== intersectionRef.current)
18
+ setIntersection(isIntersecting);
19
+ }, [container, floatingRef, intersectionRef, selector]);
20
+ const observer = useRAF(updateFunction);
21
+ useEffect(() => {
22
+ observer();
23
+ const containerObserver = new MutationObserver(observer);
24
+ containerObserver.observe(container, observerOptions ?? {
25
+ childList: true,
26
+ subtree: true,
27
+ attributes: true,
28
+ });
29
+ for (const event of REFLOW_EVENTS) {
30
+ window.addEventListener(event, observer);
31
+ }
32
+ return () => {
33
+ containerObserver.disconnect();
34
+ for (const event of REFLOW_EVENTS) {
35
+ window.removeEventListener(event, observer);
36
+ }
37
+ };
38
+ }, [container, observer, observerOptions]);
39
+ return { intersection };
40
+ }
41
+ //# sourceMappingURL=useObserveIntersection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useObserveIntersection.js","sourceRoot":"../../../../../../src","sources":["modules/search/components/hooks/useObserveIntersection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAC,MAAM,EAAC,gDAAqC;AACpD,OAAO,EAAC,aAAa,EAAE,uBAAuB,EAAC,iCAAsB;AAarE,MAAM,UAAU,sBAAsB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,GACW;IAC1B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IACjE,MAAM,eAAe,GAAG,SAAS,CAAU,YAAY,CAAC,CAAC;IAEzD,MAAM,cAAc,GAAG,WAAW,CAAC,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,uBAAuB,CAAC,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,MAAM,CAAC,cAAc,CAAC,CAAC;IAExC,SAAS,CAAC,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,aAAa,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,aAAa,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,21 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ export function useRAF(fn) {
3
+ const rafRef = useRef(null);
4
+ useEffect(() => {
5
+ return () => {
6
+ if (rafRef.current !== null) {
7
+ cancelAnimationFrame(rafRef.current);
8
+ rafRef.current = null;
9
+ }
10
+ };
11
+ }, [fn]);
12
+ return useCallback(() => {
13
+ if (rafRef.current === null) {
14
+ rafRef.current = requestAnimationFrame(() => {
15
+ rafRef.current = null;
16
+ fn();
17
+ });
18
+ }
19
+ }, [fn]);
20
+ }
21
+ //# sourceMappingURL=useRAF.js.map