@digdir/designsystemet-react 1.5.0 → 1.5.1

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,9 +19,11 @@ const label = (text, count) => text.replace('%d', Math.abs(count).toString());
19
19
  */
20
20
  const FieldCounter = react.forwardRef(function FieldCounter({ limit, under = '%d tegn igjen', over = '%d tegn for mye', ...rest }, ref) {
21
21
  const [count, setCount] = react.useState(0);
22
+ const fieldInputRef = react.useRef(null);
22
23
  const counterRef = react.useRef(null);
23
24
  const hasExceededLimit = count > limit;
24
25
  const remainder = limit - count;
26
+ // Listen to native input events (user typing) to update the counter in real time
25
27
  react.useEffect(() => {
26
28
  const field = counterRef.current?.closest('.ds-field');
27
29
  const input = Array.from(field?.getElementsByTagName('*') || []).find(fieldObserver.isInputLike);
@@ -31,9 +33,18 @@ const FieldCounter = react.forwardRef(function FieldCounter({ limit, under = '%d
31
33
  };
32
34
  if (input)
33
35
  onInput({ target: input }); // Initial setup
36
+ fieldInputRef.current = input;
34
37
  field?.addEventListener('input', onInput);
35
38
  return () => field?.removeEventListener('input', onInput);
36
- }, [setCount]);
39
+ }, []);
40
+ /* React does not dispatch a native input event when the value prop changes externally.
41
+ Since the parent re-renders this component when value changes, we can sync on render. */
42
+ react.useEffect(() => {
43
+ if (fieldInputRef.current) {
44
+ const valueLength = fieldInputRef.current.value.length;
45
+ setCount((prev) => (prev === valueLength ? prev : valueLength));
46
+ }
47
+ });
37
48
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { "data-field": 'description', className: 'ds-sr-only', "aria-live": 'polite', ref: counterRef, children: hasExceededLimit && label(over, remainder) }), hasExceededLimit ? (jsxRuntime.jsx(validationMessage.ValidationMessage, { ref: ref, ...rest, children: label(over, remainder) })) : (jsxRuntime.jsx(paragraph.Paragraph, { ref: ref, ...rest, "data-field": 'validation', children: label(under, remainder) }))] }));
38
49
  });
39
50
 
@@ -45,7 +45,7 @@ const Popover = react.forwardRef(function Popover({ id, className, onClose, onOp
45
45
  setInternalOpen((open) => !open);
46
46
  onOpen?.();
47
47
  }
48
- if (isOutside) {
48
+ if (isOutside && internalOpen) {
49
49
  setInternalOpen(false);
50
50
  onClose?.();
51
51
  }
@@ -17,9 +17,11 @@ const label = (text, count) => text.replace('%d', Math.abs(count).toString());
17
17
  */
18
18
  const FieldCounter = forwardRef(function FieldCounter({ limit, under = '%d tegn igjen', over = '%d tegn for mye', ...rest }, ref) {
19
19
  const [count, setCount] = useState(0);
20
+ const fieldInputRef = useRef(null);
20
21
  const counterRef = useRef(null);
21
22
  const hasExceededLimit = count > limit;
22
23
  const remainder = limit - count;
24
+ // Listen to native input events (user typing) to update the counter in real time
23
25
  useEffect(() => {
24
26
  const field = counterRef.current?.closest('.ds-field');
25
27
  const input = Array.from(field?.getElementsByTagName('*') || []).find(isInputLike);
@@ -29,9 +31,18 @@ const FieldCounter = forwardRef(function FieldCounter({ limit, under = '%d tegn
29
31
  };
30
32
  if (input)
31
33
  onInput({ target: input }); // Initial setup
34
+ fieldInputRef.current = input;
32
35
  field?.addEventListener('input', onInput);
33
36
  return () => field?.removeEventListener('input', onInput);
34
- }, [setCount]);
37
+ }, []);
38
+ /* React does not dispatch a native input event when the value prop changes externally.
39
+ Since the parent re-renders this component when value changes, we can sync on render. */
40
+ useEffect(() => {
41
+ if (fieldInputRef.current) {
42
+ const valueLength = fieldInputRef.current.value.length;
43
+ setCount((prev) => (prev === valueLength ? prev : valueLength));
44
+ }
45
+ });
35
46
  return (jsxs(Fragment, { children: [jsx("div", { "data-field": 'description', className: 'ds-sr-only', "aria-live": 'polite', ref: counterRef, children: hasExceededLimit && label(over, remainder) }), hasExceededLimit ? (jsx(ValidationMessage, { ref: ref, ...rest, children: label(over, remainder) })) : (jsx(Paragraph, { ref: ref, ...rest, "data-field": 'validation', children: label(under, remainder) }))] }));
36
47
  });
37
48
 
@@ -43,7 +43,7 @@ const Popover = forwardRef(function Popover({ id, className, onClose, onOpen, op
43
43
  setInternalOpen((open) => !open);
44
44
  onOpen?.();
45
45
  }
46
- if (isOutside) {
46
+ if (isOutside && internalOpen) {
47
47
  setInternalOpen(false);
48
48
  onClose?.();
49
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"field-counter.d.ts","sourceRoot":"","sources":["../../../src/components/field/field-counter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0CAA0C,CAAC;AAGlD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;QAII;IACJ,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,sBAAsB,CAAC;AAK3B;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;IAlCvB;;;;;OAKG;WACI,MAAM;IACb;;;;;OAKG;YACK,MAAM;IACd;;;;QAII;WACG,MAAM;;;;8CA8Dd,CAAC"}
1
+ {"version":3,"file":"field-counter.d.ts","sourceRoot":"","sources":["../../../src/components/field/field-counter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0CAA0C,CAAC;AAGlD,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;QAII;IACJ,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,sBAAsB,CAAC;AAK3B;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;IAlCvB;;;;;OAKG;WACI,MAAM;IACb;;;;;OAKG;YACK,MAAM;IACd;;;;QAII;WACG,MAAM;;;;8CA0Ed,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@digdir/designsystemet-react",
3
3
  "type": "module",
4
- "version": "1.5.0",
4
+ "version": "1.5.1",
5
5
  "description": "React components for Designsystemet",
6
6
  "author": "Designsystemet team",
7
7
  "repository": {
@@ -67,8 +67,8 @@
67
67
  "storybook": "^9.1.5",
68
68
  "tsx": "4.20.5",
69
69
  "typescript": "^5.9.2",
70
- "@digdir/designsystemet": "^1.5.0",
71
- "@digdir/designsystemet-css": "^1.5.0"
70
+ "@digdir/designsystemet": "^1.5.1",
71
+ "@digdir/designsystemet-css": "^1.5.1"
72
72
  },
73
73
  "scripts": {
74
74
  "build": "pnpm run clean && tsc -b tsconfig.lib.json --emitDeclarationOnly false && rollup -c --bundleConfigAsCjs",