@mittwald/flow-react-components 0.2.0-alpha.450 → 0.2.0-alpha.451

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 (69) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/assets/doc-properties.json +6663 -3838
  3. package/dist/css/all.css +1 -1
  4. package/dist/js/_virtual/_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs +26 -0
  5. package/dist/js/_virtual/_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs.map +1 -0
  6. package/dist/js/components/src/components/List/hooks/useAriaAnnounceSearchState.mjs +2 -0
  7. package/dist/js/components/src/components/List/hooks/useAriaAnnounceSearchState.mjs.map +1 -1
  8. package/dist/js/components/src/components/Markdown/Markdown.mjs +4 -2
  9. package/dist/js/components/src/components/Markdown/Markdown.mjs.map +1 -1
  10. package/dist/js/components/src/components/MarkdownEditor/MarkdownEditor.mjs +74 -0
  11. package/dist/js/components/src/components/MarkdownEditor/MarkdownEditor.mjs.map +1 -0
  12. package/dist/js/components/src/components/MarkdownEditor/MarkdownEditor.module.scss.mjs +19 -0
  13. package/dist/js/components/src/components/MarkdownEditor/MarkdownEditor.module.scss.mjs.map +1 -0
  14. package/dist/js/components/src/components/MarkdownEditor/components/ModeButton.mjs +29 -0
  15. package/dist/js/components/src/components/MarkdownEditor/components/ModeButton.mjs.map +1 -0
  16. package/dist/js/components/src/components/MarkdownEditor/components/Toolbar.mjs +39 -0
  17. package/dist/js/components/src/components/MarkdownEditor/components/Toolbar.mjs.map +1 -0
  18. package/dist/js/components/src/components/MarkdownEditor/components/ToolbarButton.mjs +37 -0
  19. package/dist/js/components/src/components/MarkdownEditor/components/ToolbarButton.mjs.map +1 -0
  20. package/dist/js/components/src/components/MarkdownEditor/lib/handleKeyDown.mjs +72 -0
  21. package/dist/js/components/src/components/MarkdownEditor/lib/handleKeyDown.mjs.map +1 -0
  22. package/dist/js/components/src/components/MarkdownEditor/lib/insertAtCursor.mjs +152 -0
  23. package/dist/js/components/src/components/MarkdownEditor/lib/insertAtCursor.mjs.map +1 -0
  24. package/dist/js/components/src/components/NumberField/NumberField.mjs +1 -1
  25. package/dist/js/components/src/components/NumberField/NumberField.mjs.map +1 -1
  26. package/dist/js/components/src/components/TextFieldBase/TextFieldBase.mjs +1 -1
  27. package/dist/js/components/src/components/TextFieldBase/TextFieldBase.mjs.map +1 -1
  28. package/dist/js/components/src/components/propTypes/index.mjs +1 -0
  29. package/dist/js/components/src/components/propTypes/index.mjs.map +1 -1
  30. package/dist/js/components/src/integrations/react-hook-form/components/Field/Field.mjs +1 -0
  31. package/dist/js/components/src/integrations/react-hook-form/components/Field/Field.mjs.map +1 -1
  32. package/dist/js/default.mjs +1 -0
  33. package/dist/js/default.mjs.map +1 -1
  34. package/dist/js/flr-universal.mjs +2 -0
  35. package/dist/js/flr-universal.mjs.map +1 -1
  36. package/dist/types/components/Markdown/Markdown.d.ts +2 -1
  37. package/dist/types/components/Markdown/Markdown.d.ts.map +1 -1
  38. package/dist/types/components/MarkdownEditor/MarkdownEditor.d.ts +8 -0
  39. package/dist/types/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  40. package/dist/types/components/MarkdownEditor/components/ModeButton.d.ts +10 -0
  41. package/dist/types/components/MarkdownEditor/components/ModeButton.d.ts.map +1 -0
  42. package/dist/types/components/MarkdownEditor/components/Toolbar.d.ts +14 -0
  43. package/dist/types/components/MarkdownEditor/components/Toolbar.d.ts.map +1 -0
  44. package/dist/types/components/MarkdownEditor/components/ToolbarButton.d.ts +15 -0
  45. package/dist/types/components/MarkdownEditor/components/ToolbarButton.d.ts.map +1 -0
  46. package/dist/types/components/MarkdownEditor/index.d.ts +3 -0
  47. package/dist/types/components/MarkdownEditor/index.d.ts.map +1 -0
  48. package/dist/types/components/MarkdownEditor/lib/handleKeyDown.d.ts +3 -0
  49. package/dist/types/components/MarkdownEditor/lib/handleKeyDown.d.ts.map +1 -0
  50. package/dist/types/components/MarkdownEditor/lib/handleKeyDown.test.d.ts +2 -0
  51. package/dist/types/components/MarkdownEditor/lib/handleKeyDown.test.d.ts.map +1 -0
  52. package/dist/types/components/MarkdownEditor/lib/insertAtCursor.d.ts +4 -0
  53. package/dist/types/components/MarkdownEditor/lib/insertAtCursor.d.ts.map +1 -0
  54. package/dist/types/components/MarkdownEditor/lib/insertAtCursor.test.d.ts +2 -0
  55. package/dist/types/components/MarkdownEditor/lib/insertAtCursor.test.d.ts.map +1 -0
  56. package/dist/types/components/MarkdownEditor/stories/Default.stories.d.ts +13 -0
  57. package/dist/types/components/MarkdownEditor/stories/Default.stories.d.ts.map +1 -0
  58. package/dist/types/components/MarkdownEditor/view.d.ts +8 -0
  59. package/dist/types/components/MarkdownEditor/view.d.ts.map +1 -0
  60. package/dist/types/components/propTypes/index.d.ts +3 -1
  61. package/dist/types/components/propTypes/index.d.ts.map +1 -1
  62. package/dist/types/components/public.d.ts +1 -0
  63. package/dist/types/components/public.d.ts.map +1 -1
  64. package/dist/types/integrations/react-hook-form/components/Field/Field.d.ts.map +1 -1
  65. package/dist/types/lib/propsContext/propsContext.d.ts +2 -0
  66. package/dist/types/lib/propsContext/propsContext.d.ts.map +1 -1
  67. package/dist/types/views/MarkdownEditorView.d.ts +5 -0
  68. package/dist/types/views/MarkdownEditorView.d.ts.map +1 -0
  69. package/package.json +5 -4
@@ -0,0 +1,26 @@
1
+ "use client"
2
+ /* */
3
+ const locales = {"de-DE": { "mode.editor": `Editor`,
4
+ "mode.preview": `Vorschau`,
5
+ "toolbar.bold": `Fett`,
6
+ "toolbar.code": `Code`,
7
+ "toolbar.italic": `Kursiv`,
8
+ "toolbar.link": `Link`,
9
+ "toolbar.orderedList": `Sortierte Liste`,
10
+ "toolbar.quote": `Zitat`,
11
+ "toolbar.strikeThrough": `Durchgestrichen`,
12
+ "toolbar.unorderedList": `Liste`,
13
+ },"en-US": { "mode.editor": `Editor`,
14
+ "mode.preview": `Preview`,
15
+ "toolbar.bold": `Bold`,
16
+ "toolbar.code": `Code`,
17
+ "toolbar.italic": `Italic`,
18
+ "toolbar.link": `Link`,
19
+ "toolbar.orderedList": `Ordered List`,
20
+ "toolbar.quote": `Quote`,
21
+ "toolbar.strikeThrough": `Strike through`,
22
+ "toolbar.unorderedList": `List`,
23
+ }};
24
+
25
+ export { locales as default };
26
+ //# sourceMappingURL=_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -69,6 +69,8 @@ import '../components/ListSummary/ListSummary.mjs';
69
69
  import { useList } from './useList.mjs';
70
70
  import '../List.mjs';
71
71
  import 'react-markdown';
72
+ import 'remark-gfm';
73
+ import '../../MarkdownEditor/MarkdownEditor.mjs';
72
74
  import '../../Message/Message.mjs';
73
75
  import '../../MessageThread/MessageThread.mjs';
