allaw-ui 2.4.8 → 2.4.9

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.
@@ -12,6 +12,7 @@ export interface SelectProps<T extends string | string[]> {
12
12
  isRequired?: boolean;
13
13
  showError?: boolean;
14
14
  width?: number;
15
+ maxItems?: number;
15
16
  onChange?: (selected: T) => void;
16
17
  onError?: (error: string) => void;
17
18
  }
@@ -14,18 +14,21 @@ import "../../../styles/global.css";
14
14
  import TinyInfo from "../typography/TinyInfo";
15
15
  function Select(_a, ref) {
16
16
  var _b;
17
- var items = _a.items, selectedItem = _a.selectedItem, _c = _a.placeholder, placeholder = _c === void 0 ? "Choisir..." : _c, _d = _a.multiple, multiple = _d === void 0 ? false : _d, _e = _a.isRequired, isRequired = _e === void 0 ? false : _e, _f = _a.showError, showError = _f === void 0 ? false : _f, _g = _a.width, width = _g === void 0 ? 100 : _g, onChange = _a.onChange, onError = _a.onError;
17
+ var items = _a.items, selectedItem = _a.selectedItem, _c = _a.placeholder, placeholder = _c === void 0 ? "Choisir..." : _c, _d = _a.multiple, multiple = _d === void 0 ? false : _d, _e = _a.isRequired, isRequired = _e === void 0 ? false : _e, _f = _a.showError, showError = _f === void 0 ? false : _f, _g = _a.width, width = _g === void 0 ? 100 : _g, maxItems = _a.maxItems, onChange = _a.onChange, onError = _a.onError;
18
18
  var _h = useState(false), isOpen = _h[0], setIsOpen = _h[1];
19
19
  var _j = useState((multiple ? selectedItem || [] : selectedItem || "")), selected = _j[0], setSelected = _j[1];
20
20
  var _k = useState(""), error = _k[0], setError = _k[1];
21
21
  var selectRef = useRef(null);
22
22
  var listRef = useRef(null);
23
- var _l = useState({
23
+ var tagContainerRef = useRef(null);
24
+ var _l = useState([]), visibleTags = _l[0], setVisibleTags = _l[1];
25
+ var _m = useState(0), hiddenCount = _m[0], setHiddenCount = _m[1];
26
+ var _o = useState({
24
27
  top: 0,
25
28
  left: 0,
26
29
  width: 0,
27
- }), listPosition = _l[0], setListPosition = _l[1];
28
- var _m = useState("bottom"), placement = _m[0], setPlacement = _m[1];
30
+ }), listPosition = _o[0], setListPosition = _o[1];
31
+ var _p = useState("bottom"), placement = _p[0], setPlacement = _p[1];
29
32
  useEffect(function () {
30
33
  setSelected((multiple ? selectedItem || [] : selectedItem || ""));
31
34
  }, [selectedItem, multiple]);
@@ -40,14 +43,70 @@ function Select(_a, ref) {
40
43
  }
41
44
  }
42
45
  }, [isOpen, multiple, selectedItem]);
