@pequity/squirrel 6.0.14 → 6.1.0

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 (45) hide show
  1. package/dist/cjs/chunks/p-action-bar.js +4 -4
  2. package/dist/cjs/chunks/p-btn.js +204 -0
  3. package/dist/cjs/chunks/p-select-btn.js +5 -4
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/p-btn.js +2 -169
  6. package/dist/es/chunks/p-action-bar.js +8 -8
  7. package/dist/es/chunks/p-btn.js +205 -0
  8. package/dist/es/chunks/p-select-btn.js +5 -4
  9. package/dist/es/index.js +62 -62
  10. package/dist/es/p-btn.js +2 -169
  11. package/dist/squirrel/components/p-btn/p-btn.vue.d.ts +106 -46
  12. package/dist/squirrel/components/p-card/p-card.vue.d.ts +27 -14
  13. package/dist/squirrel/components/p-checkbox/p-checkbox.vue.d.ts +43 -12
  14. package/dist/squirrel/components/p-close-btn/p-close-btn.vue.d.ts +1 -1
  15. package/dist/squirrel/components/p-drawer/p-drawer.vue.d.ts +1 -1
  16. package/dist/squirrel/components/p-dropdown-select/p-dropdown-select.vue.d.ts +15 -422
  17. package/dist/squirrel/components/p-file-upload/p-file-upload.vue.d.ts +1 -3
  18. package/dist/squirrel/components/p-info-icon/p-info-icon.vue.d.ts +13 -11
  19. package/dist/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue.d.ts +39 -14
  20. package/dist/squirrel/components/p-input/p-input.vue.d.ts +2 -2
  21. package/dist/squirrel/components/p-input-number/p-input-number.vue.d.ts +2 -2
  22. package/dist/squirrel/components/p-input-search/p-input-search.vue.d.ts +2 -2
  23. package/dist/squirrel/components/p-link/p-link.vue.d.ts +17 -13
  24. package/dist/squirrel/components/p-loading/p-loading.vue.d.ts +1 -3
  25. package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +240 -22
  26. package/dist/squirrel/components/p-pagination-info/p-pagination-info.vue.d.ts +77 -10
  27. package/dist/squirrel/components/p-select/p-select.vue.d.ts +116 -14
  28. package/dist/squirrel/components/p-select-btn/p-select-btn.vue.d.ts +37 -13
  29. package/dist/squirrel/components/p-select-list/p-select-list.vue.d.ts +14 -418
  30. package/dist/squirrel/components/p-table/p-table.vue.d.ts +61 -19
  31. package/dist/squirrel/components/p-table-header-cell/p-table-header-cell.vue.d.ts +2 -2
  32. package/dist/squirrel/components/p-table-loader/p-table-loader.vue.d.ts +1 -1
  33. package/dist/squirrel/components/p-table-td/p-table-td.vue.d.ts +23 -11
  34. package/dist/squirrel/components/p-tabs/p-tabs.vue.d.ts +1 -1
  35. package/dist/squirrel/components/p-textarea/p-textarea.vue.d.ts +1 -1
  36. package/dist/squirrel/components/p-toggle/p-toggle.vue.d.ts +1 -1
  37. package/dist/squirrel/utils/inputClassesMixin.d.ts +1 -1
  38. package/package.json +25 -24
  39. package/squirrel/components/p-btn/p-btn.spec.js +227 -161
  40. package/squirrel/components/p-btn/p-btn.stories.js +32 -8
  41. package/squirrel/components/p-btn/p-btn.vue +106 -73
  42. package/squirrel/components/p-dropdown/p-dropdown.vue +0 -1
  43. package/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue +1 -1
  44. package/squirrel/components/p-select-btn/p-select-btn.stories.js +45 -4
  45. package/squirrel/components/p-select-btn/p-select-btn.vue +2 -2
@@ -21,25 +21,36 @@
21
21
  :disabled="!!$attrs.disabled || loading ? true : null"
22
22
  :aria-disabled="$attrs.disabled"
23
23
  >
24
- <div :class="{ invisible: loading }"><slot></slot></div>
24
+ <div :class="[{ invisible: loading }, classes.content]">
25
+ <PIcon v-if="icon" :icon="icon" :class="classes.icon" />
26
+ <span class="slot-wrapper empty:hidden">
27
+ <slot></slot>
28
+ </span>
29
+ <PIcon v-if="iconRight" :icon="iconRight" :class="classes.icon" />
30
+ </div>
25
31
  <PRingLoader v-if="loading" :size="loaderSize" :class="classes.loader" />
