@mittwald/flow-react-components 0.2.0-alpha.535 → 0.2.0-alpha.536

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.
@@ -19,7 +19,7 @@ const MarkdownEditor = flowComponent("MarkdownEditor", (props) => {
19
19
  isReadOnly,
20
20
  children,
21
21
  className,
22
- rows,
22
+ rows = 5,
23
23
  autoResizeMaxRows,
24
24
  headingOffset,
25
25
  ref,
@@ -66,7 +66,7 @@ const MarkdownEditor = flowComponent("MarkdownEditor", (props) => {
66
66
  headingOffset,
67
67
  className: styles.markdown,
68
68
  style: {
69
- maxHeight: `calc(var(--line-height--m) * ${autoResizeMaxRows ?? rows} + (var(--form-control--padding-y) * 2))`
69
+ height: textAreaRef.current?.offsetHeight
70
70
  },
71
71
  children: value
72
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownEditor.mjs","sources":["../../../../../../src/components/MarkdownEditor/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport styles from \"./MarkdownEditor.module.scss\";\nimport { Markdown, type MarkdownProps } 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\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useManagedValue } from \"@/lib/hooks/useManagedValue\";\nimport { insertAtCursor } from \"@/components/MarkdownEditor/lib/insertAtCursor\";\n\nexport type MarkdownEditorMode = \"editor\" | \"preview\";\n\nexport type MarkdownEditorProps = TextAreaProps &\n Pick<MarkdownProps, \"headingOffset\">;\n\n/** @flr-generate all */\nexport const MarkdownEditor = flowComponent(\"MarkdownEditor\", (props) => {\n const {\n isDisabled,\n isReadOnly,\n children,\n className,\n rows,\n autoResizeMaxRows,\n headingOffset,\n ref,\n ...rest\n } = props;\n\n const [mode, setMode] = useState<MarkdownEditorMode>(\"editor\");\n const { value, handleOnChange } = useManagedValue(props);\n const textAreaRef = useObjectRef<HTMLTextAreaElement>(ref);\n\n const rootClassName = clsx(\n styles.markdownEditor,\n className,\n styles[`mode-${mode}`],\n );\n\n return (\n <TextArea\n {...rest}\n isReadOnly={isReadOnly || mode === \"preview\"}\n isDisabled={isDisabled}\n className={rootClassName}\n ref={textAreaRef}\n value={value}\n rows={rows}\n autoResizeMaxRows={autoResizeMaxRows}\n onChange={(v) => {\n handleOnChange(v);\n }}\n onKeyDown={(e) => handleKeyDown(e, textAreaRef, handleOnChange)}\n >\n <Toolbar\n currentMode={mode}\n isDisabled={isDisabled}\n onModeChange={(newMode) => setMode(newMode)}\n onToolPressed={(type) => {\n insertAtCursor(value, handleOnChange, textAreaRef, type);\n }}\n />\n\n <Markdown\n headingOffset={headingOffset}\n className={styles.markdown}\n style={{\n maxHeight: `calc(var(--line-height--m) * ${autoResizeMaxRows ?? rows} + (var(--form-control--padding-y) * 2))`,\n }}\n >\n {value}\n </Markdown>\n\n {children}\n </TextArea>\n );\n});\n\nexport default MarkdownEditor;\n"],"names":[],"mappings":";;;;;;;;;;;;;AAkBO,MAAM,cAAA,GAAiB,aAAA,CAAc,gBAAA,EAAkB,CAAC,KAAA,KAAU;AACvE,EAAA,MAAM;AAAA,IACJ,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA;AAAA,IACA,iBAAA;AAAA,IACA,aAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,QAAQ,CAAA;AAC7D,EAAA,MAAM,EAAE,KAAA,EAAO,cAAA,EAAe,GAAI,gBAAgB,KAAK,CAAA;AACvD,EAAA,MAAM,WAAA,GAAc,aAAkC,GAAG,CAAA;AAEzD,EAAA,MAAM,aAAA,GAAgB,IAAA;AAAA,IACpB,MAAA,CAAO,cAAA;AAAA,IACP,SAAA;AAAA,IACA,MAAA,CAAO,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAE;AAAA,GACvB;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,UAAA,EAAY,cAAc,IAAA,KAAS,SAAA;AAAA,MACnC,UAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MACX,GAAA,EAAK,WAAA;AAAA,MACL,KAAA;AAAA,MACA,IAAA;AAAA,MACA,iBAAA;AAAA,MACA,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,QAAA,cAAA,CAAe,CAAC,CAAA;AAAA,MAClB,CAAA;AAAA,MACA,WAAW,CAAC,CAAA,KAAM,aAAA,CAAc,CAAA,EAAG,aAAa,cAAc,CAAA;AAAA,MAE9D,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,WAAA,EAAa,IAAA;AAAA,YACb,UAAA;AAAA,YACA,YAAA,EAAc,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAO,CAAA;AAAA,YAC1C,aAAA,EAAe,CAAC,IAAA,KAAS;AACvB,cAAA,cAAA,CAAe,KAAA,EAAO,cAAA,EAAgB,WAAA,EAAa,IAAI,CAAA;AAAA,YACzD;AAAA;AAAA,SACF;AAAA,wBAEA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,aAAA;AAAA,YACA,WAAW,MAAA,CAAO,QAAA;AAAA,YAClB,KAAA,EAAO;AAAA,cACL,SAAA,EAAW,CAAA,6BAAA,EAAgC,iBAAA,IAAqB,IAAI,CAAA,wCAAA;AAAA,aACtE;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA,SACH;AAAA,QAEC;AAAA;AAAA;AAAA,GACH;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"MarkdownEditor.mjs","sources":["../../../../../../src/components/MarkdownEditor/MarkdownEditor.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport styles from \"./MarkdownEditor.module.scss\";\nimport { Markdown, type MarkdownProps } 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\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useManagedValue } from \"@/lib/hooks/useManagedValue\";\nimport { insertAtCursor } from \"@/components/MarkdownEditor/lib/insertAtCursor\";\n\nexport type MarkdownEditorMode = \"editor\" | \"preview\";\n\nexport type MarkdownEditorProps = TextAreaProps &\n Pick<MarkdownProps, \"headingOffset\">;\n\n/** @flr-generate all */\nexport const MarkdownEditor = flowComponent(\"MarkdownEditor\", (props) => {\n const {\n isDisabled,\n isReadOnly,\n children,\n className,\n rows = 5,\n autoResizeMaxRows,\n headingOffset,\n ref,\n ...rest\n } = props;\n\n const [mode, setMode] = useState<MarkdownEditorMode>(\"editor\");\n const { value, handleOnChange } = useManagedValue(props);\n const textAreaRef = useObjectRef<HTMLTextAreaElement>(ref);\n\n const rootClassName = clsx(\n styles.markdownEditor,\n className,\n styles[`mode-${mode}`],\n );\n\n return (\n <TextArea\n {...rest}\n isReadOnly={isReadOnly || mode === \"preview\"}\n isDisabled={isDisabled}\n className={rootClassName}\n ref={textAreaRef}\n value={value}\n rows={rows}\n autoResizeMaxRows={autoResizeMaxRows}\n onChange={(v) => {\n handleOnChange(v);\n }}\n onKeyDown={(e) => handleKeyDown(e, textAreaRef, handleOnChange)}\n >\n <Toolbar\n currentMode={mode}\n isDisabled={isDisabled}\n onModeChange={(newMode) => setMode(newMode)}\n onToolPressed={(type) => {\n insertAtCursor(value, handleOnChange, textAreaRef, type);\n }}\n />\n\n <Markdown\n headingOffset={headingOffset}\n className={styles.markdown}\n style={{\n height: textAreaRef.current?.offsetHeight,\n }}\n >\n {value}\n </Markdown>\n\n {children}\n </TextArea>\n );\n});\n\nexport default MarkdownEditor;\n"],"names":[],"mappings":";;;;;;;;;;;;;AAkBO,MAAM,cAAA,GAAiB,aAAA,CAAc,gBAAA,EAAkB,CAAC,KAAA,KAAU;AACvE,EAAA,MAAM;AAAA,IACJ,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA,GAAO,CAAA;AAAA,IACP,iBAAA;AAAA,IACA,aAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,QAAQ,CAAA;AAC7D,EAAA,MAAM,EAAE,KAAA,EAAO,cAAA,EAAe,GAAI,gBAAgB,KAAK,CAAA;AACvD,EAAA,MAAM,WAAA,GAAc,aAAkC,GAAG,CAAA;AAEzD,EAAA,MAAM,aAAA,GAAgB,IAAA;AAAA,IACpB,MAAA,CAAO,cAAA;AAAA,IACP,SAAA;AAAA,IACA,MAAA,CAAO,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAE;AAAA,GACvB;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,UAAA,EAAY,cAAc,IAAA,KAAS,SAAA;AAAA,MACnC,UAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MACX,GAAA,EAAK,WAAA;AAAA,MACL,KAAA;AAAA,MACA,IAAA;AAAA,MACA,iBAAA;AAAA,MACA,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,QAAA,cAAA,CAAe,CAAC,CAAA;AAAA,MAClB,CAAA;AAAA,MACA,WAAW,CAAC,CAAA,KAAM,aAAA,CAAc,CAAA,EAAG,aAAa,cAAc,CAAA;AAAA,MAE9D,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,WAAA,EAAa,IAAA;AAAA,YACb,UAAA;AAAA,YACA,YAAA,EAAc,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAO,CAAA;AAAA,YAC1C,aAAA,EAAe,CAAC,IAAA,KAAS;AACvB,cAAA,cAAA,CAAe,KAAA,EAAO,cAAA,EAAgB,WAAA,EAAa,IAAI,CAAA;AAAA,YACzD;AAAA;AAAA,SACF;AAAA,wBAEA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,aAAA;AAAA,YACA,WAAW,MAAA,CAAO,QAAA;AAAA,YAClB,KAAA,EAAO;AAAA,cACL,MAAA,EAAQ,YAAY,OAAA,EAAS;AAAA,aAC/B;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA,SACH;AAAA,QAEC;AAAA;AAAA;AAAA,GACH;AAEJ,CAAC;;;;"}
@@ -11,6 +11,7 @@ import { useFieldComponent } from '../../lib/hooks/useFieldComponent.mjs';
11
11
  import '../../lib/propsContext/propsContext.mjs';
12
12
  import { PropsContextProvider } from '../../lib/propsContext/components/PropsContextProvider.mjs';
13
13
  import clsx from 'clsx';
14
+ import { useState, useEffect } from 'react';
14
15
 
15
16
  const TextArea = flowComponent("TextArea", (props) => {
16
17
  const {
@@ -19,17 +20,57 @@ const TextArea = flowComponent("TextArea", (props) => {
19
20
  rows = 5,
20
21
  autoResizeMaxRows = rows,
21
22
  ref,
23
+ allowResize,
24
+ allowVerticalResize,
25
+ allowHorizontalResize,
22
26
  ...rest
23
27
  } = props;
28
+ const rootClassName = clsx(
29
+ styles.textArea,
30
+ allowResize && styles.resize,
31
+ allowVerticalResize && styles.verticalResize,
32
+ allowHorizontalResize && styles.horizontalResize
33
+ );
24
34
  const localRef = useObjectRef(ref);
25
35
  const getHeight = (rows2) => {
26
36
  return `calc(var(--line-height--m) * ${rows2} + (var(--form-control--padding-y) * 2))`;
27
37
  };
38
+ const [resized, setResized] = useState(false);
39
+ const autoResizable = rows !== autoResizeMaxRows;
40
+ const verticallyResizable = (allowResize || allowVerticalResize) && (!autoResizable || autoResizable && resized);
41
+ useEffect(() => {
42
+ const textarea = localRef.current;
43
+ if (!textarea) return;
44
+ const startHeight = textarea.offsetHeight;
45
+ let tracking = false;
46
+ const handleMouseDown = () => {
47
+ tracking = true;
48
+ };
49
+ const handleMouseMove = () => {
50
+ if (!tracking || resized) return;
51
+ const currentHeight = textarea.offsetHeight;
52
+ if (currentHeight !== startHeight) {
53
+ setResized(true);
54
+ tracking = false;
55
+ }
56
+ };
57
+ const handleMouseUp = () => {
58
+ tracking = false;
59
+ };
60
+ window.addEventListener("mousedown", handleMouseDown);
61
+ window.addEventListener("mousemove", handleMouseMove);
62
+ window.addEventListener("mouseup", handleMouseUp);
63
+ return () => {
64
+ window.removeEventListener("mousedown", handleMouseDown);
65
+ window.removeEventListener("mousemove", handleMouseMove);
66
+ window.removeEventListener("mouseup", handleMouseUp);
67
+ };
68
+ }, [resized]);
28
69
  const updateHeight = () => {
29
- if (localRef.current && rows !== autoResizeMaxRows) {
70
+ if (localRef.current && autoResizable && !verticallyResizable) {
30
71
  localRef.current.style.height = "0px";
31
72
  const scrollHeight = localRef.current.scrollHeight;
32
- localRef.current.style.height = scrollHeight + "px";
73
+ localRef.current.style.height = scrollHeight + 2 + "px";
33
74
  }
34
75
  };
35
76
  const input = /* @__PURE__ */ jsx(
@@ -42,12 +83,12 @@ const TextArea = flowComponent("TextArea", (props) => {
42
83
  {
43
84
  rows,
44
85
  placeholder,
45
- className: styles.textArea,
86
+ className: rootClassName,
46
87
  ref: localRef,
47
88
  onChange: updateHeight,
48
89
  style: {
49
90
  minHeight: getHeight(rows),
50
- maxHeight: getHeight(autoResizeMaxRows)
91
+ maxHeight: verticallyResizable ? void 0 : getHeight(autoResizeMaxRows)
51
92
  }
52
93
  }
53
94
  )
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.mjs","sources":["../../../../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import * as Aria from \"react-aria-components\";\nimport type { TextFieldBaseProps } from \"@/components/TextFieldBase\";\nimport { TextFieldBase } from \"@/components/TextFieldBase\";\nimport styles from \"./TextArea.module.scss\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { ReactAriaControlledValueFix } from \"@/lib/react/ReactAriaControlledValueFix\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport clsx from \"clsx\";\n\nexport interface TextAreaProps\n extends Omit<TextFieldBaseProps, \"FieldErrorView\" | \"input\" | \"ref\">,\n Pick<Aria.TextAreaProps, \"placeholder\" | \"rows\">,\n FlowComponentProps<HTMLTextAreaElement> {\n /**\n * Whether the text area should grow if its content gets longer than its\n * initial height.\n */\n autoResizeMaxRows?: number;\n}\n\n/** @flr-generate all */\nexport const TextArea = flowComponent(\"TextArea\", (props) => {\n const {\n children,\n placeholder,\n rows = 5,\n autoResizeMaxRows = rows,\n ref,\n ...rest\n } = props;\n\n const localRef = useObjectRef(ref);\n\n const getHeight = (rows: number) => {\n return `calc(var(--line-height--m) * ${rows} + (var(--form-control--padding-y) * 2))`;\n };\n\n const updateHeight = () => {\n if (localRef.current && rows !== autoResizeMaxRows) {\n // https://stackoverflow.com/a/60795884\n localRef.current.style.height = \"0px\";\n const scrollHeight = localRef.current.scrollHeight;\n localRef.current.style.height = scrollHeight + \"px\";\n }\n };\n\n const input = (\n <ReactAriaControlledValueFix\n inputContext={Aria.TextAreaContext}\n props={props}\n >\n <Aria.TextArea\n rows={rows}\n placeholder={placeholder}\n className={styles.textArea}\n ref={localRef}\n onChange={updateHeight}\n style={{\n minHeight: getHeight(rows),\n maxHeight: getHeight(autoResizeMaxRows),\n }}\n />\n </ReactAriaControlledValueFix>\n );\n\n const { FieldErrorView, fieldPropsContext, fieldProps } =\n useFieldComponent(props);\n\n return (\n <TextFieldBase\n {...rest}\n {...fieldProps}\n className={clsx(rest.className, fieldProps.className)}\n FieldErrorView={FieldErrorView}\n input={input}\n >\n <PropsContextProvider props={fieldPropsContext}>\n {children}\n </PropsContextProvider>\n </TextFieldBase>\n );\n});\n\nexport default TextArea;\n"],"names":["rows"],"mappings":";;;;;;;;;;;;AAwBO,MAAM,QAAA,GAAW,aAAA,CAAc,UAAA,EAAY,CAAC,KAAA,KAAU;AAC3D,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,WAAA;AAAA,IACA,IAAA,GAAO,CAAA;AAAA,IACP,iBAAA,GAAoB,IAAA;AAAA,IACpB,GAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,QAAA,GAAW,aAAa,GAAG,CAAA;AAEjC,EAAA,MAAM,SAAA,GAAY,CAACA,KAAAA,KAAiB;AAClC,IAAA,OAAO,gCAAgCA,KAAI,CAAA,wCAAA,CAAA;AAAA,EAC7C,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,IAAI,QAAA,CAAS,OAAA,IAAW,IAAA,KAAS,iBAAA,EAAmB;AAElD,MAAA,QAAA,CAAS,OAAA,CAAQ,MAAM,MAAA,GAAS,KAAA;AAChC,MAAA,MAAM,YAAA,GAAe,SAAS,OAAA,CAAQ,YAAA;AACtC,MAAA,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,GAAS,YAAA,GAAe,IAAA;AAAA,IACjD;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,KAAA,mBACJ,GAAA;AAAA,IAAC,2BAAA;AAAA,IAAA;AAAA,MACC,cAAc,IAAA,CAAK,eAAA;AAAA,MACnB,KAAA;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,IAAA,CAAK,QAAA;AAAA,QAAL;AAAA,UACC,IAAA;AAAA,UACA,WAAA;AAAA,UACA,WAAW,MAAA,CAAO,QAAA;AAAA,UAClB,GAAA,EAAK,QAAA;AAAA,UACL,QAAA,EAAU,YAAA;AAAA,UACV,KAAA,EAAO;AAAA,YACL,SAAA,EAAW,UAAU,IAAI,CAAA;AAAA,YACzB,SAAA,EAAW,UAAU,iBAAiB;AAAA;AACxC;AAAA;AACF;AAAA,GACF;AAGF,EAAA,MAAM,EAAE,cAAA,EAAgB,iBAAA,EAAmB,UAAA,EAAW,GACpD,kBAAkB,KAAK,CAAA;AAEzB,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACH,GAAG,UAAA;AAAA,MACJ,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,WAAW,SAAS,CAAA;AAAA,MACpD,cAAA;AAAA,MACA,KAAA;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,oBAAA,EAAA,EAAqB,KAAA,EAAO,iBAAA,EAC1B,QAAA,EACH;AAAA;AAAA,GACF;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"TextArea.mjs","sources":["../../../../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import * as Aria from \"react-aria-components\";\nimport type { TextFieldBaseProps } from \"@/components/TextFieldBase\";\nimport { TextFieldBase } from \"@/components/TextFieldBase\";\nimport styles from \"./TextArea.module.scss\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { ReactAriaControlledValueFix } from \"@/lib/react/ReactAriaControlledValueFix\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport clsx from \"clsx\";\nimport { useEffect, useState } from \"react\";\n\nexport interface TextAreaProps\n extends Omit<TextFieldBaseProps, \"FieldErrorView\" | \"input\" | \"ref\">,\n Pick<Aria.TextAreaProps, \"placeholder\" | \"rows\">,\n FlowComponentProps<HTMLTextAreaElement> {\n /**\n * Whether the text area should grow if its content gets longer than its\n * initial height.\n */\n autoResizeMaxRows?: number;\n /** Allows the user to manually resize the textArea horizontally. */\n allowHorizontalResize?: boolean;\n /** Allows the user to manually resize the textArea vertically. */\n allowVerticalResize?: boolean;\n /**\n * Allows the user to manually resize the textArea horizontally and\n * vertically.\n */\n allowResize?: boolean;\n}\n\n/** @flr-generate all */\nexport const TextArea = flowComponent(\"TextArea\", (props) => {\n const {\n children,\n placeholder,\n rows = 5,\n autoResizeMaxRows = rows,\n ref,\n allowResize,\n allowVerticalResize,\n allowHorizontalResize,\n ...rest\n } = props;\n\n const rootClassName = clsx(\n styles.textArea,\n allowResize && styles.resize,\n allowVerticalResize && styles.verticalResize,\n allowHorizontalResize && styles.horizontalResize,\n );\n\n const localRef = useObjectRef(ref);\n\n const getHeight = (rows: number) => {\n return `calc(var(--line-height--m) * ${rows} + (var(--form-control--padding-y) * 2))`;\n };\n\n const [resized, setResized] = useState(false);\n\n const autoResizable = rows !== autoResizeMaxRows;\n\n const verticallyResizable =\n (allowResize || allowVerticalResize) &&\n (!autoResizable || (autoResizable && resized));\n\n useEffect(() => {\n const textarea = localRef.current;\n if (!textarea) return;\n\n const startHeight = textarea.offsetHeight;\n let tracking = false;\n\n const handleMouseDown = () => {\n tracking = true;\n };\n\n const handleMouseMove = () => {\n if (!tracking || resized) return;\n\n const currentHeight = textarea.offsetHeight;\n\n if (currentHeight !== startHeight) {\n setResized(true);\n tracking = false;\n }\n };\n\n const handleMouseUp = () => {\n tracking = false;\n };\n\n window.addEventListener(\"mousedown\", handleMouseDown);\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n window.removeEventListener(\"mousedown\", handleMouseDown);\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [resized]);\n\n const updateHeight = () => {\n if (localRef.current && autoResizable && !verticallyResizable) {\n // https://stackoverflow.com/a/60795884\n localRef.current.style.height = \"0px\";\n const scrollHeight = localRef.current.scrollHeight;\n // + 2 to add border height\n localRef.current.style.height = scrollHeight + 2 + \"px\";\n }\n };\n\n const input = (\n <ReactAriaControlledValueFix\n inputContext={Aria.TextAreaContext}\n props={props}\n >\n <Aria.TextArea\n rows={rows}\n placeholder={placeholder}\n className={rootClassName}\n ref={localRef}\n onChange={updateHeight}\n style={{\n minHeight: getHeight(rows),\n maxHeight: verticallyResizable\n ? undefined\n : getHeight(autoResizeMaxRows),\n }}\n />\n </ReactAriaControlledValueFix>\n );\n\n const { FieldErrorView, fieldPropsContext, fieldProps } =\n useFieldComponent(props);\n\n return (\n <TextFieldBase\n {...rest}\n {...fieldProps}\n className={clsx(rest.className, fieldProps.className)}\n FieldErrorView={FieldErrorView}\n input={input}\n >\n <PropsContextProvider props={fieldPropsContext}>\n {children}\n </PropsContextProvider>\n </TextFieldBase>\n );\n});\n\nexport default TextArea;\n"],"names":["rows"],"mappings":"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"}
@@ -1,9 +1,15 @@
1
1
  "use client"
2
2
  /* */
3
3
  const textArea = "flow--text-area";
4
+ const horizontalResize = "flow--text-area--horizontal-resize";
5
+ const verticalResize = "flow--text-area--vertical-resize";
6
+ const resize = "flow--text-area--resize";
4
7
  const styles = {
5
- textArea: textArea
8
+ textArea: textArea,
9
+ horizontalResize: horizontalResize,
10
+ verticalResize: verticalResize,
11
+ resize: resize
6
12
  };
7
13
 
8
- export { styles as default, textArea };
14
+ export { styles as default, horizontalResize, resize, textArea, verticalResize };
9
15
  //# sourceMappingURL=TextArea.module.scss.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"TextArea.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
@@ -8,7 +8,11 @@ export declare const Disabled: Story;
8
8
  export declare const WithLabel: Story;
9
9
  export declare const ShowCharacterCount: Story;
10
10
  export declare const WithFieldError: Story;
11
+ export declare const AutoResizeable: Story;
11
12
  export declare const Resizeable: Story;
13
+ export declare const HorizontallyResizeable: Story;
14
+ export declare const VerticallyResizeable: Story;
15
+ export declare const VerticallyAndAutoResizeable: Story;
12
16
  export declare const WithOnChange: Story;
13
17
  export declare const WithRef: StoryObj;
14
18
  //# sourceMappingURL=Default.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/MarkdownEditor/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAM7D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAKrC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,QAqBrB,CAAC"}
1
+ {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/MarkdownEditor/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAM7D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAKrC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7C,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,KAEpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAElC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,KAEzC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,QAqBrB,CAAC"}
@@ -7,6 +7,15 @@ export interface TextAreaProps extends Omit<TextFieldBaseProps, "FieldErrorView"
7
7
  * initial height.
8
8
  */
9
9
  autoResizeMaxRows?: number;
10
+ /** Allows the user to manually resize the textArea horizontally. */
11
+ allowHorizontalResize?: boolean;
12
+ /** Allows the user to manually resize the textArea vertically. */
13
+ allowVerticalResize?: boolean;
14
+ /**
15
+ * Allows the user to manually resize the textArea horizontally and
16
+ * vertically.
17
+ */
18
+ allowResize?: boolean;
10
19
  }
11
20
  /** @flr-generate all */
12
21
  export declare const TextArea: import('react').FunctionComponent<TextAreaProps & import('react').RefAttributes<HTMLTextAreaElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../../../src/components/TextArea/TextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAQ/E,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,GAAG,OAAO,GAAG,KAAK,CAAC,EAClE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM,CAAC,EAChD,kBAAkB,CAAC,mBAAmB,CAAC;IACzC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAwB;AACxB,eAAO,MAAM,QAAQ,uGA4DnB,CAAC;AAEH,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../../../src/components/TextArea/TextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAS/E,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,GAAG,OAAO,GAAG,KAAK,CAAC,EAClE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM,CAAC,EAChD,kBAAkB,CAAC,mBAAmB,CAAC;IACzC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAwB;AACxB,eAAO,MAAM,QAAQ,uGAsHnB,CAAC;AAEH,eAAe,QAAQ,CAAC"}
@@ -12,5 +12,9 @@ export declare const WithDefaultValue: Story;
12
12
  export declare const WithPlaceholder: Story;
13
13
  export declare const WithFieldError: Story;
14
14
  export declare const ShowCharacterCount: Story;
15
+ export declare const AutoResizeable: Story;
15
16
  export declare const Resizeable: Story;
17
+ export declare const HorizontallyResizeable: Story;
18
+ export declare const VerticallyResizeable: Story;
19
+ export declare const VerticallyAndAutoResizeable: Story;
16
20
  //# sourceMappingURL=Default.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextArea/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOpC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,QAAQ,CAQ/B,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,EAAE,KAOlC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAS9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAM7B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC"}
1
+ {"version":3,"file":"Default.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextArea/stories/Default.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOpC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,QAAQ,CAQ/B,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,QAAQ,EAAE,KAAsC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,EAAE,KAOlC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAS9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAM7B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,KAEpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAElC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,KAEzC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mittwald/flow-react-components",
3
- "version": "0.2.0-alpha.535",
3
+ "version": "0.2.0-alpha.536",
4
4
  "type": "module",
5
5
  "description": "A React implementation of Flow, mittwald’s design system",
6
6
  "homepage": "https://mittwald.github.io/flow",
@@ -58,7 +58,7 @@
58
58
  "dependencies": {
59
59
  "@internationalized/string-compiler": "^3.2.6",
60
60
  "@mittwald/password-tools-js": "3.0.0-alpha.18",
61
- "@mittwald/react-tunnel": "0.2.0-alpha.535",
61
+ "@mittwald/react-tunnel": "0.2.0-alpha.536",
62
62
  "@mittwald/react-use-promise": "^4.2.2",
63
63
  "@react-aria/form": "^3.1.2",
64
64
  "@react-aria/live-announcer": "^3.4.4",
@@ -101,7 +101,7 @@
101
101
  "@faker-js/faker": "^10.1.0",
102
102
  "@internationalized/date": "^3.10.0",
103
103
  "@mittwald/flow-core": "",
104
- "@mittwald/flow-design-tokens": "0.2.0-alpha.535",
104
+ "@mittwald/flow-design-tokens": "0.2.0-alpha.536",
105
105
  "@mittwald/react-use-promise": "^4.2.2",
106
106
  "@mittwald/remote-dom-react": "1.2.2-mittwald.10",
107
107
  "@mittwald/typescript-config": "",
@@ -174,5 +174,5 @@
174
174
  "optional": true
175
175
  }
176
176
  },
177
- "gitHead": "5c8814be1b24c3ee9c12b7fa8f9f524c60fc37f5"
177
+ "gitHead": "fcb09be1f3e1ed21bdc55b121944d7fd2127ed8b"
178
178
  }