@digdir/designsystemet-react 0.0.0-test-20250715062533 → 0.0.0-test-20250715110951

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 (25) hide show
  1. package/dist/cjs/components/dialog/dialog.js +2 -3
  2. package/dist/cjs/components/field/field-observer.js +5 -7
  3. package/dist/cjs/components/suggestion/index.js +3 -0
  4. package/dist/cjs/components/suggestion/suggestion-chips.js +6 -8
  5. package/dist/cjs/components/suggestion/suggestion-input.js +2 -5
  6. package/dist/cjs/components/suggestion/suggestion-list.js +5 -11
  7. package/dist/cjs/components/suggestion/suggestion.js +25 -8
  8. package/dist/esm/components/dialog/dialog.js +2 -3
  9. package/dist/esm/components/field/field-observer.js +5 -7
  10. package/dist/esm/components/suggestion/index.js +3 -0
  11. package/dist/esm/components/suggestion/suggestion-chips.js +6 -8
  12. package/dist/esm/components/suggestion/suggestion-input.js +3 -6
  13. package/dist/esm/components/suggestion/suggestion-list.js +6 -12
  14. package/dist/esm/components/suggestion/suggestion.js +25 -8
  15. package/dist/types/components/dialog/dialog.d.ts.map +1 -1
  16. package/dist/types/components/field/field-observer.d.ts.map +1 -1
  17. package/dist/types/components/suggestion/index.d.ts +26 -5
  18. package/dist/types/components/suggestion/index.d.ts.map +1 -1
  19. package/dist/types/components/suggestion/suggestion-chips.d.ts +6 -14
  20. package/dist/types/components/suggestion/suggestion-chips.d.ts.map +1 -1
  21. package/dist/types/components/suggestion/suggestion-input.d.ts.map +1 -1
  22. package/dist/types/components/suggestion/suggestion-list.d.ts.map +1 -1
  23. package/dist/types/components/suggestion/suggestion.d.ts +65 -14
  24. package/dist/types/components/suggestion/suggestion.d.ts.map +1 -1
  25. package/package.json +3 -3
@@ -73,9 +73,8 @@ const Dialog = react.forwardRef(function Dialog({ asChild, children, className,
73
73
  /* handle closing */
74
74
  react.useEffect(() => {
75
75
  const handleClose = (event) => onClose?.(event);
76
- const currentRef = dialogRef.current;
77
- currentRef?.addEventListener('close', handleClose);
78
- return () => currentRef?.removeEventListener('close', handleClose);
76
+ dialogRef.current?.addEventListener('close', handleClose);
77
+ return () => dialogRef.current?.removeEventListener('close', handleClose);
79
78
  }, [onClose]);
80
79
  return (jsxRuntime.jsxs(Component, { className: cl('ds-dialog', className), ref: mergedRefs, "data-modal": modal, ...rest, children: [closeButton !== false && (jsxRuntime.jsx("form", { method: 'dialog', children: jsxRuntime.jsx(button.Button, { "aria-label": closeButton, autoFocus: true, "data-color": 'neutral', icon: true, name: 'close', type: 'submit', variant: 'tertiary' }) })), children] }));
81
80
  });
@@ -44,7 +44,7 @@ function fieldObserver(fieldElement) {
44
44
  }
45
45
  }
46
46
  // Connect elements
47
- const describedbyIds = describedby ? describedby.split(' ') : []; // Keep original aria-describedby
47
+ const describedbyIds = [describedby]; // Keep original aria-describedby
48
48
  const inputId = input?.id || uuid;
49
49
  // Reset type counters since we reprocess all elements
50
50
  typeCounter.clear();
@@ -62,12 +62,10 @@ function fieldObserver(fieldElement) {
62
62
  }
63
63
  if (!value)
64
64
  setAttr(el, isLabel(el) ? 'for' : 'id', id); // Ensure we have a value
65
- if (!describedbyIds.includes(el.id)) {
66
- if (descriptionType === 'validation')
67
- describedbyIds.unshift(el.id); // Validations to the front
68
- else if (descriptionType)
69
- describedbyIds.push(el.id); // Other descriptions to the back
70
- }
65
+ if (descriptionType === 'validation')
66
+ describedbyIds.unshift(el.id); // Validations to the front
67
+ else if (descriptionType)
68
+ describedbyIds.push(el.id); // Other descriptions to the back
71
69
  }
72
70
  setAttr(input, 'id', inputId);
73
71
  setAttr(input, 'aria-describedby', describedbyIds.join(' ').trim());
@@ -24,6 +24,9 @@ var suggestionOption = require('./suggestion-option.js');
24
24
  * </Suggestion>
25
25
  */
26
26
  const EXPERIMENTAL_Suggestion = Object.assign(suggestion.Suggestion, {
27
+ /**
28
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
29
+ */
27
30
  Chips: suggestionChips.SuggestionChips,
28
31
  List: suggestionList.SuggestionList,
29
32
  Input: suggestionInput.SuggestionInput,
@@ -1,14 +1,12 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var jsxRuntime = require('react/jsx-runtime');
5
- var react = require('react');
6
- var index = require('../chip/index.js');
7
- var suggestion = require('./suggestion.js');
8
-
9
- const SuggestionChips = ({ render = ({ label }) => label, }) => {
10
- const { selectedItems = [] } = react.useContext(suggestion.SuggestionContext);
11
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: selectedItems.map((item) => (jsxRuntime.jsx(index.Chip.Removable, { value: item.value, asChild: true, children: jsxRuntime.jsx("data", { children: render(item) }) }, item.value))) }));
4
+ /**
5
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
6
+ */
7
+ const SuggestionChips = () => {
8
+ console.warn('Suggestion: Using <Suggestion.Chips> is deprecated - please remove from your code.');
9
+ return null;
12
10
  };
13
11
  SuggestionChips.displayName = 'SuggestionChips';