74
76
  import '../../Modal/Modal.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"useAriaAnnounceSearchState.mjs","sources":["../../../../../../../src/components/List/hooks/useAriaAnnounceSearchState.ts"],"sourcesContent":["import { useLocalizedStringFormatter } from \"react-aria\";\nimport locales from \"../locales/*.locale.json\";\nimport { announce } from \"@react-aria/live-announcer\";\nimport { useList } from \"@/index/default\";\nimport { useDebounceCallback } from \"usehooks-ts\";\nimport { useEffect } from \"react\";\n\nconst announceDebounceMs = 600;\n\nexport const useAriaAnnounceSearchState = (): void => {\n const formatter = useLocalizedStringFormatter(locales);\n const list = useList();\n const debouncedAnnounce = useDebounceCallback(announce, announceDebounceMs);\n\n const searchTerm = list.search?.value;\n const resultCount = list.batches.getTotalItemsCount();\n const isLoading = list.loader.loaderState.useIsLoading();\n\n useEffect(() => {\n if (isLoading || !searchTerm) {\n debouncedAnnounce.cancel();\n return;\n }\n\n const text = formatter.format(\n resultCount > 0\n ? \"list.search.announce.result\"\n : \"list.search.announce.noResult\",\n {\n resultCount,\n searchTerm,\n },\n );\n\n debouncedAnnounce(text, \"polite\");\n }, [searchTerm, resultCount, isLoading]);\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,MAAM,kBAAqB,GAAA,GAAA;AAEpB,MAAM,6BAA6B,MAAY;AACpD,EAAM,MAAA,SAAA,GAAY,4BAA4B,OAAO,CAAA;AACrD,EAAA,MAAM,OAAO,OAAQ,EAAA;AACrB,EAAM,MAAA,iBAAA,GAAoB,mBAAoB,CAAA,QAAA,EAAU,kBAAkB,CAAA;AAE1E,EAAM,MAAA,UAAA,GAAa,KAAK,MAAQ,EAAA,KAAA;AAChC,EAAM,MAAA,WAAA,GAAc,IAAK,CAAA,OAAA,CAAQ,kBAAmB,EAAA;AACpD,EAAA,MAAM,SAAY,GAAA,IAAA,CAAK,MAAO,CAAA,WAAA,CAAY,YAAa,EAAA;AAEvD,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,SAAA,IAAa,CAAC,UAAY,EAAA;AAC5B,MAAA,iBAAA,CAAkB,MAAO,EAAA;AACzB,MAAA;AAAA;AAGF,IAAA,MAAM,OAAO,SAAU,CAAA,MAAA;AAAA,MACrB,WAAA,GAAc,IACV,6BACA,GAAA,+BAAA;AAAA,MACJ;AAAA,QACE,WAAA;AAAA,QACA;AAAA;AACF,KACF;AAEA,IAAA,iBAAA,CAAkB,MAAM,QAAQ,CAAA;AAAA,GAC/B,EAAA,CAAC,UAAY,EAAA,WAAA,EAAa,SAAS,CAAC,CAAA;AACzC;;;;"}
1
+ {"version":3,"file":"useAriaAnnounceSearchState.mjs","sources":["../../../../../../../src/components/List/hooks/useAriaAnnounceSearchState.ts"],"sourcesContent":["import { useLocalizedStringFormatter } from \"react-aria\";\nimport locales from \"../locales/*.locale.json\";\nimport { announce } from \"@react-aria/live-announcer\";\nimport { useList } from \"@/index/default\";\nimport { useDebounceCallback } from \"usehooks-ts\";\nimport { useEffect } from \"react\";\n\nconst announceDebounceMs = 600;\n\nexport const useAriaAnnounceSearchState = (): void => {\n const formatter = useLocalizedStringFormatter(locales);\n const list = useList();\n const debouncedAnnounce = useDebounceCallback(announce, announceDebounceMs);\n\n const searchTerm = list.search?.value;\n const resultCount = list.batches.getTotalItemsCount();\n const isLoading = list.loader.loaderState.useIsLoading();\n\n useEffect(() => {\n if (isLoading || !searchTerm) {\n debouncedAnnounce.cancel();\n return;\n }\n\n const text = formatter.format(\n resultCount > 0\n ? \"list.search.announce.result\"\n : \"list.search.announce.noResult\",\n {\n resultCount,\n searchTerm,\n },\n );\n\n debouncedAnnounce(text, \"polite\");\n }, [searchTerm, resultCount, isLoading]);\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,MAAM,kBAAqB,GAAA,GAAA;AAEpB,MAAM,6BAA6B,MAAY;AACpD,EAAM,MAAA,SAAA,GAAY,4BAA4B,OAAO,CAAA;AACrD,EAAA,MAAM,OAAO,OAAQ,EAAA;AACrB,EAAM,MAAA,iBAAA,GAAoB,mBAAoB,CAAA,QAAA,EAAU,kBAAkB,CAAA;AAE1E,EAAM,MAAA,UAAA,GAAa,KAAK,MAAQ,EAAA,KAAA;AAChC,EAAM,MAAA,WAAA,GAAc,IAAK,CAAA,OAAA,CAAQ,kBAAmB,EAAA;AACpD,EAAA,MAAM,SAAY,GAAA,IAAA,CAAK,MAAO,CAAA,WAAA,CAAY,YAAa,EAAA;AAEvD,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,SAAA,IAAa,CAAC,UAAY,EAAA;AAC5B,MAAA,iBAAA,CAAkB,MAAO,EAAA;AACzB,MAAA;AAAA;AAGF,IAAA,MAAM,OAAO,SAAU,CAAA,MAAA;AAAA,MACrB,WAAA,GAAc,IACV,6BACA,GAAA,+BAAA;AAAA,MACJ;AAAA,QACE,WAAA;AAAA,QACA;AAAA;AACF,KACF;AAEA,IAAA,iBAAA,CAAkB,MAAM,QAAQ,CAAA;AAAA,GAC/B,EAAA,CAAC,UAAY,EAAA,WAAA,EAAa,SAAS,CAAC,CAAA;AACzC;;;;"}
@@ -11,9 +11,11 @@ import { Children, isValidElement } from 'react';
11
11
  import ReactMarkdown from 'react-markdown';
12
12
  import styles from './Markdown.module.scss.mjs';
13
13
  import { extractTextFromFirstChild } from '../../lib/react/remote.mjs';
14
+ import clsx from 'clsx';
15
+ import remarkGfm from 'remark-gfm';
14
16
 
15
17
  const Markdown = (props) => {
16
- const { children, color = "default", ...rest } = props;
18
+ const { children, color = "default", className, ...rest } = props;
17
19
  const headingAndLinkColor = color === "default" ? "primary" : color;
18
20
  const textColor = color === "default" ? void 0 : color;
19
21
  const components = {
@@ -46,7 +48,7 @@ const Markdown = (props) => {
46
48
  blockquote: (props2) => /* @__PURE__ */ jsx(Text, { color: textColor, children: /* @__PURE__ */ jsx("blockquote", { children: props2.children }) })
47
49
  };
48
50
  const textContent = extractTextFromFirstChild(children);
49
- return /* @__PURE__ */ jsx("div", { className: styles.markdown, ...rest, children: /* @__PURE__ */ jsx(ReactMarkdown, { components, children: textContent }) });
51
+ return /* @__PURE__ */ jsx("div", { className: clsx(styles.markdown, className), ...rest, children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children: textContent }) });
50
52
  };
51
53
 
