diff --git a/web_widget_product_label_section_and_note/README.rst b/web_widget_product_label_section_and_note/README.rst
index 4d03bc616..0536eb1c7 100644
--- a/web_widget_product_label_section_and_note/README.rst
+++ b/web_widget_product_label_section_and_note/README.rst
@@ -57,7 +57,7 @@ Usage
Known issues / Roadmap
======================
-- Add compatibility with `sale` module
+- Add compatibility with `sale_product_configurator` module
- Add compatibility with `purchase_product_matrix` module
- When this module is installed, the PDF report will always display the column `name` as a combination of the `product code`, `product name`, and `description`. This behavior may differ from the expected behavior, where only the column `name` is displayed and can be customized independently.
diff --git a/web_widget_product_label_section_and_note/__manifest__.py b/web_widget_product_label_section_and_note/__manifest__.py
index 05eae540e..3f37cd489 100644
--- a/web_widget_product_label_section_and_note/__manifest__.py
+++ b/web_widget_product_label_section_and_note/__manifest__.py
@@ -13,6 +13,7 @@
],
"assets": {
"web.assets_backend": [
+ "web_widget_product_label_section_and_note/static/src/core/utils/**/*",
"web_widget_product_label_section_and_note/static/src/components/**/*",
],
},
diff --git a/web_widget_product_label_section_and_note/readme/ROADMAP.rst b/web_widget_product_label_section_and_note/readme/ROADMAP.rst
index f534a99ea..8e3c1f4bf 100644
--- a/web_widget_product_label_section_and_note/readme/ROADMAP.rst
+++ b/web_widget_product_label_section_and_note/readme/ROADMAP.rst
@@ -1,3 +1,3 @@
-- Add compatibility with `sale` module
+- Add compatibility with `sale_product_configurator` module
- Add compatibility with `purchase_product_matrix` module
- When this module is installed, the PDF report will always display the column `name` as a combination of the `product code`, `product name`, and `description`. This behavior may differ from the expected behavior, where only the column `name` is displayed and can be customized independently.
\ No newline at end of file
diff --git a/web_widget_product_label_section_and_note/static/description/index.html b/web_widget_product_label_section_and_note/static/description/index.html
index 0555ba047..c8204d0e7 100644
--- a/web_widget_product_label_section_and_note/static/description/index.html
+++ b/web_widget_product_label_section_and_note/static/description/index.html
@@ -407,7 +407,7 @@ in a new module, it is necessary to create an inherited view to change the widge
-- Add compatibility with sale module
+- Add compatibility with sale_product_configurator module
- Add compatibility with purchase_product_matrix module
- When this module is installed, the PDF report will always display the column name as a combination of the product code, product name, and description. This behavior may differ from the expected behavior, where only the column name is displayed and can be customized independently.
diff --git a/web_widget_product_label_section_and_note/static/src/components/product_label_section_and_note_field/product_label_section_and_note_field.esm.js b/web_widget_product_label_section_and_note/static/src/components/product_label_section_and_note_field/product_label_section_and_note_field.esm.js
index 7fffe74df..c90dbe63d 100644
--- a/web_widget_product_label_section_and_note/static/src/components/product_label_section_and_note_field/product_label_section_and_note_field.esm.js
+++ b/web_widget_product_label_section_and_note/static/src/components/product_label_section_and_note_field/product_label_section_and_note_field.esm.js
@@ -20,6 +20,7 @@ import {X2ManyField} from "@web/views/fields/x2many/x2many_field";
import {_t} from "@web/core/l10n/translation";
import {getActiveHotkey} from "@web/core/hotkeys/hotkey_service";
import {registry} from "@web/core/registry";
+import {useProductAndLabelAutoresize} from "../../core/utils/product_and_label_autoresize.esm";
export class ProductLabelSectionAndNoteListRender extends SectionAndNoteListRenderer {
setup() {
@@ -138,7 +139,13 @@ export class ProductLabelSectionAndNoteField extends Many2OneField {
value: this.props.record.columnIsProductAndLabel,
});
this.labelNode = useRef("labelNodeRef");
+ useProductAndLabelAutoresize(this.labelNode, {
+ targetParentName: this.props.name,
+ });
this.productNode = useRef("productNodeRef");
+ useProductAndLabelAutoresize(this.productNode, {
+ targetParentName: this.props.name,
+ });
useEffect(
() => {
diff --git a/web_widget_product_label_section_and_note/static/src/core/utils/autoresize.esm.js b/web_widget_product_label_section_and_note/static/src/core/utils/autoresize.esm.js
new file mode 100644
index 000000000..4136d43d2
--- /dev/null
+++ b/web_widget_product_label_section_and_note/static/src/core/utils/autoresize.esm.js
@@ -0,0 +1,111 @@
+/** @odoo-module **/
+/* Copyright Odoo S.A.
+ * Copyright 2024 Tecnativa - Carlos Lopez
+ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
+
+import {useEffect} from "@odoo/owl";
+import {browser} from "@web/core/browser/browser";
+
+function resizeInput(input) {
+ // This mesures the maximum width of the input which can get from the flex layout.
+ input.style.width = "100%";
+ const maxWidth = input.clientWidth;
+ // Somehow Safari 16 computes input sizes incorrectly. This is fixed in Safari 17
+ const isSafari16 = /Version\/16.+Safari/i.test(browser.navigator.userAgent);
+ // Minimum width of the input
+ input.style.width = "10px";
+ if (input.value === "" && input.placeholder !== "") {
+ input.style.width = "auto";
+ return;
+ }
+ if (input.scrollWidth + 5 + (isSafari16 ? 8 : 0) > maxWidth) {
+ input.style.width = "100%";
+ return;
+ }
+ input.style.width = input.scrollWidth + 5 + (isSafari16 ? 8 : 0) + "px";
+}
+
+export function resizeTextArea(textarea, options = {}) {
+ const minimumHeight = options.minimumHeight || 0;
+ let heightOffset = 0;
+ const style = window.getComputedStyle(textarea);
+ if (style.boxSizing === "border-box") {
+ const paddingHeight =
+ parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
+ const borderHeight =
+ parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
+ heightOffset = borderHeight + paddingHeight;
+ }
+ const previousStyle = {
+ borderTopWidth: style.borderTopWidth,
+ borderBottomWidth: style.borderBottomWidth,
+ padding: style.padding,
+ };
+ Object.assign(textarea.style, {
+ height: "auto",
+ borderTopWidth: 0,
+ borderBottomWidth: 0,
+ paddingTop: 0,
+ paddingRight: style.paddingRight,
+ paddingBottom: 0,
+ paddingLeft: style.paddingLeft,
+ });
+ textarea.style.height = "auto";
+ const height = Math.max(minimumHeight, textarea.scrollHeight + heightOffset);
+ Object.assign(textarea.style, previousStyle, {height: `${height}px`});
+ textarea.parentElement.style.height = `${height}px`;
+}
+
+/**
+ * This is used on text inputs or textareas to automatically resize it based on its
+ * content each time it is updated. It takes the reference of the element as
+ * parameter and some options. Do note that it may introduce mild performance issues
+ * since it will force a reflow of the layout each time the element is updated.
+ * Do also note that it only works with textareas that are nested as only child
+ * of some parent div (like in the text_field component).
+ *
+ * @param {Ref} ref
+ */
+export function useAutoresize(ref, options = {}) {
+ let wasProgrammaticallyResized = false;
+ let resize = null;
+ useEffect(
+ (el) => {
+ if (el) {
+ resize = (programmaticResize = false) => {
+ wasProgrammaticallyResized = programmaticResize;
+ if (el instanceof HTMLInputElement) {
+ resizeInput(el, options);
+ } else {
+ resizeTextArea(el, options);
+ }
+ if (options.onResize) {
+ options.onResize(el, options);
+ }
+ };
+ el.addEventListener("input", () => resize(true));
+ const resizeObserver = new ResizeObserver(() => {
+ // This ensures that the resize function is not called twice on input or page load
+ if (wasProgrammaticallyResized) {
+ wasProgrammaticallyResized = false;
+ return;
+ }
+ resize();
+ });
+ resizeObserver.observe(el);
+ return () => {
+ el.removeEventListener("input", resize);
+ resizeObserver.unobserve(el);
+ resizeObserver.disconnect();
+ resize = null;
+ };
+ }
+ },
+ () => [ref.el]
+ );
+ useEffect(() => {
+ if (resize) {
+ resize(true);
+ }
+ });
+}
diff --git a/web_widget_product_label_section_and_note/static/src/core/utils/product_and_label_autoresize.esm.js b/web_widget_product_label_section_and_note/static/src/core/utils/product_and_label_autoresize.esm.js
new file mode 100644
index 000000000..f874025ca
--- /dev/null
+++ b/web_widget_product_label_section_and_note/static/src/core/utils/product_and_label_autoresize.esm.js
@@ -0,0 +1,41 @@
+/** @odoo-module **/
+/* Copyright Odoo S.A.
+ * Copyright 2024 Tecnativa - Carlos Lopez
+ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
+
+import {useAutoresize} from "./autoresize.esm";
+
+export function productAndLabelResizeTextArea(textarea, options = {}) {
+ const style = window.getComputedStyle(textarea);
+ if (options.targetParentName) {
+ let target = textarea.parentElement;
+ let shouldContinue = true;
+ while (target && shouldContinue) {
+ const totalParentHeight = Array.from(target.children).reduce(
+ (total, child) => {
+ const childHeight = child.style.height || style.lineHeight;
+ return total + parseFloat(childHeight);
+ },
+ 0
+ );
+ target.style.height = `${totalParentHeight}px`;
+ if (target.getAttribute("name") === options.targetParentName) {
+ shouldContinue = false;
+ }
+ target = target.parentElement;
+ }
+ }
+}
+
+/**
+ * This overriden version of the resizeTextArea method is specificly done for the product_label_section_and_note widget
+ * His necessity is found in the fact that the cell of said widget doesn't contain only the input or textarea to resize
+ * but also another node containing the name of the product if said data is available. This means that the autoresize
+ * method which sets the height of the parent cell should sometimes add an additional row to the parent cell so that
+ * no text overflows
+ *
+ * @param {Ref} ref
+ */
+export function useProductAndLabelAutoresize(ref, options = {}) {
+ useAutoresize(ref, {onResize: productAndLabelResizeTextArea, ...options});
+}