46
+ useEffect(function () {
47
+ if (tagContainerRef.current &&
48
+ Array.isArray(selected) &&
49
+ selected.length > 0) {
50
+ // Initialiser avec tous les tags visibles
51
+ setVisibleTags(selected);
52
+ setHiddenCount(0);
53
+ // Attendre le prochain rendu pour mesurer les dimensions
54
+ requestAnimationFrame(function () {
55
+ var container = tagContainerRef.current;
56
+ if (!container)
57
+ return;
58
+ var containerWidth = container.offsetWidth - 40; // Espace pour l'icône et les marges
59
+ var totalWidth = 0;
60
+ var visibleCount = selected.length;
61
+ // Première passe : mesurer la taille réelle de chaque tag
62
+ var tagWidths = Array.from(container.children)
63
+ .filter(function (child) { return !child.classList.contains("hiddenTagCount"); })
64
+ .map(function (tag) { return tag.offsetWidth + 6; }); // 6px pour le gap
65
+ // Deuxième passe : calculer combien de tags peuvent tenir
66
+ var counterWidth = 60; // Espace estimé pour "+ x autres"
67
+ for (var i = 0; i < tagWidths.length; i++) {
68
+ var currentTagWidth = tagWidths[i];
69
+ var nextWidth = totalWidth + currentTagWidth;
70
+ // Si on ajoute ce tag, aurons-nous assez d'espace pour le compteur ?
71
+ var remainingTags = selected.length - (i + 1);
72
+ var needsCounter = remainingTags > 0;
73
+ var spaceNeeded = needsCounter ? counterWidth : 0;
74
+ if (nextWidth + spaceNeeded <= containerWidth) {
75
+ totalWidth = nextWidth;
76
+ visibleCount = i + 1;
77
+ }
78
+ else {
79
+ break;
80
+ }
81
+ }
82
+ // Mettre à jour les états
83
+ if (visibleCount < selected.length) {
84
+ setVisibleTags(selected.slice(0, visibleCount));
85
+ setHiddenCount(selected.length - visibleCount);
86
+ }
87
+ });
88
+ }
89
+ else {
90
+ setVisibleTags([]);
91
+ setHiddenCount(0);
92
+ }
93
+ }, [selected]);
43
94
  var handleSelect = function (item) {
44
95
  var newSelected;
45
96
  if (multiple) {
46
- newSelected = (Array.isArray(selected)
47
- ? selected.includes(item.value)
48
- ? selected.filter(function (i) { return i !== item.value; })
49
- : __spreadArray(__spreadArray([], selected, true), [item.value], false)
50
- : [item.value]);
97
+ var currentSelected = selected;
98
+ if (currentSelected.includes(item.value)) {
99
+ newSelected = currentSelected.filter(function (i) { return i !== item.value; });
100
+ }
101
+ else {
102
+ if (maxItems && currentSelected.length >= maxItems) {
103
+ return;
104
+ }
105
+ newSelected = __spreadArray(__spreadArray([], currentSelected, true), [item.value], false);
106
+ if (maxItems && currentSelected.length + 1 >= maxItems) {
107
+ setIsOpen(false);
108
+ }
109
+ }
51
110
  }
52
111
  else {
53
112
  newSelected = item.value;
@@ -134,15 +193,23 @@ function Select(_a, ref) {
134
193
  : "", " ").concat(!multiple && item.value === selectedItem ? styles.highlighted : "", " ").concat(!multiple ? styles.singleSelect : ""), onClick: function () { return handleSelect(item); } },
135
194
  multiple && React.createElement("span", { className: styles.selectItemIcon }),
136
195
  React.createElement("span", { className: styles.selectItemText }, item.label))); }))); };
196
+ var renderTags = function (selectedValues) {
197
+ if (!selectedValues.length)
198
+ return null;
199
+ return (React.createElement("div", { ref: tagContainerRef, className: styles.tagContainer },
200
+ visibleTags.map(function (val) {
201
+ var _a;
202
+ return (React.createElement("span", { key: val, className: styles.tag }, (_a = items.find(function (item) { return item.value === val; })) === null || _a === void 0 ? void 0 : _a.label));
203
+ }),
204
+ hiddenCount > 0 && (React.createElement("span", { className: "".concat(styles.hiddenTagCount, " hiddenTagCount") }, "+ ".concat(hiddenCount, " autre").concat(hiddenCount > 1 ? "s" : "")))));
205
+ };
137
206
  useImperativeHandle(ref, function () { return ({
138
207
  validate: function () { return validateSelect(selected); },
139
208
  }); });
