@uxf/core 11.53.1 → 11.54.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.
package/README.md CHANGED
@@ -97,7 +97,7 @@ Dynamically adjusts the height of a `<textarea>` based on its content and an opt
97
97
  - **`rows`** (optional): Minimum visible rows. Default is `4`.
98
98
 
99
99
  #### Behavior
100
- - Resets height to `"auto"` to measure content height.
100
+ - Leverages MutationObserver API to measure content height.
101
101
  - Adjusts height to fit content or the minimum height based on the `rows` parameter, calculated using `line-height` and `font-size`.
102
102
 
103
103
  #### Usage
@@ -105,6 +105,23 @@ Dynamically adjusts the height of a `<textarea>` based on its content and an opt
105
105
  adjustTextareaHeight(textarea); // Adjusts height (min 4 rows)
106
106
  adjustTextareaHeight(textarea, 6); // With 6-row minimum
107
107
  ```
108
+ In React component:
109
+ ```tsx
110
+ import { useIsomorphicLayoutEffect } from "@uxf/core-react/hooks/use-isomorphic-layout-effect";
111
+ import { isNotNil } from "@uxf/core/utils/is-not-nil";
112
+
113
+ useIsomorphicLayoutEffect(() => {
114
+ const textarea = textareaRef.current;
115
+
116
+ if (isNotNil(textarea)) {
117
+ return;
118
+ }
119
+
120
+ const cleanup = adjustTextareaHeight(textarea);
121
+
122
+ return () => cleanup();
123
+ }, []);
124
+ ```
108
125
 
109
126
  > **Note**: Requires valid `line-height` and `font-size` styles for accurate sizing.
110
127
 
@@ -171,6 +188,17 @@ const submitHandler: FormEventHandler<HTMLFormElement> = () => {
171
188
  };
172
189
  ```
173
190
 
191
+ ### escapeQuotes
192
+
193
+ Escapes all double quotes (`"`) in a string by replacing them with `\"`.
194
+
195
+ ```ts
196
+ import { escapeQuotes } from "@uxf/core/utils/escape-quotes";
197
+
198
+ escapeQuotes('The "quick" fox');
199
+ // Output: The \"quick\" fox
200
+ ```
201
+
174
202
  ### formatBytes
175
203
 
176
204
  Appends suitable unit to the byte value of data size.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/core",
3
- "version": "11.53.1",
3
+ "version": "11.54.0",
4
4
  "description": "UXF Core",
5
5
  "author": "Petr Vejvoda <vejvoda@uxf.cz>",
6
6
  "homepage": "https://gitlab.com/uxf-npm/core#readme",
@@ -1 +1,2 @@
1
- export declare function adjustTextareaHeight(element: HTMLTextAreaElement, rows?: number): void;
1
+ import { Noop } from "../types";
2
+ export declare function adjustTextareaHeight(node: HTMLTextAreaElement, rows?: number): Noop;
@@ -1,13 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.adjustTextareaHeight = adjustTextareaHeight;
4
- function adjustTextareaHeight(element, rows = 4) {
5
- element.style.height = "auto";
4
+ function setHeightByContent(element, shouldShrink, rows = 4) {
6
5
  if (rows >= 1) {
7
- const contentHeight = element.scrollHeight;
8
6
  const lineHeight = parseFloat(window.getComputedStyle(element).getPropertyValue("line-height"));
9
7
  const fontSize = parseFloat(window.getComputedStyle(element).getPropertyValue("font-size"));
10
8
  const targetHeight = parseInt((rows * fontSize * (lineHeight / fontSize)).toFixed(3), 10);
11
- element.style.height = Math.max(targetHeight, contentHeight) + "px";
9
+ if (shouldShrink) {
10
+ while (element.scrollHeight <= element.clientHeight) {
11
+ element.style.height = Math.max(targetHeight, element.scrollHeight - lineHeight) + "px";
12
+ if (element.clientHeight - lineHeight <= targetHeight) {
13
+ break;
14
+ }
15
+ }
16
+ }
17
+ element.style.height = Math.max(targetHeight, element.scrollHeight) + "px";
12
18
  }
19
+ else {
20
+ element.style.height = "auto";
21
+ }
22
+ }
23
+ function adjustTextareaHeight(node, rows = 4) {
24
+ setHeightByContent(node, false, rows);
25
+ const observer = new MutationObserver((mutations) => {
26
+ var _a, _b, _c, _d, _e, _f;
27
+ for (const mutation of mutations) {
28
+ if (mutation.type === "childList") {
29
+ const removedLength = (_c = (_b = (_a = mutation.removedNodes.item(0)) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
30
+ const addedLength = (_f = (_e = (_d = mutation.addedNodes.item(0)) === null || _d === void 0 ? void 0 : _d.textContent) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0;
31
+ setHeightByContent(node, removedLength > addedLength, rows);
32
+ }
33
+ }
34
+ });
35
+ observer.observe(node, {
36
+ childList: true,
37
+ });
38
+ return () => observer.disconnect();
13
39
  }
@@ -15,7 +15,7 @@ describe("adjustTextareaHeight", () => {
15
15
  it('should reset the height of the textarea to "auto" before adjustment', () => {
16
16
  textarea.style.height = "100px";
17
17
  (0, adjust_textarea_height_1.adjustTextareaHeight)(textarea);
18
- expect(textarea.style.height).toBe("auto");
18
+ expect(textarea.style.height).toBe("100px");
19
19
  });
20
20
  it("should correctly adjust the height based on content height when rows are provided", () => {
21
21
  jest.spyOn(window, "getComputedStyle").mockImplementation(() => ({
@@ -0,0 +1 @@
1
+ export declare function escapeQuotes(value: string): string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.escapeQuotes = escapeQuotes;
4
+ function escapeQuotes(value) {
5
+ return value.replace(/\x22/g, "\\\x22");
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const escape_quotes_1 = require("./escape-quotes");
4
+ test("escapeQuotes", () => {
5
+ expect((0, escape_quotes_1.escapeQuotes)('"Název něčeho"')).toBe('\\"Název něčeho\\"');
6
+ });