52
54
  export { Markdown, Markdown as default };
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.mjs","sources":["../../../../../../src/components/Markdown/Markdown.tsx"],"sourcesContent":["import { CodeBlock } from \"@/components/CodeBlock\";\nimport { Heading } from \"@/components/Heading\";\nimport { InlineCode } from \"@/components/InlineCode\";\nimport { Link } from \"@/components/Link\";\nimport { Separator } from \"@/components/Separator\";\nimport { Text } from \"@/components/Text\";\nimport type { FC, ReactNode } from \"react\";\nimport React, { Children, isValidElement } from \"react\";\nimport type { Components, Options } from \"react-markdown\";\nimport ReactMarkdown from \"react-markdown\";\nimport styles from \"./Markdown.module.scss\";\nimport { extractTextFromFirstChild } from \"@/lib/react/remote\";\n\nexport interface MarkdownProps extends Omit<Options, \"components\"> {\n /** The color schema of the markdown component. */\n color?: \"dark\" | \"light\" | \"default\";\n}\n\n/** @flr-generate all */\nexport const Markdown: FC<MarkdownProps> = (props) => {\n const { children, color = \"default\", ...rest } = props;\n\n const headingAndLinkColor = color === \"default\" ? \"primary\" : color;\n const textColor = color === \"default\" ? undefined : color;\n\n const components: Components = {\n a: (props) => (\n <Link target=\"_blank\" color={headingAndLinkColor} href={props.href}>\n {props.children}\n </Link>\n ),\n p: (props) => (\n <Text elementType=\"p\" color={textColor}>\n {props.children}\n </Text>\n ),\n code: (props) => <InlineCode color={color}>{props.children}</InlineCode>,\n h1: (props) => (\n <Heading level={1} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h2: (props) => (\n <Heading level={2} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h3: (props) => (\n <Heading level={3} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h4: (props) => (\n <Heading level={4} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h5: (props) => (\n <Heading level={5} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h6: (props) => (\n <Heading level={6} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n hr: () => <Separator />,\n pre: (props) => {\n const preElementContent = Children.toArray(props.children)[0];\n\n return (\n <CodeBlock\n copyable={false}\n color={color}\n language={\n isValidElement<{ className?: string }>(preElementContent) &&\n preElementContent.props.className\n ? preElementContent.props.className.replace(\"language-\", \"\")\n : undefined\n }\n code={String(\n isValidElement<{ children: string }>(preElementContent)\n ? preElementContent.props.children\n : preElementContent,\n )}\n />\n );\n },\n ul: (props) => (\n <Text color={textColor}>\n <ul>{props.children as ReactNode}</ul>\n </Text>\n ),\n ol: (props) => (\n <Text color={textColor}>\n <ol>{props.children as ReactNode}</ol>\n </Text>\n ),\n blockquote: (props) => (\n <Text color={textColor}>\n <blockquote>{props.children}</blockquote>\n </Text>\n ),\n };\n\n const textContent = extractTextFromFirstChild(children);\n\n return (\n <div className={styles.markdown} {...rest}>\n <ReactMarkdown components={components}>{textContent}</ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"],"names":["props"],"mappings":"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"}
1
+ {"version":3,"file":"Markdown.mjs","sources":["../../../../../../src/components/Markdown/Markdown.tsx"],"sourcesContent":["import { CodeBlock } from \"@/components/CodeBlock\";\nimport { Heading } from \"@/components/Heading\";\nimport { InlineCode } from \"@/components/InlineCode\";\nimport { Link } from \"@/components/Link\";\nimport { Separator } from \"@/components/Separator\";\nimport { Text } from \"@/components/Text\";\nimport type { CSSProperties, FC, ReactNode } from \"react\";\nimport React, { Children, isValidElement } from \"react\";\nimport type { Components, Options } from \"react-markdown\";\nimport ReactMarkdown from \"react-markdown\";\nimport styles from \"./Markdown.module.scss\";\nimport { extractTextFromFirstChild } from \"@/lib/react/remote\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport clsx from \"clsx\";\nimport remarkGfm from \"remark-gfm\";\n\nexport interface MarkdownProps\n extends PropsWithClassName,\n Omit<Options, \"components\"> {\n /** The color schema of the markdown component. */\n color?: \"dark\" | \"light\" | \"default\";\n /** @internal */\n style?: CSSProperties;\n}\n\n/** @flr-generate all */\nexport const Markdown: FC<MarkdownProps> = (props) => {\n const { children, color = \"default\", className, ...rest } = props;\n\n const headingAndLinkColor = color === \"default\" ? \"primary\" : color;\n const textColor = color === \"default\" ? undefined : color;\n\n const components: Components = {\n a: (props) => (\n <Link target=\"_blank\" color={headingAndLinkColor} href={props.href}>\n {props.children}\n </Link>\n ),\n p: (props) => (\n <Text elementType=\"p\" color={textColor}>\n {props.children}\n </Text>\n ),\n code: (props) => <InlineCode color={color}>{props.children}</InlineCode>,\n h1: (props) => (\n <Heading level={1} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h2: (props) => (\n <Heading level={2} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h3: (props) => (\n <Heading level={3} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h4: (props) => (\n <Heading level={4} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h5: (props) => (\n <Heading level={5} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n h6: (props) => (\n <Heading level={6} color={headingAndLinkColor}>\n {props.children}\n </Heading>\n ),\n hr: () => <Separator />,\n pre: (props) => {\n const preElementContent = Children.toArray(props.children)[0];\n\n return (\n <CodeBlock\n copyable={false}\n color={color}\n language={\n isValidElement<{ className?: string }>(preElementContent) &&\n preElementContent.props.className\n ? preElementContent.props.className.replace(\"language-\", \"\")\n : undefined\n }\n code={String(\n isValidElement<{ children: string }>(preElementContent)\n ? preElementContent.props.children\n : preElementContent,\n )}\n />\n );\n },\n ul: (props) => (\n <Text color={textColor}>\n <ul>{props.children as ReactNode}</ul>\n </Text>\n ),\n ol: (props) => (\n <Text color={textColor}>\n <ol>{props.children as ReactNode}</ol>\n </Text>\n ),\n blockquote: (props) => (\n <Text color={textColor}>\n <blockquote>{props.children}</blockquote>\n </Text>\n ),\n };\n\n const textContent = extractTextFromFirstChild(children);\n\n return (\n <div className={clsx(styles.markdown, className)} {...rest}>\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>\n {textContent}\n </ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"],"names":["props"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ "use client"
2
+ /* */
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import { useState, useRef } from 'react';
5
+ import styles from './MarkdownEditor.module.scss.mjs';
6
+ import { Markdown } from '../Markdown/Markdown.mjs';
7
+ import { TextArea } from '../TextArea/TextArea.mjs';
8
+ import { Toolbar } from './components/Toolbar.mjs';
9
+ import clsx from 'clsx';
10
+ import { flowComponent } from '../../lib/componentFactory/flowComponent.mjs';
11
+ import { handleKeyDown } from './lib/handleKeyDown.mjs';
12
+
13
+ const MarkdownEditor = flowComponent("MarkdownEditor", (props) => {
14
+ const {
15
+ isDisabled,
16
+ children,
17
+ className,
18
+ value,
19
+ onChange,
20
+ rows,
21
+ autoResizeMaxRows,
22
+ ...rest
23
+ } = props;
24
+ const [markdown, setMarkdown] = useState(value ?? "");
25
+ const [mode, setMode] = useState("editor");
26
+ const textAreaRef = useRef(null);
27
+ const rootClassName = clsx(
28
+ styles.markdownEditor,
29
+ className,
30
+ styles[`mode-${mode}`]
31
+ );
32
+ return /* @__PURE__ */ jsxs(
33
+ TextArea,
34
+ {
35
+ ...rest,
36
+ isDisabled: isDisabled || mode === "preview",
37
+ className: rootClassName,
38
+ ref: textAreaRef,
39
+ value: markdown,
40
+ rows,
41
+ autoResizeMaxRows,
42
+ onChange: (v) => setMarkdown(v),
43
+ onKeyDown: (e) => handleKeyDown(e, textAreaRef, setMarkdown, onChange),
44
+ children: [
45
+ /* @__PURE__ */ jsx(
46
+ Toolbar,
47
+ {
48
+ markdown,
49
+ setMarkdown,
50
+ textAreaRef,
51
+ setMode,
52
+ mode,
53
+ isDisabled,
54
+ onChange
55
+ }
56
+ ),
57
+ /* @__PURE__ */ jsx(
58
+ Markdown,
59
+ {
60
+ className: styles.markdown,
61
+ style: {
62
+ maxHeight: `calc(var(--line-height--m) * ${autoResizeMaxRows ?? rows} + (var(--form-control--padding-y) * 2))`
63
+ },
64
+ children: markdown
65
+ }
66
+ ),
67
+ children
68
+ ]
69
+ }
70
+ );
71
+ });
72
+
73
+ export { MarkdownEditor, MarkdownEditor as default };
74
+ //# sourceMappingURL=MarkdownEditor.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownEditor.mjs","sources":["../../../../../../src/components/MarkdownEditor/MarkdownEditor.tsx"],"sourcesContent":["import React, { useRef, useState } from \"react\";\nimport styles from \"./MarkdownEditor.module.scss\";\nimport { Markdown } from \"@/components/Markdown\";\nimport { TextArea, type TextAreaProps } from \"@/components/TextArea\";\nimport { Toolbar } from \"@/components/MarkdownEditor/components/Toolbar\";\nimport clsx from \"clsx\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { handleKeyDown } from \"@/components/MarkdownEditor/lib/handleKeyDown\";\n\nexport type MarkdownEditorMode = \"editor\" | \"preview\";\n\nexport type MarkdownEditorProps = TextAreaProps;\n\n/** @flr-generate all */\nexport const MarkdownEditor = flowComponent(\"MarkdownEditor\", (props) => {\n const {\n isDisabled,\n children,\n className,\n value,\n onChange,\n rows,\n autoResizeMaxRows,\n ...rest\n } = props;\n\n const [markdown, setMarkdown] = useState(value ?? \"\");\n const [mode, setMode] = useState<MarkdownEditorMode>(\"editor\");\n const textAreaRef = useRef<HTMLTextAreaElement>(null);\n\n const rootClassName = clsx(\n styles.markdownEditor,\n className,\n styles[`mode-${mode}`],\n );\n\n return (\n <TextArea\n {...rest}\n isDisabled={isDisabled || mode === \"preview\"}\n className={rootClassName}\n ref={textAreaRef}\n value={markdown}\n rows={rows}\n autoResizeMaxRows={autoResizeMaxRows}\n onChange={(v) => setMarkdown(v)}\n onKeyDown={(e) => handleKeyDown(e, textAreaRef, setMarkdown, onChange)}\n >\n <Toolbar\n markdown={markdown}\n setMarkdown={setMarkdown}\n textAreaRef={textAreaRef}\n setMode={setMode}\n mode={mode}\n isDisabled={isDisabled}\n onChange={onChange}\n />\n\n <Markdown\n className={styles.markdown}\n style={{\n maxHeight: `calc(var(--line-height--m) * ${autoResizeMaxRows ?? rows} + (var(--form-control--padding-y) * 2))`,\n }}\n >\n {markdown}\n </Markdown>\n\n {children}\n </TextArea>\n );\n});\n\nexport default MarkdownEditor;\n"],"names":[],"mappings":";;;;;;;;;;AAcO,MAAM,cAAiB,GAAA,aAAA,CAAc,gBAAkB,EAAA,CAAC,KAAU,KAAA;AACvE,EAAM,MAAA;AAAA,IACJ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,iBAAA;AAAA,IACA,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAAS,SAAS,EAAE,CAAA;AACpD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,QAAQ,CAAA;AAC7D,EAAM,MAAA,WAAA,GAAc,OAA4B,IAAI,CAAA;AAEpD,EAAA,MAAM,aAAgB,GAAA,IAAA;AAAA,IACpB,MAAO,CAAA,cAAA;AAAA,IACP,SAAA;AAAA,IACA,MAAA,CAAO,CAAQ,KAAA,EAAA,IAAI,CAAE,CAAA;AAAA,GACvB;AAEA,EACE,uBAAA,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,UAAA,EAAY,cAAc,IAAS,KAAA,SAAA;AAAA,MACnC,SAAW,EAAA,aAAA;AAAA,MACX,GAAK,EAAA,WAAA;AAAA,MACL,KAAO,EAAA,QAAA;AAAA,MACP,IAAA;AAAA,MACA,iBAAA;AAAA,MACA,QAAU,EAAA,CAAC,CAAM,KAAA,WAAA,CAAY,CAAC,CAAA;AAAA,MAC9B,WAAW,CAAC,CAAA,KAAM,cAAc,CAAG,EAAA,WAAA,EAAa,aAAa,QAAQ,CAAA;AAAA,MAErE,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,QAAA;AAAA,YACA,WAAA;AAAA,YACA,WAAA;AAAA,YACA,OAAA;AAAA,YACA,IAAA;AAAA,YACA,UAAA;AAAA,YACA;AAAA;AAAA,SACF;AAAA,wBAEA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,WAAW,MAAO,CAAA,QAAA;AAAA,YAClB,KAAO,EAAA;AAAA,cACL,SAAA,EAAW,CAAgC,6BAAA,EAAA,iBAAA,IAAqB,IAAI,CAAA,wCAAA;AAAA,aACtE;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA,SACH;AAAA,QAEC;AAAA;AAAA;AAAA,GACH;AAEJ,CAAC;;;;"}
@@ -0,0 +1,19 @@
1
+ "use client"
2
+ /* */
3
+ const markdownEditor = "flow--markdown-editor";
4
+ const toolbar = "flow--markdown-editor--toolbar";
5
+ const toolbarButtons = "flow--markdown-editor--toolbar-buttons";
6
+ const modeButton = "flow--markdown-editor--mode-button";
7
+ const markdown = "flow--markdown-editor--markdown";
8
+ const styles = {
9
+ markdownEditor: markdownEditor,
10
+ "mode-editor": "flow--markdown-editor--mode-editor",
11
+ "mode-preview": "flow--markdown-editor--mode-preview",
12
+ toolbar: toolbar,
13
+ toolbarButtons: toolbarButtons,
14
+ modeButton: modeButton,
15
+ markdown: markdown
16
+ };
17
+
18
+ export { styles as default, markdown, markdownEditor, modeButton, toolbar, toolbarButtons };
19
+ //# sourceMappingURL=MarkdownEditor.module.scss.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownEditor.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,29 @@
1
+ "use client"
2
+ /* */
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import { Button } from '../../Button/Button.mjs';
6
+ import { useLocalizedStringFormatter } from 'react-aria';
7
+ import locales from '../../../../../_virtual/_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs';
8
+ import styles from '../MarkdownEditor.module.scss.mjs';
9
+
10
+ const ModeButton = (props) => {
11
+ const { setMode, mode, isDisabled } = props;
12
+ const stringFormatter = useLocalizedStringFormatter(locales);
13
+ const otherMode = mode === "editor" ? "preview" : "editor";
14
+ return /* @__PURE__ */ jsx(
15
+ Button,
16
+ {
17
+ isDisabled,
18
+ className: styles.modeButton,
19
+ size: "s",
20
+ variant: "plain",
21
+ color: "dark",
22
+ onPress: () => setMode(otherMode),
23
+ children: stringFormatter.format(`mode.${otherMode}`)
24
+ }
25
+ );
26
+ };
27
+
28
+ export { ModeButton };
29
+ //# sourceMappingURL=ModeButton.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModeButton.mjs","sources":["../../../../../../../src/components/MarkdownEditor/components/ModeButton.tsx"],"sourcesContent":["import React, { type FC } from \"react\";\nimport { Button } from \"@/components/Button\";\nimport { useLocalizedStringFormatter } from \"react-aria\";\nimport locales from \"../locales/*.locale.json\";\nimport type { MarkdownEditorMode } from \"@/components/MarkdownEditor/MarkdownEditor\";\nimport styles from \"../MarkdownEditor.module.scss\";\n\ninterface Props {\n mode: MarkdownEditorMode;\n setMode: (mode: MarkdownEditorMode) => void;\n isDisabled?: boolean;\n}\n\nexport const ModeButton: FC<Props> = (props) => {\n const { setMode, mode, isDisabled } = props;\n\n const stringFormatter = useLocalizedStringFormatter(locales);\n\n const otherMode = mode === \"editor\" ? \"preview\" : \"editor\";\n\n return (\n <Button\n isDisabled={isDisabled}\n className={styles.modeButton}\n size=\"s\"\n variant=\"plain\"\n color=\"dark\"\n onPress={() => setMode(otherMode)}\n >\n {stringFormatter.format(`mode.${otherMode}`)}\n </Button>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAaa,MAAA,UAAA,GAAwB,CAAC,KAAU,KAAA;AAC9C,EAAA,MAAM,EAAE,OAAA,EAAS,IAAM,EAAA,UAAA,EAAe,GAAA,KAAA;AAEtC,EAAM,MAAA,eAAA,GAAkB,4BAA4B,OAAO,CAAA;AAE3D,EAAM,MAAA,SAAA,GAAY,IAAS,KAAA,QAAA,GAAW,SAAY,GAAA,QAAA;AAElD,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,UAAA;AAAA,MACA,WAAW,MAAO,CAAA,UAAA;AAAA,MAClB,IAAK,EAAA,GAAA;AAAA,MACL,OAAQ,EAAA,OAAA;AAAA,MACR,KAAM,EAAA,MAAA;AAAA,MACN,OAAA,EAAS,MAAM,OAAA,CAAQ,SAAS,CAAA;AAAA,MAE/B,QAAgB,EAAA,eAAA,CAAA,MAAA,CAAO,CAAQ,KAAA,EAAA,SAAS,CAAE,CAAA;AAAA;AAAA,GAC7C;AAEJ;;;;"}
@@ -0,0 +1,39 @@
1
+ "use client"
2
+ /* */
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import styles from '../MarkdownEditor.module.scss.mjs';
6
+ import { Icon } from '../../Icon/Icon.mjs';
7
+ import { IconBold, IconItalic, IconStrikethrough, IconQuoteFilled, IconList, IconListNumbers } from '@tabler/icons-react';
8
+ import '../../../lib/viewComponentContext/viewComponentContext.mjs';
9
+ import { IconCode } from '../../Icon/components/icons/IconCode.mjs';
10
+ import { IconLink } from '../../Icon/components/icons/IconLink.mjs';
11
+ import { ToolbarButton } from './ToolbarButton.mjs';
12
+ import { ModeButton } from './ModeButton.mjs';
13
+
14
+ const Toolbar = (props) => {
15
+ const { setMode, ...rest } = props;
16
+ return /* @__PURE__ */ jsxs("header", { className: styles.toolbar, role: "toolbar", children: [
17
+ /* @__PURE__ */ jsxs("div", { className: styles.toolbarButtons, children: [
18
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "bold", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconBold, {}) }) }),
19
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "italic", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconItalic, {}) }) }),
20
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "strikeThrough", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconStrikethrough, {}) }) }),
21
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "quote", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconQuoteFilled, {}) }) }),
22
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "code", children: /* @__PURE__ */ jsx(IconCode, {}) }),
23
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "link", children: /* @__PURE__ */ jsx(IconLink, {}) }),
24
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "unorderedList", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconList, {}) }) }),
25
+ /* @__PURE__ */ jsx(ToolbarButton, { ...rest, type: "orderedList", children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(IconListNumbers, {}) }) })
26
+ ] }),
27
+ /* @__PURE__ */ jsx(
28
+ ModeButton,
29
+ {
30
+ setMode,
31
+ mode: props.mode,
32
+ isDisabled: props.isDisabled
33
+ }
34
+ )
35
+ ] });
36
+ };
37
+
38
+ export { Toolbar };
39
+ //# sourceMappingURL=Toolbar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toolbar.mjs","sources":["../../../../../../../src/components/MarkdownEditor/components/Toolbar.tsx"],"sourcesContent":["import React, { type FC, type RefObject } from \"react\";\nimport styles from \"@/components/MarkdownEditor/MarkdownEditor.module.scss\";\nimport { Icon } from \"@/components/Icon\";\nimport {\n IconBold,\n IconItalic,\n IconList,\n IconListNumbers,\n IconQuoteFilled,\n IconStrikethrough,\n} from \"@tabler/icons-react\";\nimport { IconCode, IconLink } from \"@/components/Icon/components/icons\";\nimport { ToolbarButton } from \"@/components/MarkdownEditor/components/ToolbarButton\";\nimport type { MarkdownEditorMode } from \"@/components/MarkdownEditor/MarkdownEditor\";\nimport { ModeButton } from \"@/components/MarkdownEditor/components/ModeButton\";\n\ninterface Props {\n markdown: string;\n setMarkdown: (markdown: string) => void;\n textAreaRef: RefObject<HTMLTextAreaElement | null>;\n setMode: (mode: MarkdownEditorMode) => void;\n mode: MarkdownEditorMode;\n isDisabled?: boolean;\n onChange?: (markdown: string) => void;\n}\n\nexport const Toolbar: FC<Props> = (props) => {\n const { setMode, ...rest } = props;\n\n return (\n <header className={styles.toolbar} role=\"toolbar\">\n <div className={styles.toolbarButtons}>\n <ToolbarButton {...rest} type=\"bold\">\n <Icon>\n <IconBold />\n </Icon>\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"italic\">\n <Icon>\n <IconItalic />\n </Icon>\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"strikeThrough\">\n <Icon>\n <IconStrikethrough />\n </Icon>\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"quote\">\n <Icon>\n <IconQuoteFilled />\n </Icon>\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"code\">\n <IconCode />\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"link\">\n <IconLink />\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"unorderedList\">\n <Icon>\n <IconList />\n </Icon>\n </ToolbarButton>\n\n <ToolbarButton {...rest} type=\"orderedList\">\n <Icon>\n <IconListNumbers />\n </Icon>\n </ToolbarButton>\n </div>\n\n <ModeButton\n setMode={setMode}\n mode={props.mode}\n isDisabled={props.isDisabled}\n />\n </header>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AA0Ba,MAAA,OAAA,GAAqB,CAAC,KAAU,KAAA;AAC3C,EAAA,MAAM,EAAE,OAAA,EAAS,GAAG,IAAA,EAAS,GAAA,KAAA;AAE7B,EAAA,4BACG,QAAO,EAAA,EAAA,SAAA,EAAW,MAAO,CAAA,OAAA,EAAS,MAAK,SACtC,EAAA,QAAA,EAAA;AAAA,oBAAC,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,cACrB,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,aAAA,EAAA,EAAe,GAAG,IAAA,EAAM,IAAK,EAAA,MAAA,EAC5B,8BAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,CAAA,EACZ,CACF,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,aAAe,EAAA,EAAA,GAAG,IAAM,EAAA,IAAA,EAAK,QAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,CAAA,EACd,CACF,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,aAAe,EAAA,EAAA,GAAG,IAAM,EAAA,IAAA,EAAK,eAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,iBAAkB,EAAA,EAAA,CAAA,EACrB,CACF,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,aAAe,EAAA,EAAA,GAAG,IAAM,EAAA,IAAA,EAAK,OAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,eAAgB,EAAA,EAAA,CAAA,EACnB,CACF,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,iBAAe,GAAG,IAAA,EAAM,MAAK,MAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,YAAS,CACZ,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,iBAAe,GAAG,IAAA,EAAM,MAAK,MAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,YAAS,CACZ,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,aAAe,EAAA,EAAA,GAAG,IAAM,EAAA,IAAA,EAAK,eAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,CAAA,EACZ,CACF,EAAA,CAAA;AAAA,sBAEA,GAAA,CAAC,aAAe,EAAA,EAAA,GAAG,IAAM,EAAA,IAAA,EAAK,aAC5B,EAAA,QAAA,kBAAA,GAAA,CAAC,IACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,eAAgB,EAAA,EAAA,CAAA,EACnB,CACF,EAAA;AAAA,KACF,EAAA,CAAA;AAAA,oBAEA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAA;AAAA,QACA,MAAM,KAAM,CAAA,IAAA;AAAA,QACZ,YAAY,KAAM,CAAA;AAAA;AAAA;AACpB,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,37 @@
1
+ "use client"
2
+ /* */
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import { insertAtCursor } from '../lib/insertAtCursor.mjs';
6
+ import { Button } from '../../Button/Button.mjs';
7
+ import { useLocalizedStringFormatter } from 'react-aria';
8
+ import locales from '../../../../../_virtual/_.locale.json@bb0db7b5021f874310cbe5b6cc3d9cac.mjs';
9
+
10
+ const ToolbarButton = (props) => {
11
+ const {
12
+ markdown,
13
+ setMarkdown,
14
+ textAreaRef,
15
+ children,
16
+ isDisabled,
17
+ type,
18
+ onChange,
19
+ mode
20
+ } = props;
21
+ const stringFormatter = useLocalizedStringFormatter(locales);
22
+ return /* @__PURE__ */ jsx(
23
+ Button,
24
+ {
25
+ isDisabled: isDisabled || mode === "preview",
26
+ "aria-label": stringFormatter.format(`toolbar.${type}`),
27
+ size: "s",
28
+ variant: "plain",
29
+ color: "dark",
30
+ onPress: () => insertAtCursor(markdown, setMarkdown, textAreaRef, type, onChange),
31
+ children
32
+ }
33
+ );
34
+ };
35
+
36
+ export { ToolbarButton };
37
+ //# sourceMappingURL=ToolbarButton.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolbarButton.mjs","sources":["../../../../../../../src/components/MarkdownEditor/components/ToolbarButton.tsx"],"sourcesContent":["import React, { type FC, type PropsWithChildren, type RefObject } from \"react\";\nimport {\n insertAtCursor,\n type InsertType,\n} from \"@/components/MarkdownEditor/lib/insertAtCursor\";\nimport { Button } from \"@/components/Button\";\nimport { useLocalizedStringFormatter } from \"react-aria\";\nimport locales from \"../locales/*.locale.json\";\nimport type { MarkdownEditorMode } from \"@/components/MarkdownEditor/MarkdownEditor\";\n\ninterface Props extends PropsWithChildren {\n markdown: string;\n setMarkdown: (markdown: string) => void;\n textAreaRef: RefObject<HTMLTextAreaElement | null>;\n isDisabled?: boolean;\n type: InsertType;\n onChange?: (markdown: string) => void;\n mode: MarkdownEditorMode;\n}\n\nexport const ToolbarButton: FC<Props> = (props) => {\n const {\n markdown,\n setMarkdown,\n textAreaRef,\n children,\n isDisabled,\n type,\n onChange,\n mode,\n } = props;\n\n const stringFormatter = useLocalizedStringFormatter(locales);\n\n return (\n <Button\n isDisabled={isDisabled || mode === \"preview\"}\n aria-label={stringFormatter.format(`toolbar.${type}`)}\n size=\"s\"\n variant=\"plain\"\n color=\"dark\"\n onPress={() =>\n insertAtCursor(markdown, setMarkdown, textAreaRef, type, onChange)\n }\n >\n {children}\n </Button>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAoBa,MAAA,aAAA,GAA2B,CAAC,KAAU,KAAA;AACjD,EAAM,MAAA;AAAA,IACJ,QAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AAEJ,EAAM,MAAA,eAAA,GAAkB,4BAA4B,OAAO,CAAA;AAE3D,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY,cAAc,IAAS,KAAA,SAAA;AAAA,MACnC,YAAY,EAAA,eAAA,CAAgB,MAAO,CAAA,CAAA,QAAA,EAAW,IAAI,CAAE,CAAA,CAAA;AAAA,MACpD,IAAK,EAAA,GAAA;AAAA,MACL,OAAQ,EAAA,OAAA;AAAA,MACR,KAAM,EAAA,MAAA;AAAA,MACN,SAAS,MACP,cAAA,CAAe,UAAU,WAAa,EAAA,WAAA,EAAa,MAAM,QAAQ,CAAA;AAAA,MAGlE;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -0,0 +1,72 @@
1
+ "use client"
2
+ /* */
3
+ const scrollToCursor = (textarea) => {
4
+ const { selectionStart } = textarea;
5
+ const lineHeight = parseInt(
6
+ getComputedStyle(textarea).lineHeight || "20",
7
+ 10
8
+ );
9
+ const lines = textarea.value.slice(0, selectionStart).split("\n").length;
10
+ textarea.scrollTop = (lines - 1) * lineHeight;
11
+ };
12
+ const handleKeyDown = (e, textAreaRef, setMarkdown, onChange) => {
13
+ if (e.key !== "Enter") return;
14
+ const textarea = textAreaRef.current;
15
+ if (!textarea) return;
16
+ const start = textarea.selectionStart;
17
+ const end = textarea.selectionEnd;
18
+ const value = textarea.value;
19
+ const before = value.slice(0, start);
20
+ const after = value.slice(end);
21
+ const lineStart = before.lastIndexOf("\n") + 1;
22
+ const currentLine = before.slice(lineStart);
23
+ const orderedMatch = currentLine.match(/^(\s*)(\d+)\.\s+/);
24
+ const unorderedMatch = currentLine.match(/^(\s*)([-*+])\s+/);
25
+ if ((orderedMatch || unorderedMatch) && currentLine.trim().match(/^([-*+]|\d+\.)$/)) {
26
+ e.preventDefault();
27
+ const newText = value.slice(0, lineStart) + "\n" + after;
28
+ setMarkdown(newText);
29
+ if (onChange) {
30
+ onChange(newText);
31
+ }
32
+ requestAnimationFrame(() => {
33
+ textarea.selectionStart = textarea.selectionEnd = lineStart + 1;
34
+ scrollToCursor(textarea);
35
+ });
36
+ return;
37
+ }
38
+ if (orderedMatch) {
39
+ e.preventDefault();
40
+ const indent = orderedMatch[1];
41
+ const nextNum = parseInt(orderedMatch[2] ?? "", 10) + 1;
42
+ const insert = `
43
+ ${indent}${nextNum}. `;
44
+ const newText = before + insert + after;
45
+ setMarkdown(newText);
46
+ if (onChange) {
47
+ onChange(newText);
48
+ }
49
+ requestAnimationFrame(() => {
50
+ textarea.selectionStart = textarea.selectionEnd = start + insert.length;
51
+ scrollToCursor(textarea);
52
+ });
53
+ } else if (unorderedMatch) {
54
+ e.preventDefault();
55
+ const indent = unorderedMatch[1];
56
+ const bullet = unorderedMatch[2];
57
+ const insert = `
58
+ ${indent}${bullet} `;
59
+ const newText = before + insert + after;
60
+ setMarkdown(newText);
61
+ if (onChange) {
62
+ onChange(newText);
63
+ }
64
+ requestAnimationFrame(() => {
65
+ textarea.selectionStart = textarea.selectionEnd = start + insert.length;
66
+ scrollToCursor(textarea);
67
+ });
68
+ }
69
+ };
70
+
71
+ export { handleKeyDown };
72
+ //# sourceMappingURL=handleKeyDown.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleKeyDown.mjs","sources":["../../../../../../../src/components/MarkdownEditor/lib/handleKeyDown.ts"],"sourcesContent":["import type { KeyboardEvent, RefObject } from \"react\";\n\nconst scrollToCursor = (textarea: HTMLTextAreaElement) => {\n const { selectionStart } = textarea;\n const lineHeight = parseInt(\n getComputedStyle(textarea).lineHeight || \"20\",\n 10,\n );\n const lines = textarea.value.slice(0, selectionStart).split(\"\\n\").length;\n textarea.scrollTop = (lines - 1) * lineHeight;\n};\n\nexport const handleKeyDown = (\n e: KeyboardEvent,\n textAreaRef: RefObject<HTMLTextAreaElement | null>,\n setMarkdown: (markdown: string) => void,\n onChange?: (markdown: string) => void,\n) => {\n if (e.key !== \"Enter\") return;\n\n const textarea = textAreaRef.current;\n\n if (!textarea) return;\n\n const start = textarea.selectionStart;\n const end = textarea.selectionEnd;\n const value = textarea.value;\n\n const before = value.slice(0, start);\n const after = value.slice(end);\n const lineStart = before.lastIndexOf(\"\\n\") + 1;\n const currentLine = before.slice(lineStart);\n\n const orderedMatch = currentLine.match(/^(\\s*)(\\d+)\\.\\s+/);\n const unorderedMatch = currentLine.match(/^(\\s*)([-*+])\\s+/);\n\n if (\n (orderedMatch || unorderedMatch) &&\n currentLine.trim().match(/^([-*+]|\\d+\\.)$/)\n ) {\n e.preventDefault();\n const newText = value.slice(0, lineStart) + \"\\n\" + after;\n\n setMarkdown(newText);\n\n if (onChange) {\n onChange(newText);\n }\n\n requestAnimationFrame(() => {\n textarea.selectionStart = textarea.selectionEnd = lineStart + 1;\n scrollToCursor(textarea);\n });\n return;\n }\n\n if (orderedMatch) {\n e.preventDefault();\n const indent = orderedMatch[1];\n const nextNum = parseInt(orderedMatch[2] ?? \"\", 10) + 1;\n const insert = `\\n${indent}${nextNum}. `;\n\n const newText = before + insert + after;\n\n setMarkdown(newText);\n\n if (onChange) {\n onChange(newText);\n }\n\n requestAnimationFrame(() => {\n textarea.selectionStart = textarea.selectionEnd = start + insert.length;\n scrollToCursor(textarea);\n });\n } else if (unorderedMatch) {\n e.preventDefault();\n const indent = unorderedMatch[1];\n const bullet = unorderedMatch[2];\n const insert = `\\n${indent}${bullet} `;\n\n const newText = before + insert + after;\n\n setMarkdown(newText);\n\n if (onChange) {\n onChange(newText);\n }\n\n requestAnimationFrame(() => {\n textarea.selectionStart = textarea.selectionEnd = start + insert.length;\n scrollToCursor(textarea);\n });\n }\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ "use client"
2
+ /* */
3
+ const markdownSyntax = {
4
+ bold: { before: "**", after: "**", toggleable: true },
5
+ italic: { before: "_", after: "_", toggleable: true },
6
+ strikeThrough: { before: "~~", after: "~~", toggleable: true },
7
+ quote: { before: "> " },
8
+ code: { before: "`", after: "`", toggleable: true },
9
+ link: { before: "[", after: "](https://)" },
10
+ unorderedList: { before: "- " },
11
+ orderedList: { before: "1. " }
12
+ };
13
+ const getLineStart = (text, pos) => {
14
+ const lastNewline = text.lastIndexOf("\n", pos - 1);
15
+ return lastNewline === -1 ? 0 : lastNewline + 1;
16
+ };
17
+ const getLineEnd = (text, pos) => {
18
+ const nextNewline = text.indexOf("\n", pos);
19
+ return nextNewline === -1 ? text.length : nextNewline;
20
+ };
21
+ const insertAtCursor = (markdown, setMarkdown, textAreaRef, type, onChange) => {
22
+ const textarea = textAreaRef.current;
23
+ if (!textarea) return;
24
+ const { before, after = "", toggleable = false } = markdownSyntax[type];
25
+ const start = textarea.selectionStart;
26
+ const end = textarea.selectionEnd;
27
+ const selectedText = markdown.substring(start, end);
28
+ const lines = selectedText.split("\n");
29
+ let newText = markdown;
30
+ let selectionStart = start;
31
+ let selectionEnd = end;
32
+ if (type === "code" && selectedText.includes("\n")) {
33
+ newText = markdown.substring(0, start) + "```\n" + selectedText + "\n```\n" + markdown.substring(end);
34
+ selectionStart = start + 4;
35
+ selectionEnd = selectionStart + selectedText.length;
36
+ } else if (type === "orderedList") {
37
+ if (selectedText) {
38
+ const numbered = lines.map((line, i) => `${i + 1}. ${line}`).join("\n");
39
+ newText = markdown.substring(0, start) + numbered + markdown.substring(end);
40
+ selectionStart = start;
41
+ selectionEnd = start + numbered.length;
42
+ } else {
43
+ const lineStart = getLineStart(markdown, start);
44
+ const lineEnd = getLineEnd(markdown, start);
45
+ const numberedLine = `1. ${markdown.substring(lineStart, lineEnd)}`;
46
+ newText = markdown.substring(0, lineStart) + before + markdown.substring(lineStart);
47
+ selectionStart = lineStart + numberedLine.length;
48
+ selectionEnd = selectionStart;
49
+ }
50
+ } else if (type === "unorderedList") {
51
+ if (selectedText) {
52
+ const bulleted = lines.map((line) => `${before}${line}`).join("\n");
53
+ newText = markdown.substring(0, start) + bulleted + markdown.substring(end);
54
+ selectionStart = start;
55
+ selectionEnd = start + bulleted.length;
56
+ } else {
57
+ const lineStart = getLineStart(markdown, start);
58
+ const lineEnd = getLineEnd(markdown, start);
59
+ const bulletedLine = `- ${markdown.substring(lineStart, lineEnd)}`;
60
+ newText = markdown.substring(0, lineStart) + before + markdown.substring(lineStart);
61
+ selectionStart = lineStart + bulletedLine.length;
62
+ selectionEnd = selectionStart;
63
+ }
64
+ } else if (type === "quote") {
65
+ if (selectedText) {
66
+ const quoted = lines.map((line) => `${before}${line}`).join("\n");
67
+ newText = markdown.substring(0, start) + quoted + markdown.substring(end);
68
+ selectionStart = start;
69
+ selectionEnd = start + quoted.length;
70
+ } else {
71
+ const quoteLine = `
72
+ ${before} `;
73
+ newText = markdown.substring(0, start) + quoteLine + markdown.substring(end);
74
+ selectionStart = start + quoteLine.length;
75
+ selectionEnd = selectionStart;
76
+ }
77
+ } else if (toggleable) {
78
+ const prefix = markdown.substring(start - before.length, start);
79
+ const suffix = markdown.substring(end, end + after.length);
80
+ const isSurrounded = prefix === before && suffix === after;
81
+ const isWrappedInside = selectedText.startsWith(before) && selectedText.endsWith(after);
82
+ if (isSurrounded) {
83
+ newText = markdown.substring(0, start - before.length) + selectedText + markdown.substring(end + after.length);
84
+ selectionStart = start - before.length;
85
+ selectionEnd = selectionStart + selectedText.length;
86
+ } else if (isWrappedInside) {
87
+ const unwrapped = selectedText.slice(
88
+ before.length,
89
+ selectedText.length - after.length
90
+ );
91
+ newText = markdown.substring(0, start) + unwrapped + markdown.substring(end);
92
+ selectionStart = start;
93
+ selectionEnd = start + unwrapped.length;
94
+ } else {
95
+ newText = markdown.substring(0, start) + before + selectedText + after + markdown.substring(end);
96
+ if (selectedText.length === 0) {
97
+ selectionStart = start + before.length;
98
+ selectionEnd = selectionStart;
99
+ } else {
100
+ selectionStart = start + before.length;
101
+ selectionEnd = selectionStart + selectedText.length;
102
+ }
103
+ }
104
+ } else if (type === "link") {
105
+ let linkText = "";
106
+ let linkUrl = "";
107
+ let inserted = "";
108
+ let cursorOffsetStart = 0;
109
+ const isValidUrl = (str) => {
110
+ try {
111
+ new URL(str);
112
+ return true;
113
+ } catch {
114
+ return false;
115
+ }
116
+ };
117
+ if (selectedText) {
118
+ if (isValidUrl(selectedText)) {
119
+ linkUrl = selectedText;
120
+ inserted = `[](${linkUrl})`;
121
+ cursorOffsetStart = start + 1;
122
+ } else {
123
+ linkText = selectedText;
124
+ inserted = `[${linkText}]()`;
125
+ cursorOffsetStart = start + inserted.indexOf("](") + 2;
126
+ }
127
+ } else {
128
+ inserted = `[](https://)`;
129
+ cursorOffsetStart = start + 1;
130
+ }
131
+ newText = markdown.substring(0, start) + inserted + markdown.substring(end);
132
+ selectionStart = selectionEnd = cursorOffsetStart;
133
+ } else {
134
+ newText = markdown.substring(0, start) + before + selectedText + after + markdown.substring(end);
135
+ if (selectedText.length === 0) {
136
+ selectionStart = start + before.length;
137
+ selectionEnd = selectionStart;
138
+ } else {
139
+ selectionStart = start + before.length;
140
+ selectionEnd = selectionStart + selectedText.length;
141
+ }
142
+ }
143
+ setMarkdown(newText);
144
+ if (onChange) onChange(newText);
145
+ requestAnimationFrame(() => {
146
+ textarea.setSelectionRange(selectionStart, selectionEnd);
147
+ textarea.focus();
148
+ });
149
+ };
150
+
151
+ export { insertAtCursor };
152
+ //# sourceMappingURL=insertAtCursor.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insertAtCursor.mjs","sources":["../../../../../../../src/components/MarkdownEditor/lib/insertAtCursor.ts"],"sourcesContent":["import type { RefObject } from \"react\";\n\nexport type InsertType =\n | \"bold\"\n | \"italic\"\n | \"strikeThrough\"\n | \"quote\"\n | \"code\"\n | \"link\"\n | \"unorderedList\"\n | \"orderedList\";\n\nconst markdownSyntax: Record<\n InsertType,\n { before: string; after?: string; toggleable?: boolean }\n> = {\n bold: { before: \"**\", after: \"**\", toggleable: true },\n italic: { before: \"_\", after: \"_\", toggleable: true },\n strikeThrough: { before: \"~~\", after: \"~~\", toggleable: true },\n quote: { before: \"> \" },\n code: { before: \"`\", after: \"`\", toggleable: true },\n link: { before: \"[\", after: \"](https://)\" },\n unorderedList: { before: \"- \" },\n orderedList: { before: \"1. \" },\n};\n\nconst getLineStart = (text: string, pos: number) => {\n const lastNewline = text.lastIndexOf(\"\\n\", pos - 1);\n return lastNewline === -1 ? 0 : lastNewline + 1;\n};\n\nconst getLineEnd = (text: string, pos: number) => {\n const nextNewline = text.indexOf(\"\\n\", pos);\n return nextNewline === -1 ? text.length : nextNewline;\n};\n\nexport const insertAtCursor = (\n markdown: string,\n setMarkdown: (markdown: string) => void,\n textAreaRef: RefObject<HTMLTextAreaElement | null>,\n type: InsertType,\n onChange?: (markdown: string) => void,\n) => {\n const textarea = textAreaRef.current;\n if (!textarea) return;\n\n const { before, after = \"\", toggleable = false } = markdownSyntax[type];\n const start = textarea.selectionStart;\n const end = textarea.selectionEnd;\n const selectedText = markdown.substring(start, end);\n const lines = selectedText.split(\"\\n\");\n\n let newText = markdown;\n let selectionStart = start;\n let selectionEnd = end;\n\n if (type === \"code\" && selectedText.includes(\"\\n\")) {\n newText =\n markdown.substring(0, start) +\n \"```\\n\" +\n selectedText +\n \"\\n```\\n\" +\n markdown.substring(end);\n selectionStart = start + 4;\n selectionEnd = selectionStart + selectedText.length;\n } else if (type === \"orderedList\") {\n if (selectedText) {\n const numbered = lines.map((line, i) => `${i + 1}. ${line}`).join(\"\\n\");\n newText =\n markdown.substring(0, start) + numbered + markdown.substring(end);\n selectionStart = start;\n selectionEnd = start + numbered.length;\n } else {\n const lineStart = getLineStart(markdown, start);\n const lineEnd = getLineEnd(markdown, start);\n const numberedLine = `1. ${markdown.substring(lineStart, lineEnd)}`;\n\n newText =\n markdown.substring(0, lineStart) +\n before +\n markdown.substring(lineStart);\n selectionStart = lineStart + numberedLine.length;\n selectionEnd = selectionStart;\n }\n } else if (type === \"unorderedList\") {\n if (selectedText) {\n const bulleted = lines.map((line) => `${before}${line}`).join(\"\\n\");\n newText =\n markdown.substring(0, start) + bulleted + markdown.substring(end);\n selectionStart = start;\n selectionEnd = start + bulleted.length;\n } else {\n const lineStart = getLineStart(markdown, start);\n const lineEnd = getLineEnd(markdown, start);\n const bulletedLine = `- ${markdown.substring(lineStart, lineEnd)}`;\n\n newText =\n markdown.substring(0, lineStart) +\n before +\n markdown.substring(lineStart);\n selectionStart = lineStart + bulletedLine.length;\n selectionEnd = selectionStart;\n }\n } else if (type === \"quote\") {\n if (selectedText) {\n const quoted = lines.map((line) => `${before}${line}`).join(\"\\n\");\n newText = markdown.substring(0, start) + quoted + markdown.substring(end);\n selectionStart = start;\n selectionEnd = start + quoted.length;\n } else {\n const quoteLine = `\\n${before} `;\n newText =\n markdown.substring(0, start) + quoteLine + markdown.substring(end);\n selectionStart = start + quoteLine.length;\n selectionEnd = selectionStart;\n }\n } else if (toggleable) {\n const prefix = markdown.substring(start - before.length, start);\n const suffix = markdown.substring(end, end + after.length);\n const isSurrounded = prefix === before && suffix === after;\n const isWrappedInside =\n selectedText.startsWith(before) && selectedText.endsWith(after);\n\n if (isSurrounded) {\n // Remove external wrapping (not selected)\n newText =\n markdown.substring(0, start - before.length) +\n selectedText +\n markdown.substring(end + after.length);\n selectionStart = start - before.length;\n selectionEnd = selectionStart + selectedText.length;\n } else if (isWrappedInside) {\n // Remove internal wrapping (selected)\n const unwrapped = selectedText.slice(\n before.length,\n selectedText.length - after.length,\n );\n newText =\n markdown.substring(0, start) + unwrapped + markdown.substring(end);\n selectionStart = start;\n selectionEnd = start + unwrapped.length;\n } else {\n // Add wrapping\n newText =\n markdown.substring(0, start) +\n before +\n selectedText +\n after +\n markdown.substring(end);\n\n if (selectedText.length === 0) {\n selectionStart = start + before.length;\n selectionEnd = selectionStart;\n } else {\n selectionStart = start + before.length;\n selectionEnd = selectionStart + selectedText.length;\n }\n }\n } else if (type === \"link\") {\n let linkText = \"\";\n let linkUrl = \"\";\n let inserted = \"\";\n let cursorOffsetStart = 0;\n\n const isValidUrl = (str: string): boolean => {\n try {\n new URL(str);\n return true;\n } catch {\n return false;\n }\n };\n\n if (selectedText) {\n if (isValidUrl(selectedText)) {\n linkUrl = selectedText;\n inserted = `[](${linkUrl})`;\n cursorOffsetStart = start + 1;\n } else {\n linkText = selectedText;\n inserted = `[${linkText}]()`;\n cursorOffsetStart = start + inserted.indexOf(\"](\") + 2;\n }\n } else {\n inserted = `[](https://)`;\n cursorOffsetStart = start + 1;\n }\n\n newText = markdown.substring(0, start) + inserted + markdown.substring(end);\n selectionStart = selectionEnd = cursorOffsetStart;\n } else {\n // Fallback for non-toggleable, inline syntax\n newText =\n markdown.substring(0, start) +\n before +\n selectedText +\n after +\n markdown.substring(end);\n\n if (selectedText.length === 0) {\n // No text selected – place cursor between syntax\n selectionStart = start + before.length;\n selectionEnd = selectionStart;\n } else {\n // Keep selection\n selectionStart = start + before.length;\n selectionEnd = selectionStart + selectedText.length;\n }\n }\n\n setMarkdown(newText);\n if (onChange) onChange(newText);\n\n requestAnimationFrame(() => {\n textarea.setSelectionRange(selectionStart, selectionEnd);\n textarea.focus();\n });\n};\n"],"names":[],"mappings":"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"}