14
12
 
@@ -18,20 +18,17 @@ var suggestion = require('./suggestion.js');
18
18
  * </Suggestion>
19
19
  */
20
20
  const SuggestionInput = react.forwardRef(function SuggestionList({ value, onInput, onChange, ...rest }, ref) {
21
- const { listId, handleFilter } = react.useContext(suggestion.SuggestionContext);
21
+ const { handleFilter } = react.useContext(suggestion.SuggestionContext);
22
22
  react.useEffect(handleFilter, [value]); // Filter if controlled value
23
23
  if (onChange)
24
24
  console.warn('SuggestionInput: Avoid using onChange, as Suggestion controls the Input. Use onValueChange on Suggest instead, or onInput if fetching API results');
25
25
  if (value)
26
26
  console.warn('SuggestionInput: Avoid using value, as Suggestion controls the Input. Use value on Suggest instead.');
27
- const popoverProps = Object.assign({
28
- [react.version.startsWith('19') ? 'popoverTarget' : 'popovertarget']: listId,
29
- }, rest);
30
27
  return (jsxRuntime.jsx(input.Input, { placeholder: '' // We need an empty placeholder for the clear button to be able to show/hide
31
28
  , ref: ref, onInput: (event) => {
32
29
  onInput?.(event); // Should run first
33
30
  handleFilter?.(); // Filter if uncontrolled value
34
- }, ...popoverProps }));
31
+ }, ...rest }));
35
32
  });
36
33
 
37
34
  exports.SuggestionInput = SuggestionInput;
@@ -6,7 +6,6 @@ var react = require('react');
6
6
  require('@u-elements/u-datalist');
7
7
  var dom = require('@floating-ui/dom');
8
8
  var suggestion = require('./suggestion.js');
9
- var useMergeRefs = require('../../utilities/hooks/use-merge-refs/use-merge-refs.js');
10
9
 
11
10
  /**
12
11
  * Component that provides a Suggestion list.
@@ -20,17 +19,12 @@ var useMergeRefs = require('../../utilities/hooks/use-merge-refs/use-merge-refs.
20
19
  * </Suggestion>
21
20
  */
