@pequity/squirrel 7.1.2 → 7.1.4
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/dist/cjs/chunks/p-dropdown-select.js +75 -18
- package/dist/es/chunks/p-dropdown-select.js +76 -19
- package/dist/squirrel/components/p-dropdown-select/p-dropdown-select.vue.d.ts +15 -0
- package/dist/squirrel.css +2 -2
- package/package.json +1 -1
- package/squirrel/assets/filter-icon-active-hover.svg +3 -6
- package/squirrel/assets/filter-icon-active.svg +3 -5
- package/squirrel/components/p-dropdown-select/p-dropdown-select.spec.js +107 -0
- package/squirrel/components/p-dropdown-select/p-dropdown-select.stories.js +21 -0
- package/squirrel/components/p-dropdown-select/p-dropdown-select.vue +52 -7
|
@@ -12,16 +12,28 @@ const lodashEs = require("lodash-es");
|
|
|
12
12
|
const _imports_0 = "data:image/svg+xml,%3csvg%20width='18'%20height='12'%20viewBox='0%200%2018%2012'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M16.1383%200.166992L6.30411%209.83366L1.69828%205.27533L0.526611%206.46033L5.71578%2011.597C5.87174%2011.7509%206.08205%2011.8372%206.3012%2011.8372C6.52034%2011.8372%206.73065%2011.7509%206.88661%2011.597L17.3033%201.35366L16.1383%200.166992Z'%20fill='%231A123B'%20/%3e%3c/svg%3e";
|
|
13
13
|
const _hoisted_1 = ["data-has-error"];
|
|
14
14
|
const _hoisted_2 = { class: "truncate text-left text-p-gray-40" };
|
|
15
|
-
const _hoisted_3 = {
|
|
15
|
+
const _hoisted_3 = {
|
|
16
|
+
key: 0,
|
|
17
|
+
class: "flex flex-wrap gap-1.5 pr-8"
|
|
18
|
+
};
|
|
16
19
|
const _hoisted_4 = {
|
|
20
|
+
class: "max-w-[200px] truncate",
|
|
21
|
+
"data-test": "pill-text"
|
|
22
|
+
};
|
|
23
|
+
const _hoisted_5 = ["onClick"];
|
|
24
|
+
const _hoisted_6 = {
|
|
25
|
+
key: 1,
|
|
26
|
+
class: "truncate text-left"
|
|
27
|
+
};
|
|
28
|
+
const _hoisted_7 = {
|
|
17
29
|
key: 0,
|
|
18
30
|
class: "mt-3 px-3"
|
|
19
31
|
};
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
32
|
+
const _hoisted_8 = { class: "text-p-purple-60" };
|
|
33
|
+
const _hoisted_9 = { class: "flex flex-row" };
|
|
34
|
+
const _hoisted_10 = ["onClick"];
|
|
35
|
+
const _hoisted_11 = ["title"];
|
|
36
|
+
const _hoisted_12 = {
|
|
25
37
|
key: 0,
|
|
26
38
|
class: "ml-auto fill-p-purple-60 pl-2",
|
|
27
39
|
src: _imports_0
|
|
@@ -167,6 +179,13 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
167
179
|
creatable: {
|
|
168
180
|
type: Boolean,
|
|
169
181
|
default: false
|
|
182
|
+
},
|
|
183
|
+
/**
|
|
184
|
+
* Shows selected items as pills in the button when multiple selection is enabled
|
|
185
|
+
*/
|
|
186
|
+
pills: {
|
|
187
|
+
type: Boolean,
|
|
188
|
+
default: false
|
|
170
189
|
}
|
|
171
190
|
},
|
|
172
191
|
emits: ["update:modelValue", "select", "create"],
|
|
@@ -184,9 +203,19 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
184
203
|
enableArrowNavigation: false
|
|
185
204
|
};
|
|
186
205
|
const CLEAR_BUTTON_SPACING = {
|
|
187
|
-
sm: "right-8",
|
|
188
|
-
md: "right-9",
|
|
189
|
-
lg: "right-10"
|
|
206
|
+
sm: "right-8 text-sm top-[0.3rem]",
|
|
207
|
+
md: "right-9 text-base top-[0.5rem]",
|
|
208
|
+
lg: "right-10 text-lg top-[0.7rem]"
|
|
209
|
+
};
|
|
210
|
+
const PILL_SIZE = {
|
|
211
|
+
sm: "text-sm",
|
|
212
|
+
md: "text-base",
|
|
213
|
+
lg: "text-lg"
|
|
214
|
+
};
|
|
215
|
+
const PILL_SELECT_SPACING = {
|
|
216
|
+
sm: "min-h-[2rem] py-1 bg-[position:right_1rem_top_0.7rem]",
|
|
217
|
+
md: "min-h-[2.5rem] py-2 bg-[position:right_1rem_top_0.9rem]",
|
|
218
|
+
lg: "min-h-[3rem] py-2 bg-[position:right_1rem_top_1.1rem]"
|
|
190
219
|
};
|
|
191
220
|
const width = vue.ref("auto");
|
|
192
221
|
const listItemStyle = vue.ref({ paddingTop: 0, paddingBottom: 0 });
|
|
@@ -304,15 +333,15 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
304
333
|
"p-select-list": "",
|
|
305
334
|
role: "listbox"
|
|
306
335
|
}), [
|
|
307
|
-
__props.multiple || __props.searchable ? (vue.openBlock(), vue.createElementBlock("div",
|
|
336
|
+
__props.multiple || __props.searchable ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_7, [
|
|
308
337
|
__props.multiple ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
309
338
|
key: 0,
|
|
310
339
|
ref_key: "actionsContainer",
|
|
311
340
|
ref: actionsContainer,
|
|
312
341
|
class: "flex flex-row justify-between text-xs font-semibold text-primary"
|
|
313
342
|
}, [
|
|
314
|
-
vue.createElementVNode("p",
|
|
315
|
-
vue.createElementVNode("div",
|
|
343
|
+
vue.createElementVNode("p", _hoisted_8, vue.toDisplayString(vue.unref(computedItems).length) + " items", 1),
|
|
344
|
+
vue.createElementVNode("div", _hoisted_9, [
|
|
316
345
|
vue.unref(computedItems).length === vue.unref(internalItems).length ? (vue.openBlock(), vue.createElementBlock("a", {
|
|
317
346
|
key: 0,
|
|
318
347
|
class: vue.normalizeClass([
|
|
@@ -399,11 +428,11 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
399
428
|
class: vue.normalizeClass({ "bg-p-blue-20": index === 1 })
|
|
400
429
|
}, vue.toDisplayString(str), 3);
|
|
401
430
|
}), 128))
|
|
402
|
-
], 8,
|
|
431
|
+
], 8, _hoisted_11)
|
|
403
432
|
]),
|
|
404
|
-
vue.unref(isSelected)(vue.unref(getValue)(row.index)) ? (vue.openBlock(), vue.createElementBlock("img",
|
|
433
|
+
vue.unref(isSelected)(vue.unref(getValue)(row.index)) ? (vue.openBlock(), vue.createElementBlock("img", _hoisted_12)) : vue.createCommentVNode("", true)
|
|
405
434
|
], 2)
|
|
406
|
-
], 14,
|
|
435
|
+
], 14, _hoisted_10)), [
|
|
407
436
|
[_directive_close_popper, !__props.multiple]
|
|
408
437
|
])
|
|
409
438
|
], 4);
|
|
@@ -434,7 +463,13 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
434
463
|
vue.createElementVNode("button", vue.mergeProps(attrs.value, {
|
|
435
464
|
ref: "button",
|
|
436
465
|
type: "button",
|
|
437
|
-
class: [
|
|
466
|
+
class: [
|
|
467
|
+
"w-full",
|
|
468
|
+
vue.unref(selectClasses),
|
|
469
|
+
dropdownShow.value ? "border-primary" : "",
|
|
470
|
+
{ "box-border h-auto items-start": __props.multiple && __props.pills && vue.unref(selectedItems).length > 0 },
|
|
471
|
+
PILL_SELECT_SPACING[__props.size]
|
|
472
|
+
],
|
|
438
473
|
role: "button",
|
|
439
474
|
"aria-haspopup": "listbox",
|
|
440
475
|
onClick: _cache[1] || (_cache[1] = ($event) => dropdownShow.value = !dropdownShow.value)
|
|
@@ -445,11 +480,33 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
445
480
|
key: 1,
|
|
446
481
|
item: __props.multiple ? vue.unref(selectedItems) : vue.unref(selectedItems)[0]
|
|
447
482
|
}, () => [
|
|
448
|
-
|
|
483
|
+
__props.multiple && __props.pills ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
|
|
484
|
+
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(selectedItems), (item) => {
|
|
485
|
+
return vue.openBlock(), vue.createElementBlock("div", {
|
|
486
|
+
key: String(item[__props.itemValue]),
|
|
487
|
+
class: vue.normalizeClass(["flex items-center gap-1 rounded bg-p-gray-10 px-2 text-p-gray-50", [PILL_SIZE[__props.size]]]),
|
|
488
|
+
"data-test": "selected-pill"
|
|
489
|
+
}, [
|
|
490
|
+
vue.createElementVNode("span", _hoisted_4, vue.toDisplayString(item[__props.itemText]), 1),
|
|
491
|
+
vue.createElementVNode("button", {
|
|
492
|
+
type: "button",
|
|
493
|
+
class: "flex items-center justify-center text-p-gray-40 hover:text-p-gray-60",
|
|
494
|
+
"aria-label": "Remove item",
|
|
495
|
+
"data-test": "pill-remove",
|
|
496
|
+
onClick: vue.withModifiers(($event) => vue.unref(select)($event, item[__props.itemValue]), ["stop"])
|
|
497
|
+
}, [
|
|
498
|
+
vue.createVNode(pIcon_vue_vue_type_script_setup_true_lang._sfc_main, {
|
|
499
|
+
icon: "fe:close",
|
|
500
|
+
class: "h-3.5 w-3.5"
|
|
501
|
+
})
|
|
502
|
+
], 8, _hoisted_5)
|
|
503
|
+
], 2);
|
|
504
|
+
}), 128))
|
|
505
|
+
])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, vue.toDisplayString(__props.multiple ? vue.unref(selectedItems).length === selectableItemsCount.value ? "All options selected" : `${vue.unref(selectedItems).length} option${vue.unref(selectedItems).length > 1 ? "s" : ""} selected` : vue.unref(selectedItems)[0][__props.itemText]), 1))
|
|
449
506
|
]),
|
|
450
507
|
__props.clearable && vue.unref(selectedItems).length ? (vue.openBlock(), vue.createElementBlock("button", {
|
|
451
508
|
key: 2,
|
|
452
|
-
class: vue.normalizeClass(["absolute
|
|
509
|
+
class: vue.normalizeClass(["absolute right-9 flex h-6 items-center justify-center text-base text-p-gray-40 hover:text-p-gray-60", [CLEAR_BUTTON_SPACING[__props.size]]]),
|
|
453
510
|
"aria-label": "Clear selection",
|
|
454
511
|
onClick: _cache[0] || (_cache[0] = vue.withModifiers(
|
|
455
512
|
//@ts-ignore
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, ref, useAttrs, computed, watch, onMounted, onUnmounted, resolveDirective, createElementBlock, openBlock, normalizeStyle, normalizeClass, unref, createCommentVNode, createVNode, withDirectives, toDisplayString, mergeProps, withCtx, createElementVNode, renderSlot,
|
|
1
|
+
import { defineComponent, ref, useAttrs, computed, watch, onMounted, onUnmounted, resolveDirective, createElementBlock, openBlock, normalizeStyle, normalizeClass, unref, createCommentVNode, createVNode, withDirectives, toDisplayString, mergeProps, withCtx, createElementVNode, renderSlot, Fragment, renderList, withModifiers, isRef, createTextVNode, vShow } from "vue";
|
|
2
2
|
import PDropdown from "../p-dropdown.js";
|
|
3
3
|
import { _ as _sfc_main$1 } from "./p-icon.js";
|
|
4
4
|
import PInputSearch from "../p-input-search.js";
|
|
@@ -11,16 +11,28 @@ import { omit } from "lodash-es";
|
|
|
11
11
|
const _imports_0 = "data:image/svg+xml,%3csvg%20width='18'%20height='12'%20viewBox='0%200%2018%2012'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M16.1383%200.166992L6.30411%209.83366L1.69828%205.27533L0.526611%206.46033L5.71578%2011.597C5.87174%2011.7509%206.08205%2011.8372%206.3012%2011.8372C6.52034%2011.8372%206.73065%2011.7509%206.88661%2011.597L17.3033%201.35366L16.1383%200.166992Z'%20fill='%231A123B'%20/%3e%3c/svg%3e";
|
|
12
12
|
const _hoisted_1 = ["data-has-error"];
|
|
13
13
|
const _hoisted_2 = { class: "truncate text-left text-p-gray-40" };
|
|
14
|
-
const _hoisted_3 = {
|
|
14
|
+
const _hoisted_3 = {
|
|
15
|
+
key: 0,
|
|
16
|
+
class: "flex flex-wrap gap-1.5 pr-8"
|
|
17
|
+
};
|
|
15
18
|
const _hoisted_4 = {
|
|
19
|
+
class: "max-w-[200px] truncate",
|
|
20
|
+
"data-test": "pill-text"
|
|
21
|
+
};
|
|
22
|
+
const _hoisted_5 = ["onClick"];
|
|
23
|
+
const _hoisted_6 = {
|
|
24
|
+
key: 1,
|
|
25
|
+
class: "truncate text-left"
|
|
26
|
+
};
|
|
27
|
+
const _hoisted_7 = {
|
|
16
28
|
key: 0,
|
|
17
29
|
class: "mt-3 px-3"
|
|
18
30
|
};
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
31
|
+
const _hoisted_8 = { class: "text-p-purple-60" };
|
|
32
|
+
const _hoisted_9 = { class: "flex flex-row" };
|
|
33
|
+
const _hoisted_10 = ["onClick"];
|
|
34
|
+
const _hoisted_11 = ["title"];
|
|
35
|
+
const _hoisted_12 = {
|
|
24
36
|
key: 0,
|
|
25
37
|
class: "ml-auto fill-p-purple-60 pl-2",
|
|
26
38
|
src: _imports_0
|
|
@@ -166,6 +178,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
166
178
|
creatable: {
|
|
167
179
|
type: Boolean,
|
|
168
180
|
default: false
|
|
181
|
+
},
|
|
182
|
+
/**
|
|
183
|
+
* Shows selected items as pills in the button when multiple selection is enabled
|
|
184
|
+
*/
|
|
185
|
+
pills: {
|
|
186
|
+
type: Boolean,
|
|
187
|
+
default: false
|
|
169
188
|
}
|
|
170
189
|
},
|
|
171
190
|
emits: ["update:modelValue", "select", "create"],
|
|
@@ -183,9 +202,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
183
202
|
enableArrowNavigation: false
|
|
184
203
|
};
|
|
185
204
|
const CLEAR_BUTTON_SPACING = {
|
|
186
|
-
sm: "right-8",
|
|
187
|
-
md: "right-9",
|
|
188
|
-
lg: "right-10"
|
|
205
|
+
sm: "right-8 text-sm top-[0.3rem]",
|
|
206
|
+
md: "right-9 text-base top-[0.5rem]",
|
|
207
|
+
lg: "right-10 text-lg top-[0.7rem]"
|
|
208
|
+
};
|
|
209
|
+
const PILL_SIZE = {
|
|
210
|
+
sm: "text-sm",
|
|
211
|
+
md: "text-base",
|
|
212
|
+
lg: "text-lg"
|
|
213
|
+
};
|
|
214
|
+
const PILL_SELECT_SPACING = {
|
|
215
|
+
sm: "min-h-[2rem] py-1 bg-[position:right_1rem_top_0.7rem]",
|
|
216
|
+
md: "min-h-[2.5rem] py-2 bg-[position:right_1rem_top_0.9rem]",
|
|
217
|
+
lg: "min-h-[3rem] py-2 bg-[position:right_1rem_top_1.1rem]"
|
|
189
218
|
};
|
|
190
219
|
const width = ref("auto");
|
|
191
220
|
const listItemStyle = ref({ paddingTop: 0, paddingBottom: 0 });
|
|
@@ -303,15 +332,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
303
332
|
"p-select-list": "",
|
|
304
333
|
role: "listbox"
|
|
305
334
|
}), [
|
|
306
|
-
__props.multiple || __props.searchable ? (openBlock(), createElementBlock("div",
|
|
335
|
+
__props.multiple || __props.searchable ? (openBlock(), createElementBlock("div", _hoisted_7, [
|
|
307
336
|
__props.multiple ? (openBlock(), createElementBlock("div", {
|
|
308
337
|
key: 0,
|
|
309
338
|
ref_key: "actionsContainer",
|
|
310
339
|
ref: actionsContainer,
|
|
311
340
|
class: "flex flex-row justify-between text-xs font-semibold text-primary"
|
|
312
341
|
}, [
|
|
313
|
-
createElementVNode("p",
|
|
314
|
-
createElementVNode("div",
|
|
342
|
+
createElementVNode("p", _hoisted_8, toDisplayString(unref(computedItems).length) + " items", 1),
|
|
343
|
+
createElementVNode("div", _hoisted_9, [
|
|
315
344
|
unref(computedItems).length === unref(internalItems).length ? (openBlock(), createElementBlock("a", {
|
|
316
345
|
key: 0,
|
|
317
346
|
class: normalizeClass([
|
|
@@ -398,11 +427,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
398
427
|
class: normalizeClass({ "bg-p-blue-20": index === 1 })
|
|
399
428
|
}, toDisplayString(str), 3);
|
|
400
429
|
}), 128))
|
|
401
|
-
], 8,
|
|
430
|
+
], 8, _hoisted_11)
|
|
402
431
|
]),
|
|
403
|
-
unref(isSelected)(unref(getValue)(row.index)) ? (openBlock(), createElementBlock("img",
|
|
432
|
+
unref(isSelected)(unref(getValue)(row.index)) ? (openBlock(), createElementBlock("img", _hoisted_12)) : createCommentVNode("", true)
|
|
404
433
|
], 2)
|
|
405
|
-
], 14,
|
|
434
|
+
], 14, _hoisted_10)), [
|
|
406
435
|
[_directive_close_popper, !__props.multiple]
|
|
407
436
|
])
|
|
408
437
|
], 4);
|
|
@@ -433,7 +462,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
433
462
|
createElementVNode("button", mergeProps(attrs.value, {
|
|
434
463
|
ref: "button",
|
|
435
464
|
type: "button",
|
|
436
|
-
class: [
|
|
465
|
+
class: [
|
|
466
|
+
"w-full",
|
|
467
|
+
unref(selectClasses),
|
|
468
|
+
dropdownShow.value ? "border-primary" : "",
|
|
469
|
+
{ "box-border h-auto items-start": __props.multiple && __props.pills && unref(selectedItems).length > 0 },
|
|
470
|
+
PILL_SELECT_SPACING[__props.size]
|
|
471
|
+
],
|
|
437
472
|
role: "button",
|
|
438
473
|
"aria-haspopup": "listbox",
|
|
439
474
|
onClick: _cache[1] || (_cache[1] = ($event) => dropdownShow.value = !dropdownShow.value)
|
|
@@ -444,11 +479,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
444
479
|
key: 1,
|
|
445
480
|
item: __props.multiple ? unref(selectedItems) : unref(selectedItems)[0]
|
|
446
481
|
}, () => [
|
|
447
|
-
|
|
482
|
+
__props.multiple && __props.pills ? (openBlock(), createElementBlock("div", _hoisted_3, [
|
|
483
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(selectedItems), (item) => {
|
|
484
|
+
return openBlock(), createElementBlock("div", {
|
|
485
|
+
key: String(item[__props.itemValue]),
|
|
486
|
+
class: normalizeClass(["flex items-center gap-1 rounded bg-p-gray-10 px-2 text-p-gray-50", [PILL_SIZE[__props.size]]]),
|
|
487
|
+
"data-test": "selected-pill"
|
|
488
|
+
}, [
|
|
489
|
+
createElementVNode("span", _hoisted_4, toDisplayString(item[__props.itemText]), 1),
|
|
490
|
+
createElementVNode("button", {
|
|
491
|
+
type: "button",
|
|
492
|
+
class: "flex items-center justify-center text-p-gray-40 hover:text-p-gray-60",
|
|
493
|
+
"aria-label": "Remove item",
|
|
494
|
+
"data-test": "pill-remove",
|
|
495
|
+
onClick: withModifiers(($event) => unref(select)($event, item[__props.itemValue]), ["stop"])
|
|
496
|
+
}, [
|
|
497
|
+
createVNode(_sfc_main$1, {
|
|
498
|
+
icon: "fe:close",
|
|
499
|
+
class: "h-3.5 w-3.5"
|
|
500
|
+
})
|
|
501
|
+
], 8, _hoisted_5)
|
|
502
|
+
], 2);
|
|
503
|
+
}), 128))
|
|
504
|
+
])) : (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString(__props.multiple ? unref(selectedItems).length === selectableItemsCount.value ? "All options selected" : `${unref(selectedItems).length} option${unref(selectedItems).length > 1 ? "s" : ""} selected` : unref(selectedItems)[0][__props.itemText]), 1))
|
|
448
505
|
]),
|
|
449
506
|
__props.clearable && unref(selectedItems).length ? (openBlock(), createElementBlock("button", {
|
|
450
507
|
key: 2,
|
|
451
|
-
class: normalizeClass(["absolute
|
|
508
|
+
class: normalizeClass(["absolute right-9 flex h-6 items-center justify-center text-base text-p-gray-40 hover:text-p-gray-60", [CLEAR_BUTTON_SPACING[__props.size]]]),
|
|
452
509
|
"aria-label": "Clear selection",
|
|
453
510
|
onClick: _cache[0] || (_cache[0] = withModifiers(
|
|
454
511
|
//@ts-ignore
|
|
@@ -148,6 +148,13 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
|
|
|
148
148
|
type: BooleanConstructor;
|
|
149
149
|
default: boolean;
|
|
150
150
|
};
|
|
151
|
+
/**
|
|
152
|
+
* Shows selected items as pills in the button when multiple selection is enabled
|
|
153
|
+
*/
|
|
154
|
+
pills: {
|
|
155
|
+
type: BooleanConstructor;
|
|
156
|
+
default: boolean;
|
|
157
|
+
};
|
|
151
158
|
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
152
159
|
select: (...args: any[]) => void;
|
|
153
160
|
"update:modelValue": (...args: any[]) => void;
|
|
@@ -286,6 +293,13 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
|
|
|
286
293
|
type: BooleanConstructor;
|
|
287
294
|
default: boolean;
|
|
288
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* Shows selected items as pills in the button when multiple selection is enabled
|
|
298
|
+
*/
|
|
299
|
+
pills: {
|
|
300
|
+
type: BooleanConstructor;
|
|
301
|
+
default: boolean;
|
|
302
|
+
};
|
|
289
303
|
}>> & Readonly<{
|
|
290
304
|
onSelect?: ((...args: any[]) => any) | undefined;
|
|
291
305
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
@@ -314,6 +328,7 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
|
|
|
314
328
|
selectedTopShown: boolean;
|
|
315
329
|
disabledBy: string;
|
|
316
330
|
creatable: boolean;
|
|
331
|
+
pills: boolean;
|
|
317
332
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
318
333
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
319
334
|
export default _default;
|
package/dist/squirrel.css
CHANGED
|
@@ -371,10 +371,10 @@ to {
|
|
|
371
371
|
background: url("data:image/svg+xml,%3csvg%20width='20'%20height='20'%20viewBox='0%200%2020%2020'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='20'%20height='20'%20rx='4'%20fill='black'%20fill-opacity='0.05'/%3e%3cpath%20d='M15.5%206.73001H4.5C4.36739%206.73001%204.24021%206.67733%204.14645%206.58356C4.05268%206.4898%204%206.36262%204%206.23001C4%206.0974%204.05268%205.97023%204.14645%205.87646C4.24021%205.78269%204.36739%205.73001%204.5%205.73001H15.5C15.6326%205.73001%2015.7598%205.78269%2015.8536%205.87646C15.9473%205.97023%2016%206.0974%2016%206.23001C16%206.36262%2015.9473%206.4898%2015.8536%206.58356C15.7598%206.67733%2015.6326%206.73001%2015.5%206.73001Z'%20fill='%23424E6E'/%3e%3cpath%20d='M14.33%209.24503H5.67C5.53739%209.24503%205.41021%209.19235%205.31644%209.09858C5.22268%209.00481%205.17%208.87763%205.17%208.74503C5.17%208.61242%205.22268%208.48524%205.31644%208.39147C5.41021%208.2977%205.53739%208.24503%205.67%208.24503H14.33C14.4626%208.24503%2014.5898%208.2977%2014.6836%208.39147C14.7773%208.48524%2014.83%208.61242%2014.83%208.74503C14.83%208.87763%2014.7773%209.00481%2014.6836%209.09858C14.5898%209.19235%2014.4626%209.24503%2014.33%209.24503Z'%20fill='%23424E6E'/%3e%3cpath%20d='M11.605%2014.27H8.395C8.2624%2014.27%208.13522%2014.2173%208.04145%2014.1236C7.94768%2014.0298%207.895%2013.9026%207.895%2013.77C7.895%2013.6374%207.94768%2013.5102%208.04145%2013.4165C8.13522%2013.3227%208.2624%2013.27%208.395%2013.27H11.605C11.7376%2013.27%2011.8648%2013.3227%2011.9586%2013.4165C12.0523%2013.5102%2012.105%2013.6374%2012.105%2013.77C12.105%2013.9026%2012.0523%2014.0298%2011.9586%2014.1236C11.8648%2014.2173%2011.7376%2014.27%2011.605%2014.27Z'%20fill='%23424E6E'/%3e%3cpath%20d='M13.155%2011.755H6.845C6.71239%2011.755%206.58522%2011.7023%206.49145%2011.6086C6.39768%2011.5148%206.345%2011.3876%206.345%2011.255C6.345%2011.1224%206.39768%2010.9952%206.49145%2010.9015C6.58522%2010.8077%206.71239%2010.755%206.845%2010.755H13.155C13.2876%2010.755%2013.4148%2010.8077%2013.5086%2010.9015C13.6023%2010.9952%2013.655%2011.1224%2013.655%2011.255C13.655%2011.3876%2013.6023%2011.5148%2013.5086%2011.6086C13.4148%2011.7023%2013.2876%2011.755%2013.155%2011.755Z'%20fill='%23424E6E'/%3e%3c/svg%3e") no-repeat;
|
|
372
372
|
}
|
|
373
373
|
.filter.active[data-v-84864117] {
|
|
374
|
-
background: url("data:image/svg+xml,%3csvg%20width='20'%20height='20'%20viewBox='0%200%
|
|
374
|
+
background: url("data:image/svg+xml,%3csvg%20width='20'%20height='20'%20viewBox='0%200%2024%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M10%2014L4%205V3h16v2l-6%209v6l-4%202z'%20fill='%230F45AF'%20/%3e%3c/svg%3e") no-repeat;
|
|
375
375
|
}
|
|
376
376
|
.filter.active[data-v-84864117]:hover {
|
|
377
|
-
background: url("data:image/svg+xml,%3csvg%20width='20'%20height='20'%20viewBox='0%200%
|
|
377
|
+
background: url("data:image/svg+xml,%3csvg%20width='20'%20height='20'%20viewBox='0%200%2024%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='24'%20height='24'%20rx='4'%20fill='black'%20fill-opacity='0.05'/%3e%3cpath%20d='M10%2014L4%205V3h16v2l-6%209v6l-4%202z'%20fill='%230F45AF'%20/%3e%3c/svg%3e") no-repeat;
|
|
378
378
|
}.td-shadow-right[data-v-c9978e26] {
|
|
379
379
|
box-shadow: -1px 1px 5px 4px rgba(0, 0, 0, 0.15);
|
|
380
380
|
clip-path: inset(0px -12px 0px 0px);
|
package/package.json
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
<svg width="20" height="20" viewBox="0 0
|
|
2
|
-
<rect width="
|
|
3
|
-
<path
|
|
4
|
-
<path d="M14.33 9.245H5.67C5.53739 9.245 5.41021 9.19232 5.31644 9.09855C5.22268 9.00478 5.17 8.8776 5.17 8.745C5.17 8.61239 5.22268 8.48521 5.31644 8.39144C5.41021 8.29767 5.53739 8.245 5.67 8.245H14.33C14.4626 8.245 14.5898 8.29767 14.6836 8.39144C14.7773 8.48521 14.83 8.61239 14.83 8.745C14.83 8.8776 14.7773 9.00478 14.6836 9.09855C14.5898 9.19232 14.4626 9.245 14.33 9.245Z" fill="#0F45AF"/>
|
|
5
|
-
<path d="M11.605 14.27H8.395C8.2624 14.27 8.13522 14.2173 8.04145 14.1235C7.94768 14.0297 7.895 13.9026 7.895 13.77C7.895 13.6374 7.94768 13.5102 8.04145 13.4164C8.13522 13.3226 8.2624 13.27 8.395 13.27H11.605C11.7376 13.27 11.8648 13.3226 11.9586 13.4164C12.0523 13.5102 12.105 13.6374 12.105 13.77C12.105 13.9026 12.0523 14.0297 11.9586 14.1235C11.8648 14.2173 11.7376 14.27 11.605 14.27Z" fill="#0F45AF"/>
|
|
6
|
-
<path d="M13.155 11.755H6.845C6.71239 11.755 6.58522 11.7023 6.49145 11.6086C6.39768 11.5148 6.345 11.3876 6.345 11.255C6.345 11.1224 6.39768 10.9952 6.49145 10.9015C6.58522 10.8077 6.71239 10.755 6.845 10.755H13.155C13.2876 10.755 13.4148 10.8077 13.5086 10.9015C13.6023 10.9952 13.655 11.1224 13.655 11.255C13.655 11.3876 13.6023 11.5148 13.5086 11.6086C13.4148 11.7023 13.2876 11.755 13.155 11.755Z" fill="#0F45AF"/>
|
|
1
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="24" height="24" rx="4" fill="black" fill-opacity="0.05"/>
|
|
3
|
+
<path d="M10 14L4 5V3h16v2l-6 9v6l-4 2z" fill="#0F45AF" />
|
|
7
4
|
</svg>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
<svg width="20" height="20" viewBox="0 0
|
|
2
|
-
<path
|
|
3
|
-
<path d="M14.33 9.245H5.67C5.53739 9.245 5.41021 9.19232 5.31644 9.09855C5.22268 9.00478 5.17 8.8776 5.17 8.745C5.17 8.61239 5.22268 8.48521 5.31644 8.39144C5.41021 8.29767 5.53739 8.245 5.67 8.245H14.33C14.4626 8.245 14.5898 8.29767 14.6836 8.39144C14.7773 8.48521 14.83 8.61239 14.83 8.745C14.83 8.8776 14.7773 9.00478 14.6836 9.09855C14.5898 9.19232 14.4626 9.245 14.33 9.245Z" fill="#0F45AF"/>
|
|
4
|
-
<path d="M11.605 14.27H8.395C8.2624 14.27 8.13522 14.2173 8.04145 14.1235C7.94768 14.0297 7.895 13.9026 7.895 13.77C7.895 13.6374 7.94768 13.5102 8.04145 13.4164C8.13522 13.3226 8.2624 13.27 8.395 13.27H11.605C11.7376 13.27 11.8648 13.3226 11.9586 13.4164C12.0523 13.5102 12.105 13.6374 12.105 13.77C12.105 13.9026 12.0523 14.0297 11.9586 14.1235C11.8648 14.2173 11.7376 14.27 11.605 14.27Z" fill="#0F45AF"/>
|
|
5
|
-
<path d="M13.155 11.755H6.845C6.71239 11.755 6.58522 11.7023 6.49145 11.6086C6.39768 11.5148 6.345 11.3876 6.345 11.255C6.345 11.1224 6.39768 10.9952 6.49145 10.9015C6.58522 10.8077 6.71239 10.755 6.845 10.755H13.155C13.2876 10.755 13.4148 10.8077 13.5086 10.9015C13.6023 10.9952 13.655 11.1224 13.655 11.255C13.655 11.3876 13.6023 11.5148 13.5086 11.6086C13.4148 11.7023 13.2876 11.755 13.155 11.755Z" fill="#0F45AF"/>
|
|
1
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M10 14L4 5V3h16v2l-6 9v6l-4 2z" fill="#0F45AF" />
|
|
6
3
|
</svg>
|
|
4
|
+
|
|
@@ -857,4 +857,111 @@ describe('PDropdownSelect.vue', () => {
|
|
|
857
857
|
cleanup(wrapper);
|
|
858
858
|
});
|
|
859
859
|
});
|
|
860
|
+
|
|
861
|
+
describe('pills functionality', () => {
|
|
862
|
+
it('renders selected items as pills when pills prop is true and multiple is true', async () => {
|
|
863
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
864
|
+
|
|
865
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: true });
|
|
866
|
+
|
|
867
|
+
const button = wrapper.find('button');
|
|
868
|
+
const pillsContainer = button.find('div.flex.flex-wrap.gap-1\\.5');
|
|
869
|
+
expect(pillsContainer.exists()).toBe(true);
|
|
870
|
+
|
|
871
|
+
const pills = wrapper.findAll('[data-test="selected-pill"]');
|
|
872
|
+
expect(pills.length).toBe(2);
|
|
873
|
+
expect(pills[0].find('[data-test="pill-text"]').text()).toBe('d39ad899-709e-4ed1-b48f-3ef160a617b1');
|
|
874
|
+
expect(pills[1].find('[data-test="pill-text"]').text()).toBe('42e1aeff-2147-485d-9265-fd79abc897b5');
|
|
875
|
+
|
|
876
|
+
cleanup(wrapper);
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
it('does not render pills when pills prop is false', async () => {
|
|
880
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
881
|
+
|
|
882
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: false });
|
|
883
|
+
|
|
884
|
+
const button = wrapper.find('button');
|
|
885
|
+
const pills = wrapper.findAll('[data-test="selected-pill"]');
|
|
886
|
+
expect(pills.length).toBe(0);
|
|
887
|
+
expect(button.text()).toBe('2 options selected');
|
|
888
|
+
|
|
889
|
+
cleanup(wrapper);
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
it('does not render pills when multiple is false, regardless of pills prop', async () => {
|
|
893
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
894
|
+
|
|
895
|
+
const wrapper = createWrapper({ selected: 4 }, { multiple: false, pills: true });
|
|
896
|
+
|
|
897
|
+
const button = wrapper.find('button');
|
|
898
|
+
const pills = wrapper.findAll('[data-test="selected-pill"]');
|
|
899
|
+
expect(pills.length).toBe(0);
|
|
900
|
+
expect(button.text()).toBe('d39ad899-709e-4ed1-b48f-3ef160a617b1');
|
|
901
|
+
|
|
902
|
+
cleanup(wrapper);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
it('allows removing individual items by clicking the pill close button', async () => {
|
|
906
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
907
|
+
|
|
908
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: true });
|
|
909
|
+
|
|
910
|
+
const pills = wrapper.findAll('[data-test="selected-pill"]');
|
|
911
|
+
const closeButton = pills[0].find('[data-test="pill-remove"]');
|
|
912
|
+
await closeButton.trigger('click');
|
|
913
|
+
|
|
914
|
+
expect(wrapper.vm.$data.selected).toEqual([5]);
|
|
915
|
+
expect(wrapper.findAll('[data-test="selected-pill"]').length).toBe(1);
|
|
916
|
+
|
|
917
|
+
cleanup(wrapper);
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
it('shows pills with correct layout', async () => {
|
|
921
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
922
|
+
|
|
923
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: true });
|
|
924
|
+
|
|
925
|
+
const button = wrapper.find('button');
|
|
926
|
+
expect(button.classes()).toContain('h-auto');
|
|
927
|
+
expect(button.classes()).toContain('min-h-[2.5rem]');
|
|
928
|
+
expect(button.classes()).toContain('items-start');
|
|
929
|
+
expect(button.classes()).toContain('py-2');
|
|
930
|
+
|
|
931
|
+
const pillsContainer = wrapper.find('div.flex.flex-wrap.gap-1\\.5');
|
|
932
|
+
expect(pillsContainer.exists()).toBe(true);
|
|
933
|
+
|
|
934
|
+
cleanup(wrapper);
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
it('truncates long text in pills', async () => {
|
|
938
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
939
|
+
|
|
940
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: true });
|
|
941
|
+
|
|
942
|
+
const pillText = wrapper.find('[data-test="pill-text"]');
|
|
943
|
+
expect(pillText.classes()).toContain('max-w-[200px]');
|
|
944
|
+
expect(pillText.classes()).toContain('truncate');
|
|
945
|
+
|
|
946
|
+
cleanup(wrapper);
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
it('maintains pills after dropdown interaction', async () => {
|
|
950
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
951
|
+
|
|
952
|
+
const wrapper = createWrapper({ selected: [4, 5] }, { multiple: true, pills: true });
|
|
953
|
+
|
|
954
|
+
const button = wrapper.find('button');
|
|
955
|
+
await button.trigger('click');
|
|
956
|
+
|
|
957
|
+
const item = wrapper.findAll('[p-select-list-option-item]')[6];
|
|
958
|
+
await item.trigger('click');
|
|
959
|
+
|
|
960
|
+
const pills = wrapper.findAll('[data-test="selected-pill"]');
|
|
961
|
+
expect(pills.length).toBe(3);
|
|
962
|
+
expect(wrapper.vm.$data.selected).toEqual([4, 5, 7]);
|
|
963
|
+
|
|
964
|
+
cleanup(wrapper);
|
|
965
|
+
});
|
|
966
|
+
});
|
|
860
967
|
});
|
|
@@ -280,6 +280,27 @@ export const MultipleSearchable = {
|
|
|
280
280
|
},
|
|
281
281
|
};
|
|
282
282
|
|
|
283
|
+
export const MultipleWithPills = {
|
|
284
|
+
render: createRenderFunction({ selectedVal: [33, 34, 36] }),
|
|
285
|
+
parameters: {
|
|
286
|
+
docs: {
|
|
287
|
+
description: {
|
|
288
|
+
story: 'Multiple selection with selected items displayed as pills in the button',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
args: {
|
|
293
|
+
...Default.args,
|
|
294
|
+
label: 'Multiple with pills',
|
|
295
|
+
items: items4,
|
|
296
|
+
multiple: true,
|
|
297
|
+
searchable: true,
|
|
298
|
+
pills: true,
|
|
299
|
+
placeholder: 'Select an item from the list',
|
|
300
|
+
placeholderSearch: 'Search an item...',
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
|
|
283
304
|
export const SelectedOnTop = {
|
|
284
305
|
render: createRenderFunction({ selectedVal: [33, 34, 36] }),
|
|
285
306
|
args: {
|
|
@@ -19,7 +19,13 @@
|
|
|
19
19
|
v-bind="attrs"
|
|
20
20
|
ref="button"
|
|
21
21
|
type="button"
|
|
22
|
-
:class="[
|
|
22
|
+
:class="[
|
|
23
|
+
'w-full',
|
|
24
|
+
selectClasses,
|
|
25
|
+
dropdownShow ? 'border-primary' : '',
|
|
26
|
+
{ 'box-border h-auto items-start': multiple && pills && selectedItems.length > 0 },
|
|
27
|
+
PILL_SELECT_SPACING[size],
|
|
28
|
+
]"
|
|
23
29
|
role="button"
|
|
24
30
|
aria-haspopup="listbox"
|
|
25
31
|
@click="dropdownShow = !dropdownShow"
|
|
@@ -30,7 +36,27 @@
|
|
|
30
36
|
</div>
|
|
31
37
|
</slot>
|
|
32
38
|
<slot v-else name="selected-item" :item="multiple ? selectedItems : selectedItems[0]">
|
|
33
|
-
<div class="
|
|
39
|
+
<div v-if="multiple && pills" class="flex flex-wrap gap-1.5 pr-8">
|
|
40
|
+
<div
|
|
41
|
+
v-for="item in selectedItems"
|
|
42
|
+
:key="String(item[itemValue])"
|
|
43
|
+
class="flex items-center gap-1 rounded bg-p-gray-10 px-2 text-p-gray-50"
|
|
44
|
+
:class="[PILL_SIZE[size]]"
|
|
45
|
+
data-test="selected-pill"
|
|
46
|
+
>
|
|
47
|
+
<span class="max-w-[200px] truncate" data-test="pill-text">{{ item[itemText] }}</span>
|
|
48
|
+
<button
|
|
49
|
+
type="button"
|
|
50
|
+
class="flex items-center justify-center text-p-gray-40 hover:text-p-gray-60"
|
|
51
|
+
aria-label="Remove item"
|
|
52
|
+
data-test="pill-remove"
|
|
53
|
+
@click.stop="select($event, item[itemValue])"
|
|
54
|
+
>
|
|
55
|
+
<PIcon icon="fe:close" class="h-3.5 w-3.5" />
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div v-else class="truncate text-left">
|
|
34
60
|
{{
|
|
35
61
|
multiple
|
|
36
62
|
? selectedItems.length === selectableItemsCount
|
|
@@ -43,8 +69,8 @@
|
|
|
43
69
|
<!-- Clear selection button -->
|
|
44
70
|
<button
|
|
45
71
|
v-if="clearable && selectedItems.length"
|
|
46
|
-
class="absolute
|
|
47
|
-
:class="[
|
|
72
|
+
class="absolute right-9 flex h-6 items-center justify-center text-base text-p-gray-40 hover:text-p-gray-60"
|
|
73
|
+
:class="[CLEAR_BUTTON_SPACING[size]]"
|
|
48
74
|
aria-label="Clear selection"
|
|
49
75
|
@click.stop="clearAll"
|
|
50
76
|
>
|
|
@@ -349,6 +375,13 @@ const props = defineProps({
|
|
|
349
375
|
type: Boolean,
|
|
350
376
|
default: false,
|
|
351
377
|
},
|
|
378
|
+
/**
|
|
379
|
+
* Shows selected items as pills in the button when multiple selection is enabled
|
|
380
|
+
*/
|
|
381
|
+
pills: {
|
|
382
|
+
type: Boolean,
|
|
383
|
+
default: false,
|
|
384
|
+
},
|
|
352
385
|
});
|
|
353
386
|
|
|
354
387
|
// Async helpers
|
|
@@ -366,9 +399,21 @@ const P_DROPDOWN_DEFAULTS = {
|
|
|
366
399
|
};
|
|
367
400
|
|
|
368
401
|
const CLEAR_BUTTON_SPACING = {
|
|
369
|
-
sm: 'right-8',
|
|
370
|
-
md: 'right-9',
|
|
371
|
-
lg: 'right-10',
|
|
402
|
+
sm: 'right-8 text-sm top-[0.3rem]',
|
|
403
|
+
md: 'right-9 text-base top-[0.5rem]',
|
|
404
|
+
lg: 'right-10 text-lg top-[0.7rem]',
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const PILL_SIZE = {
|
|
408
|
+
sm: 'text-sm',
|
|
409
|
+
md: 'text-base',
|
|
410
|
+
lg: 'text-lg',
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
const PILL_SELECT_SPACING = {
|
|
414
|
+
sm: 'min-h-[2rem] py-1 bg-[position:right_1rem_top_0.7rem]',
|
|
415
|
+
md: 'min-h-[2.5rem] py-2 bg-[position:right_1rem_top_0.9rem]',
|
|
416
|
+
lg: 'min-h-[3rem] py-2 bg-[position:right_1rem_top_1.1rem]',
|
|
372
417
|
};
|
|
373
418
|
|
|
374
419
|
const width = ref('auto');
|