26
32
  </Component>
27
33
  </template>
28
34
 
29
35
  <script lang="ts">
30
36
  import { type Size, SIZES } from '@squirrel/components/p-btn/p-btn.types';
37
+ import PIcon from '@squirrel/components/p-icon/p-icon.vue';
31
38
  import PRingLoader from '@squirrel/components/p-ring-loader/p-ring-loader.vue';
32
39
  import { isExternalLink } from '@squirrel/utils/link';
33
40
  import { sanitizeUrl } from '@squirrel/utils/sanitization';
34
41
  import { tv, type VariantProps } from 'tailwind-variants';
35
- import { defineComponent, type PropType } from 'vue';
36
- import { type RouteLocationRaw, RouterLink } from 'vue-router';
42
+ import { computed, type PropType } from 'vue';
43
+ import { type RouteLocationRaw } from 'vue-router';
44
+
45
+ type Icon = InstanceType<typeof PIcon>['$props']['icon'];
37
46
 
38
47
  const btnClasses = {
39
48
  slots: {
40
49
  button:
41
50
  'relative inline-block rounded font-medium outline-none disabled:pointer-events-none disabled:cursor-default disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:cursor-default aria-disabled:opacity-50',
51
+ content: 'flex items-center justify-center has-[.slot-wrapper:empty]:gap-0',
42
52
  loader: 'absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center font-medium',
53
+ icon: 'shrink-0',
43
54
  },
44
55
  variants: {
45
56
  type: {
@@ -72,9 +83,21 @@ const btnClasses = {
72
83
  'secondary-ghost-dark': { button: 'text-white hover:bg-p-purple-50', loader: 'text-p-blue-15' },
73
84
  },
74
85
  size: {
75
- sm: { button: 'px-2 py-1 text-sm' },
76
- md: { button: 'px-6 py-2 text-base' },
77
- lg: { button: 'px-6 py-2.5 text-lg' },
86
+ sm: {
87
+ button: 'px-2 has-[.slot-wrapper:empty]:px-1 py-1 text-sm',
88
+ content: 'gap-1',
89
+ icon: 'text-lg',
90
+ },
91
+ md: {
92
+ button: 'px-6 has-[.slot-wrapper:empty]:px-2 py-2 text-base',
93
+ content: 'gap-2',
94
+ icon: 'text-xl',
95
+ },
96
+ lg: {
97
+ button: 'px-6 has-[.slot-wrapper:empty]:px-2.5 py-2.5 text-lg',
98
+ content: 'gap-2.5',
99
+ icon: 'text-2xl',
100
+ },
78
101
  },
79
102
  },
80
103
  defaultVariants: {
@@ -84,87 +107,97 @@ const btnClasses = {
84
107
  } as const;
85
108
 
86
109
  const btn = tv(btnClasses);
110
+
87
111
  const BUTTON_TYPES = Object.keys(btnClasses.variants.type);
88
112
  const BUTTON_NATIVE_TYPES = ['button', 'submit', 'reset'] as const;
89
113
  const LOADER_SIZES = { sm: 24, md: 30, lg: 40 } as const satisfies { [key in Size]: number };
90
114
 
91
115
  type ButtonNativeType = (typeof BUTTON_NATIVE_TYPES)[number];
92
116
  type ButtonType = NonNullable<VariantProps<typeof btn>['type']>;
117
+ </script>
93
118
 
94
- export default defineComponent({
119
+ <script setup lang="ts">
120
+ defineOptions({
95
121
  name: 'PBtn',
96
- components: {
97
- PRingLoader,
98
- RouterLink,
99
- },
100
122
  inheritAttrs: false,
101
- props: {
102
- /**
103
- * The button style e.g primary, secondary, primary-outline, secondary-outline, error, success, primary-link
104
- */
105
- type: {
106
- type: String as PropType<ButtonType>,
107
- default: 'primary',
108
- validator(value: ButtonType) {
109
- return BUTTON_TYPES.includes(value);
110
- },
111
- },
112
- /**
113
- * The button native type e.g button, submit, reset
114
- */
115
- nativeType: {
116
- type: String as PropType<ButtonNativeType>,
117
- default: 'button',
118
- validator(value: ButtonNativeType) {
119
- return BUTTON_NATIVE_TYPES.includes(value);
120
- },
121
- },
122
- /**
123
- * The button size e.g sm, md, lg
124
- */
125
- size: {
126
- type: String as PropType<Size>,
127
- default: 'md',
128
- validator(value: Size) {
129
- return SIZES.includes(value);
130
- },
131
- },
132
- /**
133
- * Whether the button is loading
134
- */
135
- loading: {
136
- type: Boolean,
137
- default: false,
138
- },
139
- /**
140
- * Whether the button is selected (sets aria-selected attribute)
141
- */
142
- selected: {
143
- type: Boolean,
144
- default: false,
145
- },
146
- /**
147
- * Exactly as the `to` prop in `RouterLink`, when used, it renders a link that triggers a navigation on click.
148
- * See https://router.vuejs.org/api/#RouteLocationRaw
149
- */
150
- to: {
151
- type: [Object, String] as PropType<RouteLocationRaw>,
152
- default: '',
123
+ });
124
+
125
+ const props = defineProps({
126
+ /**
127
+ * The button style e.g primary, secondary, primary-outline, secondary-outline, error, success, primary-link
128
+ */
129
+ type: {
130
+ type: String as PropType<ButtonType>,
131
+ default: 'primary',
132
+ validator(value: ButtonType) {
133
+ return BUTTON_TYPES.includes(value);
153
134
  },
154
135
  },
155
- computed: {
156
- classes() {
157
- const { button, loader } = btn({ type: this.type, size: this.size });
158
-
159
- return { button: button(), loader: loader() };
136
+ /**
137
+ * The button native type e.g button, submit, reset
138
+ */
139
+ nativeType: {
140
+ type: String as PropType<ButtonNativeType>,
141
+ default: 'button',
142
+ validator(value: ButtonNativeType) {
143
+ return BUTTON_NATIVE_TYPES.includes(value);
160
144
  },
161
- loaderSize() {
162
- return Number(`${LOADER_SIZES[this.size]}`);
145
+ },
146
+ /**
147
+ * The button size e.g sm, md, lg
148
+ */
149
+ size: {
150
+ type: String as PropType<Size>,
151
+ default: 'md',
152
+ validator(value: Size) {
153
+ return SIZES.includes(value);
163
154
  },
164
155
  },
165
- methods: {
166
- isExternalLink,
167
- sanitizeUrl,
156
+ /**
157
+ * Whether the button is loading
158
+ */
159
+ loading: {
160
+ type: Boolean,
161
+ default: false,
162
+ },
163
+ /**
164
+ * Whether the button is selected (sets aria-selected attribute)
165
+ */
166
+ selected: {
167
+ type: Boolean,
168
+ default: false,
169
+ },
170
+ /**
171
+ * Exactly as the `to` prop in `RouterLink`, when used, it renders a link that triggers a navigation on click.
172
+ * See https://router.vuejs.org/api/#RouteLocationRaw
173
+ */
174
+ to: {
175
+ type: [Object, String] as PropType<RouteLocationRaw>,
176
+ default: '',
168
177
  },
178
+ /**
179
+ * The icon to display on the button
180
+ */
181
+ icon: {
182
+ type: String as PropType<Icon>,
183
+ default: '',
184
+ },
185
+ iconRight: {
186
+ type: String as PropType<Icon>,
187
+ default: '',
188
+ },
189
+ });
190
+
191
+ const classes = computed(() => {
192
+ const { button, content, loader, icon } = btn({
193
+ type: props.type,
194
+ size: props.size,
195
+ });
196
+
197
+ return { button: button(), content: content(), loader: loader(), icon: icon() };
198
+ });
199
+
200
+ const loaderSize = computed(() => {
201
+ return Number(`${LOADER_SIZES[props.size]}`);
169
202
  });
170
203
  </script>
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <VDropdown ref="vPopper" v-bind="{ ...defaultAttrs, ...$attrs }" @show="onShow" @hide="destroy">
3
- <!-- @vue-expect-error -->
4
3
  <template v-for="(_, slot) in $slots" #[slot]="scope">
5
4
  <slot :name="slot" v-bind="scope || {}" />
6
5
  </template>
@@ -45,7 +45,7 @@ const attrs = useAttrs();
45
45
  const { labelClasses, errorMsgClasses } = useInputClasses(props);
46
46
 
47
47
  // Computed
48
- const datePickerProps = computed(() => {
48
+ const datePickerProps = computed<VueDatePickerProps>(() => {
49
49
  const { modelValue: _, ...propsWithoutModelValue } = props;
50
50
  const { class: classes, style, ...attrsWithoutClassAndStyle } = attrs;
51
51
 
@@ -52,9 +52,11 @@ export const Default = {
52
52
  play: async ({ canvasElement }) => {
53
53
  const canvas = within(canvasElement);
54
54
 
55
- await userEvent.click(canvas.getByText(/Meris/i));
55
+ const btn = canvas.getByRole('button', { name: /Aleksandr Chappel/i });
56
56
 
57
- await expect(canvas.getByText(/Meris/i).parentNode.getAttribute('aria-selected')).toBe('true');
57
+ await userEvent.click(btn);
58
+
59
+ await expect(btn.getAttribute('aria-selected')).toBe('true');
58
60
  },
59
61
  };
60
62
 
@@ -72,9 +74,9 @@ export const DisabledOption = {
72
74
  play: async ({ canvasElement }) => {
73
75
  const canvas = within(canvasElement);
74
76
 
75
- const disabledEl = canvas.getByText(/Van/i);
77
+ const disabledBtn = canvas.getByRole('button', { name: /Van Deyes/i });
76
78
 
77
- await expect(disabledEl.parentNode.hasAttribute('disabled')).toBe(true);
79
+ await expect(disabledBtn.hasAttribute('disabled')).toBe(true);
78
80
  await expect(canvas.getByText(/Meris/i).parentNode.hasAttribute('disabled')).toBe(false);
79
81
  await expect(canvas.getByText(/Chick/i).parentNode.hasAttribute('disabled')).toBe(false);
80
82
  },
@@ -245,3 +247,42 @@ export const MultipleSelected = {
245
247
  },
246
248
  },
247
249
  };
250
+
251
+ export const WithIcons = {
252
+ args: {
253
+ items: [
254
+ { value: 1, text: 'Aleksandr Chappel', icon: 'archive' },
255
+ { value: 2, text: 'Van Deyes', icon: 'edit' },
256
+ { value: 3, text: 'Meris Hardman', icon: 'delete' },
257
+ { value: 4, text: 'Chick Catto', icon: 'send' },
258
+ { value: 5, text: "Alys O'Flynn", icon: 'settings' },
259
+ ],
260
+ },
261
+ parameters: {
262
+ docs: {
263
+ description: {
264
+ story: 'We can pass an `icon` attribute to the list of options to add an icon to an option.',
265
+ },
266
+ },
267
+ },
268
+ };
269
+
270
+ export const WithIconsOnly = {
271
+ args: {
272
+ items: [
273
+ { value: 1, icon: 'archive' },
274
+ { value: 2, icon: 'edit' },
275
+ { value: 3, icon: 'delete' },
276
+ { value: 4, icon: 'send' },
277
+ { value: 5, icon: 'settings' },
278
+ ],
279
+ },
280
+ parameters: {
281
+ docs: {
282
+ description: {
283
+ story:
284
+ 'We can pass an `icon` attribute without a `text` attribute to the list of options to only display an icon.',
285
+ },
286
+ },
287
+ },
288
+ };
@@ -2,7 +2,7 @@
2
2
  <div :class="{ flex: grow }">
3
3
  <div
4
4
  v-for="(item, index) in items"
5
- :key="item[itemValue] as Key"
5
+ :key="String(item[itemValue])"
6
6
  v-tooltip="{ content: tooltipText(item) }"
7
7
  :class="['inline-flex', { '*:px-0 *:py-0': noPadding, grow }]"
8
8
  >
@@ -10,6 +10,7 @@
10
10
  :size="size"
11
11
  type="secondary-outline-blue"
12
12
  :disabled="item.disabled"
13
+ :icon="String(item.icon)"
13
14
  :class="{
14
15
  'rounded-none': index !== 0 && index !== items.length - 1 && items.length > 1,
15
16
  'rounded-br-none rounded-tr-none': index === 0 && items.length > 1,
@@ -31,7 +32,6 @@ import { type Size } from '@squirrel/components/p-btn/p-btn.types';
31
32
  import PBtn from '@squirrel/components/p-btn/p-btn.vue';
32
33
 
33
34
  type BtnGroupItem = Record<string, string | number | boolean>;
34
- type Key = string | number;
35
35
 
36
36
  type Props = {
37
37
  modelValue?: string | number | null | BtnGroupItem[];