140
209
  return (React.createElement("div", { ref: selectRef, className: "".concat(styles.selectContainer, " ").concat(isOpen ? styles.selectPressed : ""), style: { width: "".concat(width, "%") } },
141
- React.createElement("button", { type: "button", className: "".concat(styles.select, " ").concat(isOpen ? styles.selectPressed : styles.selectDefault), onClick: toggleOpen, style: { width: "100%" } },
210
+ React.createElement("button", { type: "button", className: "".concat(styles.select, " ").concat(isOpen ? styles.selectPressed : styles.selectDefault, " ").concat(multiple ? styles.selectMultiple : styles.selectSingle), onClick: toggleOpen, style: { width: "100%" } },
142
211
  React.createElement("span", { className: styles.selectText }, Array.isArray(selected) && selected.length > 0
143
- ? selected
144
- .map(function (val) { var _a; return (_a = items.find(function (item) { return item.value === val; })) === null || _a === void 0 ? void 0 : _a.label; })
145
- .join(", ")
212
+ ? renderTags(selected)
146
213
  : !Array.isArray(selected) && selected
147
214
  ? (_b = items.find(function (item) { return item.value === selected; })) === null || _b === void 0 ? void 0 : _b.label
148
215
  : placeholder),
@@ -1,12 +1,12 @@
1
1
  .selectContainer {
2
2
  position: relative;
3
+ min-height: 40px;
3
4
  }
4
5
 
5
6
  .select {
6
7
  display: flex;
7
- padding: 8px 16px;
8
8
  justify-content: space-between;
9
- align-items: center;
9
+ align-items: flex-start;
10
10
  gap: 11px;
11
11
  border-radius: 8px;
12
12
  background: var(--secondary-light-grey, #f4f7fb);
@@ -31,6 +31,10 @@
31
31
  white-space: nowrap;
32
32
  overflow: hidden;
33
33
  text-overflow: ellipsis;
34
+ display: flex;
35
+ flex: 1;
36
+ min-height: 24px;
37
+ padding: 2px 0;
34
38
  }
35
39
 
36
40
  .selectIcon {
@@ -40,7 +44,7 @@
40
44
  display: flex;
41
45
  align-items: center;
42
46
  justify-content: center;
43
- padding-top: 4px;
47
+ padding-top: 2px;
44
48
  }
45
49
 
46
50
  .selectList {
@@ -113,3 +117,44 @@
113
117
  .selectItem.highlighted {
114
118
  background-color: var(--venom-grey-dark, #d1dce8);
115
119
  }
120
+
121
+ .tagContainer {
122
+ display: flex;
123
+ flex-wrap: nowrap;
124
+ gap: 6px;
125
+ align-items: center;
126
+ overflow: hidden;
127
+ width: 100%;
128
+ }
129
+
130
+ .tag {
131
+ background: var(--grey-venom, #e6edf5);
132
+ border-radius: 4px;
133
+ padding: 8px 8px;
134
+ font-size: 12px;
135
+ font-weight: 600;
136
+ color: var(--Primary-Mid-black, var(--primary-black, #171e25));
137
+ white-space: nowrap;
138
+ flex-shrink: 0;
139
+ }
140
+
141
+ .hiddenTagCount {
142
+ font-size: 12px;
143
+ font-weight: 600;
144
+ color: var(--Primary-Mid-black, var(--primary-black, #171e25));
145
+ white-space: nowrap;
146
+ flex-shrink: 0;
147
+ padding: 2px 0;
148
+ }
149
+
150
+ .select:hover .tag {
151
+ background-color: var(--venom-grey-dark, #d1dce8);
152
+ }
153
+
154
+ .selectMultiple {
155
+ padding: 6px 8px;
156
+ }
157
+
158
+ .selectSingle {
159
+ padding: 8px 16px;
160
+ }
@@ -39,19 +39,28 @@ declare namespace _default {
39
39
  }
40
40
  export { control_4 as control };
41
41
  }
42
+ namespace maxItems {
43
+ export namespace control_5 {
44
+ let type_5: string;
45
+ export { type_5 as type };
46
+ export let min: number;
47
+ }
48
+ export { control_5 as control };
49
+ }
42
50
  namespace onChange {
43
51
  namespace table {
44
52
  let disable: boolean;
45
53
  }
46
54
  }
47
55
  namespace width {
48
- export namespace control_5 {
49
- let type_5: string;
50
- export { type_5 as type };
51
- export let min: number;
56
+ export namespace control_6 {
57
+ let type_6: string;
58
+ export { type_6 as type };
59
+ let min_1: number;
60
+ export { min_1 as min };
52
61
  export let max: number;
53
62
  }
54
- export { control_5 as control };
63
+ export { control_6 as control };
55
64
  }
56
65
  }
57
66
  export namespace parameters {
@@ -45,6 +45,12 @@ export default {
45
45
  type: "text",
46
46
  },
47
47
  },
48
+ maxItems: {
49
+ control: {
50
+ type: "number",
51
+ min: 1,
52
+ },
53
+ },
48
54
  onChange: {
49
55
  table: {
50
56
  disable: true,
@@ -134,6 +140,7 @@ Multiple.args = {
134
140
  placeholder: "Select...",
135
141
  multiple: true,
136
142
  isRequired: false,
143
+ maxItems: 3,
137
144
  };
138
145
  export var Required = Template.bind({});
139
146
  Required.args = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "2.4.8",
3
+ "version": "2.4.9",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",