22
21
  const SuggestionList = react.forwardRef(function SuggestionList({ singular = '%d forslag', plural = '%d forslag', className, id, ...rest }, ref) {
23
- const { listId, setListId, handleFilter } = react.useContext(suggestion.SuggestionContext);
24
- const listRef = react.useRef(null);
25
- const mergedRefs = useMergeRefs.useMergeRefs([ref, listRef]);
22
+ const { handleFilter, uComboboxRef } = react.useContext(suggestion.SuggestionContext);
26
23
  react.useEffect(handleFilter); // Must run on every render
27
- react.useEffect(() => {
28
- id && setListId(id);
29
- }, [id]);
30
24
  // Position with floating-ui
31
25
  react.useEffect(() => {
32
- const list = listRef.current;
33
- const trigger = document.querySelector(`[popovertarget="${list?.id}"]`);
26
+ const trigger = uComboboxRef?.current?.control;
27
+ const list = uComboboxRef?.current?.list;
34
28
  if (list && trigger) {
35
29
  return dom.autoUpdate(trigger, list, () => {
36
30
  dom.computePosition(trigger, list, {
@@ -42,8 +36,8 @@ const SuggestionList = react.forwardRef(function SuggestionList({ singular = '%d
42
36
  });
43
37
  });
44
38
  }
45
- }, [listId]);
46
- return (jsxRuntime.jsx("u-datalist", { "data-nofilter": true, "data-sr-singular": singular, "data-sr-plural": plural, class: className, ref: mergedRefs, id: listId, popover: 'manual', ...rest }));
39
+ }, []);
40
+ return (jsxRuntime.jsx("u-datalist", { "data-nofilter": true, "data-sr-singular": singular, "data-sr-plural": plural, class: className, ref: ref, popover: 'manual', ...rest }));
47
41
  });
48
42
  const triggerWidth = {
49
43
  name: 'TriggerWidth',
@@ -5,10 +5,10 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
  var react = require('react');
6
6
  require('@u-elements/u-combobox');
7
7
  var cl = require('clsx/lite');
8
+ var index = require('../chip/index.js');
8
9
  var useMergeRefs = require('../../utilities/hooks/use-merge-refs/use-merge-refs.js');
9
10
 
10
11
  const SuggestionContext = react.createContext({
11
- setListId: () => undefined,
12
12
  handleFilter: () => undefined,
13
13
  });
14
14
  const text = (el) => el.textContent?.trim() || '';
@@ -29,16 +29,26 @@ const nextItems = (data, prev, multiple) => {
29
29
  : [...sanitizeItems(prev), item];
30
30
  };
31
31
  const defaultFilter = ({ label, input }) => label.toLowerCase().includes(input.value.trim().toLowerCase());
32
- const Suggestion = react.forwardRef(function Suggestion({ children, className, creatable = false, defaultValue, filter = true, multiple = false, name, onValueChange, value, ...rest }, ref) {
32
+ const deprecate = (from, to) => console.warn(`Suggestion: Using "${from}" is deprecated, please use "${to}" instead.`);
33
+ const Suggestion = react.forwardRef(function Suggestion({ children, className, creatable = false, defaultSelected: _defaultSelected, defaultValue, filter = true, multiple = false, name, onBeforeMatch, onSelectedChange: _onSelectedChange, onValueChange, renderSelected = ({ label }) => label, selected: _selected, value, ...rest }, ref) {
34
+ // For backwards compatibility:
35
+ const selected = _selected ?? value;
36
+ const defaultSelected = _defaultSelected ?? defaultValue;
37
+ const onSelectedChange = _onSelectedChange ?? onValueChange;
38
+ if (value)
39
+ deprecate('value', 'selected');
40
+ if (defaultValue)
41
+ deprecate('defaultValue', 'defaultSelected');
42
+ if (onValueChange)
43
+ deprecate('onValueChange', 'onSelectedChange');
33
44
  const uComboboxRef = react.useRef(null);
34
45
  const genId = react.useId();
35
46
  const selectId = rest.id ? `${rest.id}-select` : genId;
36
- const isControlled = value !== undefined;
47
+ const isControlled = selected !== undefined;
37
48
  const mergedRefs = useMergeRefs.useMergeRefs([ref, uComboboxRef]);
38
- const [listId, setListId] = react.useState(`${rest.id || genId}-list`);
39
49
  const [isEmpty, setIsEmpty] = react.useState(false);
40
- const [defaultItems, setDefaultItems] = react.useState(sanitizeItems(defaultValue));
41
- const selectedItems = value ? sanitizeItems(value) : defaultItems;
50
+ const [defaultItems, setDefaultItems] = react.useState(sanitizeItems(defaultSelected));
51
+ const selectedItems = selected ? sanitizeItems(selected) : defaultItems;
42
52
  /**
43
53
  * Listerners and handling of adding/removing
44
54
  */
@@ -49,13 +59,20 @@ const Suggestion = react.forwardRef(function Suggestion({ children, className, c
49
59
  const multiple = combobox?.multiple;
50
60
  const data = event.detail;
51
61
  if (isControlled)
52
- onValueChange?.(nextItems(data, selectedItems, multiple));
62
+ onSelectedChange?.(nextItems(data, selectedItems, multiple));
53
63
  else
54
64
  setDefaultItems(nextItems(data, selectedItems, multiple));
55
65
  };
56
66
  combobox?.addEventListener('beforechange', beforeChange);
57
67
  return () => combobox?.removeEventListener('beforechange', beforeChange);
58
68
  }, [selectedItems, isControlled]);
69
+ // Before match event listener
70
+ react.useEffect(() => {
71
+ const combobox = uComboboxRef.current;
72
+ const beforeMatch = (e) => onBeforeMatch?.(e);
73
+ combobox?.addEventListener('beforematch', beforeMatch);
74
+ return () => combobox?.removeEventListener('beforematch', beforeMatch);
75
+ }, [onBeforeMatch]);
59
76
  const handleFilter = react.useCallback(() => {
60
77
  const { control: input, options = [] } = uComboboxRef?.current || {};
61
78
  const filterFn = filter === true ? defaultFilter : filter;
@@ -77,7 +94,7 @@ const Suggestion = react.forwardRef(function Suggestion({ children, className, c
77
94
  }
78
95
  setIsEmpty(index === disabled);
79
96
  }, [filter]);
80
- return (jsxRuntime.jsx(SuggestionContext.Provider, { value: { isEmpty, selectedItems, listId, setListId, handleFilter }, children: jsxRuntime.jsxs("u-combobox", { "data-multiple": multiple || undefined, "data-creatable": creatable || undefined, class: cl('ds-suggestion', className), ref: mergedRefs, ...rest, children: [children, !!name && (jsxRuntime.jsx("select", { name: name, multiple: true, hidden: true, id: selectId }))] }) }));
97
+ return (jsxRuntime.jsx(SuggestionContext.Provider, { value: { isEmpty, handleFilter, uComboboxRef }, children: jsxRuntime.jsxs("u-combobox", { "data-multiple": multiple || undefined, "data-creatable": creatable || undefined, class: cl('ds-suggestion', className), ref: mergedRefs, ...rest, children: [selectedItems.map((item) => (jsxRuntime.jsx(index.Chip.Removable, { value: item.value, asChild: true, children: jsxRuntime.jsx("data", { children: renderSelected(item) }) }, item.value))), children, !!name && (jsxRuntime.jsx("select", { name: name, multiple: true, hidden: true, id: selectId }))] }) }));
81
98
  });
82
99
 
83
100
  exports.Suggestion = Suggestion;
@@ -71,9 +71,8 @@ const Dialog = forwardRef(function Dialog({ asChild, children, className, closeB
71
71
  /* handle closing */
72
72
  useEffect(() => {
73
73
  const handleClose = (event) => onClose?.(event);
74
- const currentRef = dialogRef.current;
75
- currentRef?.addEventListener('close', handleClose);
76
- return () => currentRef?.removeEventListener('close', handleClose);
74
+ dialogRef.current?.addEventListener('close', handleClose);
75
+ return () => dialogRef.current?.removeEventListener('close', handleClose);
77
76
  }, [onClose]);
78
77
  return (jsxs(Component, { className: cl('ds-dialog', className), ref: mergedRefs, "data-modal": modal, ...rest, children: [closeButton !== false && (jsx("form", { method: 'dialog', children: jsx(Button, { "aria-label": closeButton, autoFocus: true, "data-color": 'neutral', icon: true, name: 'close', type: 'submit', variant: 'tertiary' }) })), children] }));
79
78
  });
@@ -42,7 +42,7 @@ function fieldObserver(fieldElement) {
42
42
  }
43
43
  }
44
44
  // Connect elements
45
- const describedbyIds = describedby ? describedby.split(' ') : []; // Keep original aria-describedby
45
+ const describedbyIds = [describedby]; // Keep original aria-describedby
46
46
  const inputId = input?.id || uuid;
47
47
  // Reset type counters since we reprocess all elements
48
48
  typeCounter.clear();
@@ -60,12 +60,10 @@ function fieldObserver(fieldElement) {
60
60
  }
61
61
  if (!value)
62
62
  setAttr(el, isLabel(el) ? 'for' : 'id', id); // Ensure we have a value
63
- if (!describedbyIds.includes(el.id)) {
64
- if (descriptionType === 'validation')
65
- describedbyIds.unshift(el.id); // Validations to the front
66
- else if (descriptionType)
67
- describedbyIds.push(el.id); // Other descriptions to the back
68
- }
63
+ if (descriptionType === 'validation')
64
+ describedbyIds.unshift(el.id); // Validations to the front
65
+ else if (descriptionType)
66
+ describedbyIds.push(el.id); // Other descriptions to the back
69
67
  }
70
68
  setAttr(input, 'id', inputId);
71
69
  setAttr(input, 'aria-describedby', describedbyIds.join(' ').trim());
@@ -22,6 +22,9 @@ import { SuggestionOption } from './suggestion-option.js';
22
22
  * </Suggestion>
23
23
  */
24
24
  const EXPERIMENTAL_Suggestion = Object.assign(Suggestion, {
25
+ /**
26
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
27
+ */
25
28
  Chips: SuggestionChips,
26
29
  List: SuggestionList,
27
30
  Input: SuggestionInput,
@@ -1,12 +1,10 @@
1
1
  'use client';
2
- import { jsx, Fragment } from 'react/jsx-runtime';
3
- import { useContext } from 'react';
4
- import { Chip } from '../chip/index.js';
5
- import { SuggestionContext } from './suggestion.js';
6
-
7
- const SuggestionChips = ({ render = ({ label }) => label, }) => {
8
- const { selectedItems = [] } = useContext(SuggestionContext);
9
- return (jsx(Fragment, { children: selectedItems.map((item) => (jsx(Chip.Removable, { value: item.value, asChild: true, children: jsx("data", { children: render(item) }) }, item.value))) }));
2
+ /**
3
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
4
+ */
5
+ const SuggestionChips = () => {
6
+ console.warn('Suggestion: Using <Suggestion.Chips> is deprecated - please remove from your code.');
7
+ return null;
10
8
  };
11
9
  SuggestionChips.displayName = 'SuggestionChips';
12
10
 
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { forwardRef, useContext, useEffect, version } from 'react';
3
+ import { forwardRef, useContext, useEffect } from 'react';
4
4
  import { Input } from '../input/input.js';
5
5
  import { SuggestionContext } from './suggestion.js';
6
6
 
@@ -16,20 +16,17 @@ import { SuggestionContext } from './suggestion.js';
16
16
  * </Suggestion>
17
17
  */
18
18
  const SuggestionInput = forwardRef(function SuggestionList({ value, onInput, onChange, ...rest }, ref) {
19
- const { listId, handleFilter } = useContext(SuggestionContext);
19
+ const { handleFilter } = useContext(SuggestionContext);
20
20
  useEffect(handleFilter, [value]); // Filter if controlled value
21
21
  if (onChange)
22
22
  console.warn('SuggestionInput: Avoid using onChange, as Suggestion controls the Input. Use onValueChange on Suggest instead, or onInput if fetching API results');
23
23
  if (value)
24
24
  console.warn('SuggestionInput: Avoid using value, as Suggestion controls the Input. Use value on Suggest instead.');
25
- const popoverProps = Object.assign({
26
- [version.startsWith('19') ? 'popoverTarget' : 'popovertarget']: listId,
27
- }, rest);
28
25
  return (jsx(Input, { placeholder: '' // We need an empty placeholder for the clear button to be able to show/hide
29
26
  , ref: ref, onInput: (event) => {
30
27
  onInput?.(event); // Should run first
31
28
  handleFilter?.(); // Filter if uncontrolled value
32
- }, ...popoverProps }));
29
+ }, ...rest }));
33
30
  });
34
31
 
35
32
  export { SuggestionInput };
@@ -1,10 +1,9 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { forwardRef, useContext, useRef, useEffect } from 'react';
3
+ import { forwardRef, useContext, useEffect } from 'react';
4
4
  import '@u-elements/u-datalist';
5
5
  import { autoUpdate, computePosition } from '@floating-ui/dom';
6
6
  import { SuggestionContext } from './suggestion.js';
7
- import { useMergeRefs } from '../../utilities/hooks/use-merge-refs/use-merge-refs.js';
8
7
 
9
8
  /**
10
9
  * Component that provides a Suggestion list.
@@ -18,17 +17,12 @@ import { useMergeRefs } from '../../utilities/hooks/use-merge-refs/use-merge-ref
18
17
  * </Suggestion>
19
18
  */
20
19
  const SuggestionList = forwardRef(function SuggestionList({ singular = '%d forslag', plural = '%d forslag', className, id, ...rest }, ref) {
21
- const { listId, setListId, handleFilter } = useContext(SuggestionContext);
22
- const listRef = useRef(null);
23
- const mergedRefs = useMergeRefs([ref, listRef]);
20
+ const { handleFilter, uComboboxRef } = useContext(SuggestionContext);
24
21
  useEffect(handleFilter); // Must run on every render
25
- useEffect(() => {
26
- id && setListId(id);
27
- }, [id]);
28
22
  // Position with floating-ui
29
23
  useEffect(() => {
30
- const list = listRef.current;
31
- const trigger = document.querySelector(`[popovertarget="${list?.id}"]`);
24
+ const trigger = uComboboxRef?.current?.control;
25
+ const list = uComboboxRef?.current?.list;
32
26
  if (list && trigger) {
33
27
  return autoUpdate(trigger, list, () => {
34
28
  computePosition(trigger, list, {
@@ -40,8 +34,8 @@ const SuggestionList = forwardRef(function SuggestionList({ singular = '%d forsl
40
34
  });
41
35
  });
42
36
  }
43
- }, [listId]);
44
- return (jsx("u-datalist", { "data-nofilter": true, "data-sr-singular": singular, "data-sr-plural": plural, class: className, ref: mergedRefs, id: listId, popover: 'manual', ...rest }));
37
+ }, []);
38
+ return (jsx("u-datalist", { "data-nofilter": true, "data-sr-singular": singular, "data-sr-plural": plural, class: className, ref: ref, popover: 'manual', ...rest }));
45
39
  });
46
40
  const triggerWidth = {
47
41
  name: 'TriggerWidth',
@@ -3,10 +3,10 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import { forwardRef, createContext, useRef, useId, useState, useEffect, useCallback } from 'react';
4
4
  import '@u-elements/u-combobox';
5
5
  import cl from 'clsx/lite';
6
+ import { Chip } from '../chip/index.js';
6
7
  import { useMergeRefs } from '../../utilities/hooks/use-merge-refs/use-merge-refs.js';
7
8
 
8
9
  const SuggestionContext = createContext({
9
- setListId: () => undefined,
10
10
  handleFilter: () => undefined,
11
11
  });
12
12
  const text = (el) => el.textContent?.trim() || '';
@@ -27,16 +27,26 @@ const nextItems = (data, prev, multiple) => {
27
27
  : [...sanitizeItems(prev), item];
28
28
  };
29
29
  const defaultFilter = ({ label, input }) => label.toLowerCase().includes(input.value.trim().toLowerCase());
30
- const Suggestion = forwardRef(function Suggestion({ children, className, creatable = false, defaultValue, filter = true, multiple = false, name, onValueChange, value, ...rest }, ref) {
30
+ const deprecate = (from, to) => console.warn(`Suggestion: Using "${from}" is deprecated, please use "${to}" instead.`);
31
+ const Suggestion = forwardRef(function Suggestion({ children, className, creatable = false, defaultSelected: _defaultSelected, defaultValue, filter = true, multiple = false, name, onBeforeMatch, onSelectedChange: _onSelectedChange, onValueChange, renderSelected = ({ label }) => label, selected: _selected, value, ...rest }, ref) {
32
+ // For backwards compatibility:
33
+ const selected = _selected ?? value;
34
+ const defaultSelected = _defaultSelected ?? defaultValue;
35
+ const onSelectedChange = _onSelectedChange ?? onValueChange;
36
+ if (value)
37
+ deprecate('value', 'selected');
38
+ if (defaultValue)
39
+ deprecate('defaultValue', 'defaultSelected');
40
+ if (onValueChange)
41
+ deprecate('onValueChange', 'onSelectedChange');
31
42
  const uComboboxRef = useRef(null);
32
43
  const genId = useId();
33
44
  const selectId = rest.id ? `${rest.id}-select` : genId;
34
- const isControlled = value !== undefined;
45
+ const isControlled = selected !== undefined;
35
46
  const mergedRefs = useMergeRefs([ref, uComboboxRef]);
36
- const [listId, setListId] = useState(`${rest.id || genId}-list`);
37
47
  const [isEmpty, setIsEmpty] = useState(false);
38
- const [defaultItems, setDefaultItems] = useState(sanitizeItems(defaultValue));
39
- const selectedItems = value ? sanitizeItems(value) : defaultItems;
48
+ const [defaultItems, setDefaultItems] = useState(sanitizeItems(defaultSelected));
49
+ const selectedItems = selected ? sanitizeItems(selected) : defaultItems;
40
50
  /**
41
51
  * Listerners and handling of adding/removing
42
52
  */
@@ -47,13 +57,20 @@ const Suggestion = forwardRef(function Suggestion({ children, className, creatab
47
57
  const multiple = combobox?.multiple;
48
58
  const data = event.detail;
49
59
  if (isControlled)
50
- onValueChange?.(nextItems(data, selectedItems, multiple));
60
+ onSelectedChange?.(nextItems(data, selectedItems, multiple));
51
61
  else
52
62
  setDefaultItems(nextItems(data, selectedItems, multiple));
53
63
  };
54
64
  combobox?.addEventListener('beforechange', beforeChange);
55
65
  return () => combobox?.removeEventListener('beforechange', beforeChange);
56
66
  }, [selectedItems, isControlled]);
67
+ // Before match event listener
68
+ useEffect(() => {
69
+ const combobox = uComboboxRef.current;
70
+ const beforeMatch = (e) => onBeforeMatch?.(e);
71
+ combobox?.addEventListener('beforematch', beforeMatch);
72
+ return () => combobox?.removeEventListener('beforematch', beforeMatch);
73
+ }, [onBeforeMatch]);
57
74
  const handleFilter = useCallback(() => {
58
75
  const { control: input, options = [] } = uComboboxRef?.current || {};
59
76
  const filterFn = filter === true ? defaultFilter : filter;
@@ -75,7 +92,7 @@ const Suggestion = forwardRef(function Suggestion({ children, className, creatab
75
92
  }
76
93
  setIsEmpty(index === disabled);
77
94
  }, [filter]);
78
- return (jsx(SuggestionContext.Provider, { value: { isEmpty, selectedItems, listId, setListId, handleFilter }, children: jsxs("u-combobox", { "data-multiple": multiple || undefined, "data-creatable": creatable || undefined, class: cl('ds-suggestion', className), ref: mergedRefs, ...rest, children: [children, !!name && (jsx("select", { name: name, multiple: true, hidden: true, id: selectId }))] }) }));
95
+ return (jsx(SuggestionContext.Provider, { value: { isEmpty, handleFilter, uComboboxRef }, children: jsxs("u-combobox", { "data-multiple": multiple || undefined, "data-creatable": creatable || undefined, class: cl('ds-suggestion', className), ref: mergedRefs, ...rest, children: [selectedItems.map((item) => (jsx(Chip.Removable, { value: item.value, asChild: true, children: jsx("data", { children: renderSelected(item) }) }, item.value))), children, !!name && (jsx("select", { name: name, multiple: true, hidden: true, id: selectId }))] }) }));
79
96
  });
80
97
 
81
98
  export { Suggestion, SuggestionContext };
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/components/dialog/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlD,MAAM,MAAM,WAAW,GAAG,UAAU,CAClC,YAAY,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,EACtD;IACE;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,KAAK,CAAC;IAC3C;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,MAAM;IA1Df;;;OAGG;kBACW,MAAM,GAAG,KAAK;IAC5B;;;;OAIG;eACQ,MAAM,GAAG,cAAc,GAAG,KAAK;IAC1C;;;;;;OAMG;YACK,OAAO;IACf;;OAEG;WACI,OAAO;IACd;;OAEG;cACO,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IAChC;;;OAGG;cACO,OAAO;2CAqHpB,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/components/dialog/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlD,MAAM,MAAM,WAAW,GAAG,UAAU,CAClC,YAAY,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,EACtD;IACE;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,KAAK,CAAC;IAC3C;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,MAAM;IA1Df;;;OAGG;kBACW,MAAM,GAAG,KAAK;IAC5B;;;;OAIG;eACQ,MAAM,GAAG,cAAc,GAAG,KAAK;IAC1C;;;;;;OAMG;YACK,OAAO;IACf;;OAEG;WACI,OAAO;IACd;;OAEG;cACO,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IAChC;;;OAGG;cACO,OAAO;2CAoHpB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-observer.d.ts","sourceRoot":"","sources":["../../../src/components/field/field-observer.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,4BAsF7D;AAGD,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,oBAA4B,CAAC;AACjE,eAAO,MAAM,OAAO,GAAI,MAAM,IAAI,6BAAqC,CAAC;AACxE,eAAO,MAAM,WAAW,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,gBAGd,CAAC"}
1
+ {"version":3,"file":"field-observer.d.ts","sourceRoot":"","sources":["../../../src/components/field/field-observer.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,4BAoF7D;AAGD,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,oBAA4B,CAAC;AACjE,eAAO,MAAM,OAAO,GAAI,MAAM,IAAI,6BAAqC,CAAC;AACxE,eAAO,MAAM,WAAW,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,gBAGd,CAAC"}
@@ -29,16 +29,32 @@ declare const EXPERIMENTAL_Suggestion: React.ForwardRefExoticComponent<{
29
29
  }) => boolean);
30
30
  creatable?: boolean;
31
31
  multiple?: boolean;
32
- value?: import("./suggestion").SuggestionValues;
33
- defaultValue?: import("./suggestion").SuggestionValues;
32
+ selected?: import("./suggestion").SuggestionSelected;
33
+ value?: import("./suggestion").SuggestionSelected;
34
+ defaultSelected?: import("./suggestion").SuggestionSelected;
35
+ defaultValue?: import("./suggestion").SuggestionSelected;
36
+ onSelectedChange?: (value: {
37
+ label: string;
38
+ value: string;
39
+ }[]) => void;
34
40
  onValueChange?: (value: {
35
41
  label: string;
36
42
  value: string;
37
43
  }[]) => void;
44
+ onBeforeMatch?: (event: Omit<CustomEvent<HTMLOptionElement | undefined>, "currentTarget"> & {
45
+ currentTarget: import("@u-elements/u-combobox").UHTMLComboboxElement;
46
+ }) => void;
38
47
  name?: string;
48
+ renderSelected?: (args: {
49
+ label: string;
50
+ value: string;
51
+ }) => React.ReactNode;
39
52
  } & React.HTMLAttributes<import("@u-elements/u-combobox").UHTMLComboboxElement> & React.RefAttributes<import("@u-elements/u-combobox").UHTMLComboboxElement>> & {
53
+ /**
54
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
55
+ */
40
56
  Chips: {
41
- ({ render, }: import("./suggestion-chips").SuggestionChipsProps): import("react/jsx-runtime").JSX.Element;
57
+ (): null;
42
58
  displayName: string;
43
59
  };
44
60
  List: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.HTMLAttributes<HTMLDataListElement>, "singular" | "plural"> & {
@@ -58,8 +74,13 @@ declare const EXPERIMENTAL_Suggestion: React.ForwardRefExoticComponent<{
58
74
  'aria-label'?: string;
59
75
  } & React.RefAttributes<HTMLButtonElement>>;
60
76
  };
61
- export { EXPERIMENTAL_Suggestion, SuggestionChips as EXPERIMENTAL_SuggestionChips, SuggestionList as EXPERIMENTAL_SuggestionList, SuggestionInput as EXPERIMENTAL_SuggestionInput, SuggestionEmpty as EXPERIMENTAL_SuggestionEmpty, SuggestionOption as EXPERIMENTAL_SuggestionOption, SuggestionClear as EXPERIMENTAL_SuggestionClear, };
62
- export type { SuggestionProps, SuggestionValues } from './suggestion';
77
+ export { EXPERIMENTAL_Suggestion,
78
+ /**
79
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
80
+ */
81
+ SuggestionChips as EXPERIMENTAL_SuggestionChips, SuggestionList as EXPERIMENTAL_SuggestionList, SuggestionInput as EXPERIMENTAL_SuggestionInput, SuggestionEmpty as EXPERIMENTAL_SuggestionEmpty, SuggestionOption as EXPERIMENTAL_SuggestionOption, SuggestionClear as EXPERIMENTAL_SuggestionClear, };
82
+ export type { SuggestionProps, SuggestionSelected, // Export SuggestionValues for easier useState
83
+ SuggestionSelected as SuggestionValues, } from './suggestion';
63
84
  export type { SuggestionChipsProps } from './suggestion-chips';
64
85
  export type { SuggestionClearProps } from './suggestion-clear';
65
86
  export type { SuggestionEmptyProps } from './suggestion-empty';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAO3B,CAAC;AAUH,OAAO,EACL,uBAAuB,EACvB,eAAe,IAAI,4BAA4B,EAC/C,cAAc,IAAI,2BAA2B,EAC7C,eAAe,IAAI,4BAA4B,EAC/C,eAAe,IAAI,4BAA4B,EAC/C,gBAAgB,IAAI,6BAA6B,EACjD,eAAe,IAAI,4BAA4B,GAChD,CAAC;AACF,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACtE,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAC3B;;OAEG;;;;;;;;;;;;;;;;;;;;;CAOH,CAAC;AAUH,OAAO,EACL,uBAAuB;AACvB;;GAEG;AACH,eAAe,IAAI,4BAA4B,EAC/C,cAAc,IAAI,2BAA2B,EAC7C,eAAe,IAAI,4BAA4B,EAC/C,eAAe,IAAI,4BAA4B,EAC/C,gBAAgB,IAAI,6BAA6B,EACjD,eAAe,IAAI,4BAA4B,GAChD,CAAC;AACF,YAAY,EACV,eAAe,EACf,kBAAkB,EAAE,8CAA8C;AAClE,kBAAkB,IAAI,gBAAgB,GACvC,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,19 +1,11 @@
1
- import type { HTMLAttributes, ReactNode } from 'react';
1
+ import type { HTMLAttributes } from 'react';
2
2
  import type { DefaultProps } from '../../types';
3
- import type { MergeRight } from '../../utilities';
4
- export type SuggestionChipsProps = MergeRight<DefaultProps & HTMLAttributes<HTMLDivElement>, {
5
- /**
6
- * Change the rendered content of the chip.
7
- *
8
- * @default ({ label }) => label
9
- */
10
- render?: (args: {
11
- label: string;
12
- value: string;
13
- }) => ReactNode;
14
- }>;
3
+ export type SuggestionChipsProps = DefaultProps & HTMLAttributes<HTMLDivElement>;
4
+ /**
5
+ * @deprecated Suggestion.Chips is deprecated, use `renderSelected` on `Suggestion` instead
6
+ */
15
7
  export declare const SuggestionChips: {
16
- ({ render, }: SuggestionChipsProps): import("react/jsx-runtime").JSX.Element;
8
+ (): null;
17
9
  displayName: string;
18
10
  };
19
11
  //# sourceMappingURL=suggestion-chips.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suggestion-chips.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-chips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIlD,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAC3C,YAAY,GAAG,cAAc,CAAC,cAAc,CAAC,EAC7C;IACE;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;CAChE,CACF,CAAC;AAEF,eAAO,MAAM,eAAe;kBAEzB,oBAAoB;;CAYtB,CAAC"}
1
+ {"version":3,"file":"suggestion-chips.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-chips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAC7C,cAAc,CAAC,cAAc,CAAC,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,eAAe;;;CAK3B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"suggestion-input.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-input.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGxD,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAI9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC,GAAG,CAAC;QAClB,UAAU,mBAAmB;YAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB;KACF;IACD,UAAU,KAAK,CAAC;QAEd,UAAU,cAAc,CAAC,CAAC;YACxB,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB;KACF;CACF;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe;;;;;;0CAkC1B,CAAC"}
1
+ {"version":3,"file":"suggestion-input.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-input.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGxD,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAI9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK,CAAC,GAAG,CAAC;QAClB,UAAU,mBAAmB;YAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB;KACF;IACD,UAAU,KAAK,CAAC;QAEd,UAAU,cAAc,CAAC,CAAC;YACxB,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB;KACF;CACF;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe;;;;;;0CA2B1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"suggestion-list.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIlD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAC1C,YAAY,GAAG,cAAc,CAAC,mBAAmB,CAAC,EAClD;IACE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CACF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;IAxBvB;;;OAGG;eACQ,MAAM;IACjB;;;OAGG;aACM,MAAM;6CAgEjB,CAAC"}
1
+ {"version":3,"file":"suggestion-list.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion-list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAC1C,YAAY,GAAG,cAAc,CAAC,mBAAmB,CAAC,EAClD;IACE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CACF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;IAxBvB;;;OAGG;eACQ,MAAM;IACjB;;;OAGG;aACM,MAAM;6CAuDjB,CAAC"}
@@ -1,11 +1,14 @@
1
- import { type HTMLAttributes } from 'react';
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
2
  import '@u-elements/u-combobox';
3
3
  import type { UHTMLComboboxElement } from '@u-elements/u-combobox';
4
- export type SuggestionValues = Array<string | Partial<Item>> | string;
4
+ export type SuggestionSelected = Array<string | Partial<Item>> | string;
5
5
  type Item = {
6
6
  label: string;
7
7
  value: string;
8
8
  };
9
+ type EventBeforeMatch = Omit<CustomEvent<HTMLOptionElement | undefined>, 'currentTarget'> & {
10
+ currentTarget: UHTMLComboboxElement;
11
+ };
9
12
  type Filter = (args: {
10
13
  /**
11
14
  * Index of the `option`
@@ -33,11 +36,9 @@ type Filter = (args: {
33
36
  input: HTMLInputElement;
34
37
  }) => boolean;
35
38
  type SuggestionContextType = {
36
- isEmpty?: boolean;
37
- selectedItems?: Item[];
38
- listId?: string;
39
- setListId: (id: string) => void;
40
39
  handleFilter: (input?: HTMLInputElement | null) => void;
40
+ isEmpty?: boolean;
41
+ uComboboxRef?: React.RefObject<UHTMLComboboxElement | null>;
41
42
  };
42
43
  export declare const SuggestionContext: React.Context<SuggestionContextType>;
43
44
  export type SuggestionProps = {
@@ -64,24 +65,49 @@ export type SuggestionProps = {
64
65
  */
65
66
  multiple?: boolean;
66
67
  /**
67
- * The selected items of the multi-select.
68
- * Using this makes the component controlled and it must be used in combination with onValueChange
68
+ * The selected items of the Suggestion.
69
+ * Using this makes the component controlled and it must be used in combination with onSelectedChange.
70
+ */
71
+ selected?: SuggestionSelected;
72
+ /**
73
+ * @deprecated Use `selected` instead
69
74
  */
70
- value?: SuggestionValues;
75
+ value?: SuggestionSelected;
71
76
  /**
72
77
  * Default selected items when uncontrolled
73
78
  */
74
- defaultValue?: SuggestionValues;
79
+ defaultSelected?: SuggestionSelected;
80
+ /**
81
+ * @deprecated Use `defaultSelected` instead
82
+ */
83
+ defaultValue?: SuggestionSelected;
75
84
  /**
76
85
  * Callback when selected items changes
77
86
  */
87
+ onSelectedChange?: (value: Item[]) => void;
88
+ /**
89
+ * @deprecated Use `onSelectedChange` instead
90
+ */
78
91
  onValueChange?: (value: Item[]) => void;
92
+ /**
93
+ * Callback when matching input value against options
94
+ */
95
+ onBeforeMatch?: (event: EventBeforeMatch) => void;
79
96
  /**
80
97
  * The name of the associated form control
81
98
  *
82
99
  * @default undefined
83
100
  */
84
101
  name?: string;
102
+ /**
103
+ * Allows the user to select multiple items
104
+ *
105
+ * @default false
106
+ */
107
+ renderSelected?: (args: {
108
+ label: string;
109
+ value: string;
110
+ }) => ReactNode;
85
111
  } & HTMLAttributes<UHTMLComboboxElement>;
86
112
  export declare const Suggestion: React.ForwardRefExoticComponent<{
87
113
  /**
@@ -107,24 +133,49 @@ export declare const Suggestion: React.ForwardRefExoticComponent<{
107
133
  */
108
134
  multiple?: boolean;
109
135
  /**
110
- * The selected items of the multi-select.
111
- * Using this makes the component controlled and it must be used in combination with onValueChange
136
+ * The selected items of the Suggestion.
137
+ * Using this makes the component controlled and it must be used in combination with onSelectedChange.
138
+ */
139
+ selected?: SuggestionSelected;
140
+ /**
141
+ * @deprecated Use `selected` instead
112
142
  */
113
- value?: SuggestionValues;
143
+ value?: SuggestionSelected;
114
144
  /**
115
145
  * Default selected items when uncontrolled
116
146
  */
117
- defaultValue?: SuggestionValues;
147
+ defaultSelected?: SuggestionSelected;
148
+ /**
149
+ * @deprecated Use `defaultSelected` instead
150
+ */
151
+ defaultValue?: SuggestionSelected;
118
152
  /**
119
153
  * Callback when selected items changes
120
154
  */
155
+ onSelectedChange?: (value: Item[]) => void;
156
+ /**
157
+ * @deprecated Use `onSelectedChange` instead
158
+ */
121
159
  onValueChange?: (value: Item[]) => void;
160
+ /**
161
+ * Callback when matching input value against options
162
+ */
163
+ onBeforeMatch?: (event: EventBeforeMatch) => void;
122
164
  /**
123
165
  * The name of the associated form control
124
166
  *
125
167
  * @default undefined
126
168
  */
127
169
  name?: string;
170
+ /**
171
+ * Allows the user to select multiple items
172
+ *
173
+ * @default false
174
+ */
175
+ renderSelected?: (args: {
176
+ label: string;
177
+ value: string;
178
+ }) => ReactNode;
128
179
  } & HTMLAttributes<UHTMLComboboxElement> & React.RefAttributes<UHTMLComboboxElement>>;
129
180
  export {};
130
181
  //# sourceMappingURL=suggestion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suggestion.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EAMpB,MAAM,OAAO,CAAC;AACf,OAAO,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAInE,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;AAEtE,KAAK,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC7C,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE;IACnB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC;;OAEG;IACH,KAAK,EAAE,gBAAgB,CAAC;CACzB,KAAK,OAAO,CAAC;AAEd,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,YAAY,EAAE,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,sCAG5B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAgCzC,eAAO,MAAM,UAAU;IAzErB;;;;;;;;OAQG;aACM,OAAO,GAAG,MAAM;IACzB;;;;OAIG;gBACS,OAAO;IACnB;;;;OAIG;eACQ,OAAO;IAClB;;;OAGG;YACK,gBAAgB;IACxB;;OAEG;mBACY,gBAAgB;IAC/B;;OAEG;oBACa,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI;IACvC;;;;OAIG;WACI,MAAM;qFA4Hd,CAAC"}
1
+ {"version":3,"file":"suggestion.d.ts","sourceRoot":"","sources":["../../../src/components/suggestion/suggestion.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@digdir/designsystemet-react",
3
3
  "type": "module",
4
- "version": "0.0.0-test-20250715062533",
4
+ "version": "0.0.0-test-20250715110951",
5
5
  "description": "React components for Designsystemet",
6
6
  "author": "Designsystemet team",
7
7
  "repository": {
@@ -41,7 +41,7 @@
41
41
  "@navikt/aksel-icons": "^7.25.1",
42
42
  "@radix-ui/react-slot": "^1.2.3",
43
43
  "@tanstack/react-virtual": "^3.13.12",
44
- "@u-elements/u-combobox": "^0.0.17",
44
+ "@u-elements/u-combobox": "^0.0.18",
45
45
  "@u-elements/u-datalist": "^1.0.10",
46
46
  "@u-elements/u-details": "^0.1.1",
47
47
  "clsx": "^2.1.1"
@@ -67,7 +67,7 @@
67
67
  "storybook": "^9.0.15",
68
68
  "tsx": "4.20.3",
69
69
  "typescript": "^5.8.3",
70
- "@digdir/designsystemet-css": "^0.0.0-test-20250715062533"
70
+ "@digdir/designsystemet-css": "^0.0.0-test-20250715110951"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "pnpm run clean && tsc -b tsconfig.lib.json --emitDeclarationOnly false && rollup -c --bundleConfigAsCjs",