@pequity/squirrel 5.1.0 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ const P_ICON_ALIASES = {
2
+ delete: "octicon:trash-24",
3
+ edit: "simple-line-icons:pencil",
4
+ send: "fa:paper-plane",
5
+ settings: "heroicons:cog-8-tooth-20-solid"
6
+ };
7
+ export {
8
+ P_ICON_ALIASES
9
+ };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, resolveComponent, openBlock, createBlock, withCtx, renderSlot, createTextVNode, toDisplayString, pushScopeId, popScopeId, createElementVNode } from "vue";
2
2
  import { _ as _export_sfc } from "./chunks/_plugin-vue_export-helper.js";
3
- const _withScopeId = (n) => (pushScopeId("data-v-2662da21"), n = n(), popScopeId(), n);
3
+ const _withScopeId = (n) => (pushScopeId("data-v-a46da710"), n = n(), popScopeId(), n);
4
4
  const _hoisted_1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElementVNode("i", { class: "bg-info-circle-icon block h-3 w-3" }, null, -1));
5
5
  const _sfc_main = /* @__PURE__ */ defineComponent({
6
6
  ...{
@@ -8,32 +8,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
8
8
  },
9
9
  __name: "p-info-icon",
10
10
  props: {
11
- text: {
12
- type: String,
13
- default: ""
14
- }
11
+ text: { default: null }
15
12
  },
16
13
  setup(__props) {
17
14
  return (_ctx, _cache) => {
18
15
  const _component_VTooltip = resolveComponent("VTooltip");
19
16
  return openBlock(), createBlock(_component_VTooltip, {
20
17
  "popper-triggers": ["hover"],
21
- delay: { show: 750, hide: 0 }
18
+ delay: { show: 750, hide: 0 },
19
+ disabled: !_ctx.text
22
20
  }, {
23
21
  popper: withCtx(() => [
24
22
  renderSlot(_ctx.$slots, "default", {}, () => [
25
- createTextVNode(toDisplayString(__props.text), 1)
23
+ createTextVNode(toDisplayString(_ctx.text), 1)
26
24
  ], true)
27
25
  ]),
28
26
  default: withCtx(() => [
29
27
  _hoisted_1
30
28
  ]),
31
29
  _: 3
32
- });
30
+ }, 8, ["disabled"]);
33
31
  };
34
32
  }
35
33
  });
36
- const PInfoIcon = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-2662da21"]]);
34
+ const PInfoIcon = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a46da710"]]);
37
35
  export {
38
36
  PInfoIcon as default
39
37
  };
@@ -12,6 +12,7 @@ import PDropdown from './p-dropdown/p-dropdown.vue';
12
12
  import PDropdownSelect from './p-dropdown-select/p-dropdown-select.vue';
13
13
  import PFileUpload from './p-file-upload/p-file-upload.vue';
14
14
  import PFilterIcon from './p-table-header-cell/p-table-filter-icon.vue';
15
+ import PIcon from './p-icon/p-icon.vue';
15
16
  import PInfoIcon from './p-info-icon/p-info-icon.vue';
16
17
  import PInlineDatePicker from './p-inline-date-picker/p-inline-date-picker.vue';
17
18
  import PInput from './p-input/p-input.vue';
@@ -41,6 +42,7 @@ import PToggle from './p-toggle/p-toggle.vue';
41
42
  import { type FileUploadFile } from './p-file-upload/p-file-upload.types';
42
43
  import { type HeaderCellAttrs, MIN_WIDTH_COL_RESIZE, type TableCol, type ThAttrs, colsInjectionKey, isColsResizableInjectionKey, isFirstColFixedInjectionKey, isLastColFixedInjectionKey } from './p-table/p-table.types';
43
44
  import { type PActionBarAction } from './p-action-bar/p-action-bar.types';
45
+ import { type PIconAlias, P_ICON_ALIASES } from './p-icon/p-icon.types';
44
46
  import { SORTING_TYPES, type SortingType, type SortingTypeWithoutNoSorting } from './p-table-sort/p-table-sort.config';
45
47
  import { type Size } from './p-btn/p-btn.types';
46
48
  import { usePLoading } from './p-loading/usePLoading';
@@ -48,4 +50,4 @@ import { usePModal } from './p-modal/usePModal';
48
50
  import { usePTableColResize } from './p-table/usePTableColResize';
49
51
  import { usePTableRowVirtualizer } from './p-table/usePTableRowVirtualizer';
50
52
  import { useSelectList } from './p-select-list/useSelectList';
51
- export { PActionBar, PActionBarAction, PAlert, PAvatar, PBtn, PCard, PCheckbox, PChips, PCloseBtn, PDatePicker, PDrawer, PDropdown, PDropdownSelect, PFileUpload, PFilterIcon, PInfoIcon, PInlineDatePicker, PInput, PInputNumber, PInputPercent, PInputSearch, PLink, PLoading, PModal, PPagination, PPaginationInfo, PProgressBar, PRingLoader, PSelect, PSelectBtn, PSelectList, PSelectPill, PSkeletonLoader, PTable, PTableHeaderCell, PTableLoader, PTableSort, PTableTd, PTabs, PTextarea, PToggle, SORTING_TYPES, MIN_WIDTH_COL_RESIZE, colsInjectionKey, isColsResizableInjectionKey, isFirstColFixedInjectionKey, isLastColFixedInjectionKey, usePModal, usePTableColResize, usePTableRowVirtualizer, useSelectList, usePLoading, SortingType, SortingTypeWithoutNoSorting, Size, FileUploadFile, HeaderCellAttrs, TableCol, ThAttrs, };
53
+ export { PActionBar, PActionBarAction, PAlert, PAvatar, PBtn, PCard, PCheckbox, PChips, PCloseBtn, PDatePicker, PDrawer, PDropdown, PDropdownSelect, PFileUpload, PFilterIcon, PIcon, PInfoIcon, PInlineDatePicker, PInput, PInputNumber, PInputPercent, PInputSearch, PLink, PLoading, PModal, PPagination, PPaginationInfo, PProgressBar, PRingLoader, PSelect, PSelectBtn, PSelectList, PSelectPill, PSkeletonLoader, PTable, PTableHeaderCell, PTableLoader, PTableSort, PTableTd, PTabs, PTextarea, PToggle, SORTING_TYPES, MIN_WIDTH_COL_RESIZE, P_ICON_ALIASES, colsInjectionKey, isColsResizableInjectionKey, isFirstColFixedInjectionKey, isLastColFixedInjectionKey, usePModal, usePTableColResize, usePTableRowVirtualizer, useSelectList, usePLoading, SortingType, SortingTypeWithoutNoSorting, Size, FileUploadFile, HeaderCellAttrs, TableCol, ThAttrs, PIconAlias, };
@@ -0,0 +1,7 @@
1
+ export declare const P_ICON_ALIASES: {
2
+ readonly delete: "octicon:trash-24";
3
+ readonly edit: "simple-line-icons:pencil";
4
+ readonly send: "fa:paper-plane";
5
+ readonly settings: "heroicons:cog-8-tooth-20-solid";
6
+ };
7
+ export type PIconAlias = keyof typeof P_ICON_ALIASES;
@@ -0,0 +1,17 @@
1
+ import { type IconifyIconAttributes } from 'iconify-icon';
2
+ import { type PIconAlias } from './p-icon.types';
3
+ import 'iconify-icon';
4
+ interface Props extends /* @vue-ignore */ Omit<IconifyIconAttributes, 'icon'> {
5
+ icon: IconifyIconAttributes['icon'] | PIconAlias;
6
+ }
7
+ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToOption<Props>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<Props>>>, {}, {}>;
8
+ export default _default;
9
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
10
+ type __VLS_TypePropsToOption<T> = {
11
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
12
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
13
+ } : {
14
+ type: import('vue').PropType<T[K]>;
15
+ required: true;
16
+ };
17
+ };
@@ -1,3 +1,6 @@
1
+ type Props = {
2
+ text: string | null;
3
+ };
1
4
  declare function __VLS_template(): {
2
5
  slots: {
3
6
  default?(_: {}): any;
@@ -6,23 +9,34 @@ declare function __VLS_template(): {
6
9
  attrs: Partial<{}>;
7
10
  };
8
11
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
9
- declare const __VLS_component: import("vue").DefineComponent<{
10
- text: {
11
- type: StringConstructor;
12
- default: string;
13
- };
14
- }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
15
- text: {
16
- type: StringConstructor;
17
- default: string;
18
- };
19
- }>>, {
20
- text: string;
12
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
13
+ text: null;
14
+ }>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
15
+ text: null;
16
+ }>>>, {
17
+ text: string | null;
21
18
  }, {}>;
22
19
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
23
20
  export default _default;
21
+ type __VLS_WithDefaults<P, D> = {
22
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_PrettifyLocal<P[K] & {
23
+ default: D[K];
24
+ }> : P[K];
25
+ };
26
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
27
+ type __VLS_TypePropsToOption<T> = {
28
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
29
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
30
+ } : {
31
+ type: import('vue').PropType<T[K]>;
32
+ required: true;
33
+ };
34
+ };
24
35
  type __VLS_WithTemplateSlots<T, S> = T & {
25
36
  new (): {
26
37
  $slots: S;
27
38
  };
28
39
  };
40
+ type __VLS_PrettifyLocal<T> = {
41
+ [K in keyof T]: T[K];
42
+ } & {};
package/dist/style.css CHANGED
@@ -7,7 +7,7 @@
7
7
  transform: translateX(100%);
8
8
  }
9
9
  }
10
- .bg-info-circle-icon[data-v-2662da21] {
10
+ .bg-info-circle-icon[data-v-a46da710] {
11
11
  background-image: url("data:image/svg+xml,%3csvg%20width='12'%20height='12'%20viewBox='0%200%2012%2012'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_4002_33291)'%3e%3cpath%20d='M0.5%206C0.5%207.45869%201.07946%208.85764%202.11091%209.88909C3.14236%2010.9205%204.54131%2011.5%206%2011.5C7.45869%2011.5%208.85764%2010.9205%209.88909%209.88909C10.9205%208.85764%2011.5%207.45869%2011.5%206C11.5%204.54131%2010.9205%203.14236%209.88909%202.11091C8.85764%201.07946%207.45869%200.5%206%200.5C4.54131%200.5%203.14236%201.07946%202.11091%202.11091C1.07946%203.14236%200.5%204.54131%200.5%206Z'%20stroke='%231A123B'%20stroke-miterlimit='10'/%3e%3cpath%20d='M6.5%203.5H5.5V2.5H6.5V3.5Z'%20fill='%231A123B'/%3e%3cpath%20d='M4.5%205H6V9M4.5%208.5H7.5'%20stroke='%231A123B'%20stroke-miterlimit='10'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_4002_33291'%3e%3crect%20width='12'%20height='12'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e");
12
12
  }
13
13
  div[id^=popper_].dropdown {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@pequity/squirrel",
3
3
  "description": "Squirrel component library",
4
- "version": "5.1.0",
5
- "packageManager": "pnpm@9.9.0",
4
+ "version": "5.2.1",
5
+ "packageManager": "pnpm@9.10.0",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "preinstall": "npx only-allow pnpm",
@@ -52,31 +52,31 @@
52
52
  "devDependencies": {
53
53
  "@babel/core": "^7.25.2",
54
54
  "@babel/preset-env": "^7.25.4",
55
- "@commitlint/cli": "^19.4.1",
56
- "@commitlint/config-conventional": "^19.4.1",
55
+ "@commitlint/cli": "^19.5.0",
56
+ "@commitlint/config-conventional": "^19.5.0",
57
57
  "@pequity/eslint-config": "^0.0.13",
58
- "@playwright/test": "^1.47.0",
58
+ "@playwright/test": "^1.47.1",
59
59
  "@popperjs/core": "2.11.8",
60
60
  "@semantic-release/changelog": "^6.0.3",
61
61
  "@semantic-release/git": "^10.0.1",
62
- "@storybook/addon-a11y": "^8.2.9",
63
- "@storybook/addon-actions": "^8.2.9",
64
- "@storybook/addon-essentials": "^8.2.9",
65
- "@storybook/addon-interactions": "^8.2.9",
66
- "@storybook/addon-links": "^8.2.9",
67
- "@storybook/blocks": "^8.2.9",
68
- "@storybook/manager-api": "^8.2.9",
69
- "@storybook/test": "^8.2.9",
62
+ "@storybook/addon-a11y": "^8.3.2",
63
+ "@storybook/addon-actions": "^8.3.2",
64
+ "@storybook/addon-essentials": "^8.3.2",
65
+ "@storybook/addon-interactions": "^8.3.2",
66
+ "@storybook/addon-links": "^8.3.2",
67
+ "@storybook/blocks": "^8.3.2",
68
+ "@storybook/manager-api": "^8.3.2",
69
+ "@storybook/test": "^8.3.2",
70
70
  "@storybook/test-runner": "^0.19.1",
71
- "@storybook/theming": "^8.2.9",
72
- "@storybook/vue3": "^8.2.9",
73
- "@storybook/vue3-vite": "^8.2.9",
74
- "@tanstack/vue-virtual": "3.10.7",
75
- "@types/jest": "^29.5.12",
71
+ "@storybook/theming": "^8.3.2",
72
+ "@storybook/vue3": "^8.3.2",
73
+ "@storybook/vue3-vite": "^8.3.2",
74
+ "@tanstack/vue-virtual": "3.10.8",
75
+ "@types/jest": "^29.5.13",
76
76
  "@types/jsdom": "^21.1.7",
77
77
  "@types/lodash-es": "^4.17.12",
78
- "@types/node": "^22.5.4",
79
- "@vitejs/plugin-vue": "^5.1.3",
78
+ "@types/node": "^22.5.5",
79
+ "@vitejs/plugin-vue": "^5.1.4",
80
80
  "@vue/compiler-sfc": "3.4.38",
81
81
  "@vue/test-utils": "^2.4.6",
82
82
  "@vue/vue3-jest": "^29.2.6",
@@ -87,29 +87,30 @@
87
87
  "eslint-plugin-storybook": "^0.8.0",
88
88
  "floating-vue": "5.2.2",
89
89
  "glob": "^11.0.0",
90
- "husky": "^9.1.5",
90
+ "husky": "^9.1.6",
91
+ "iconify-icon": "^2.1.0",
91
92
  "jest": "^29.7.0",
92
93
  "jest-environment-jsdom": "^29.7.0",
93
94
  "lint-staged": "^15.2.10",
94
95
  "lodash-es": "4.17.21",
95
96
  "make-coverage-badge": "^1.2.0",
96
- "postcss": "^8.4.45",
97
+ "postcss": "^8.4.47",
97
98
  "prettier": "^3.3.3",
98
99
  "prettier-plugin-tailwindcss": "^0.6.6",
99
- "resolve-tspaths": "^0.8.19",
100
+ "resolve-tspaths": "^0.8.22",
100
101
  "rimraf": "^6.0.1",
101
- "sass": "^1.78.0",
102
+ "sass": "^1.79.2",
102
103
  "semantic-release": "^24.1.1",
103
- "storybook": "^8.2.9",
104
+ "storybook": "^8.3.2",
104
105
  "svgo": "^3.3.2",
105
- "tailwindcss": "^3.4.10",
106
+ "tailwindcss": "^3.4.12",
106
107
  "ts-jest": "^29.2.5",
107
- "typescript": "5.5.4",
108
+ "typescript": "5.6.2",
108
109
  "v-calendar": "3.1.2",
109
- "vite": "^5.4.3",
110
+ "vite": "^5.4.6",
110
111
  "vue": "3.4.38",
111
112
  "vue-currency-input": "3.1.0",
112
- "vue-router": "4.4.3",
113
+ "vue-router": "4.4.5",
113
114
  "vue-toastification": "2.0.0-rc.5",
114
115
  "vue-tsc": "2.1.6"
115
116
  }
@@ -12,6 +12,7 @@ import PDropdown from '@squirrel/components/p-dropdown/p-dropdown.vue';
12
12
  import PDropdownSelect from '@squirrel/components/p-dropdown-select/p-dropdown-select.vue';
13
13
  import PFileUpload from '@squirrel/components/p-file-upload/p-file-upload.vue';
14
14
  import PFilterIcon from '@squirrel/components/p-table-header-cell/p-table-filter-icon.vue';
15
+ import PIcon from '@squirrel/components/p-icon/p-icon.vue';
15
16
  import PInfoIcon from '@squirrel/components/p-info-icon/p-info-icon.vue';
16
17
  import PInlineDatePicker from '@squirrel/components/p-inline-date-picker/p-inline-date-picker.vue';
17
18
  import PInput from '@squirrel/components/p-input/p-input.vue';
@@ -50,6 +51,7 @@ import {
50
51
  isLastColFixedInjectionKey,
51
52
  } from '@squirrel/components/p-table/p-table.types';
52
53
  import { type PActionBarAction } from '@squirrel/components/p-action-bar/p-action-bar.types';
54
+ import { type PIconAlias, P_ICON_ALIASES } from '@squirrel/components/p-icon/p-icon.types';
53
55
  import {
54
56
  SORTING_TYPES,
55
57
  type SortingType,
@@ -78,6 +80,7 @@ export {
78
80
  PDropdownSelect,
79
81
  PFileUpload,
80
82
  PFilterIcon,
83
+ PIcon,
81
84
  PInfoIcon,
82
85
  PInlineDatePicker,
83
86
  PInput,
@@ -106,6 +109,7 @@ export {
106
109
  PToggle,
107
110
  SORTING_TYPES,
108
111
  MIN_WIDTH_COL_RESIZE,
112
+ P_ICON_ALIASES,
109
113
  colsInjectionKey,
110
114
  isColsResizableInjectionKey,
111
115
  isFirstColFixedInjectionKey,
@@ -122,4 +126,5 @@ export {
122
126
  HeaderCellAttrs,
123
127
  TableCol,
124
128
  ThAttrs,
129
+ PIconAlias,
125
130
  };
@@ -0,0 +1,79 @@
1
+ import PIcon from '@squirrel/components/p-icon/p-icon.vue';
2
+ import { P_ICON_ALIASES } from '@squirrel/components/p-icon/p-icon.types';
3
+ import { createWrapperFor } from '@tests/jest.helpers';
4
+
5
+ const createWrapper = (props, attrs) => {
6
+ return createWrapperFor(PIcon, {
7
+ props: {
8
+ icon: 'ant-design:build-twotone',
9
+ ...props,
10
+ },
11
+ attrs,
12
+ global: {
13
+ stubs: {
14
+ 'iconify-icon': true,
15
+ },
16
+ },
17
+ });
18
+ };
19
+
20
+ describe('PIcon.vue', () => {
21
+ it('renders an icon', async () => {
22
+ const wrapper = createWrapper({
23
+ icon: 'ant-design:build-twotone',
24
+ });
25
+
26
+ const icon = wrapper.findComponent('iconify-icon-stub');
27
+
28
+ expect(icon.exists()).toBe(true);
29
+ expect(icon.attributes().icon).toBe('ant-design:build-twotone');
30
+ });
31
+
32
+ it('passes arbitrary attrs to the icon component', async () => {
33
+ const wrapper = createWrapper({}, { 'data-test': 'test' });
34
+
35
+ const icon = wrapper.findComponent('iconify-icon-stub');
36
+
37
+ expect(icon.attributes()['data-test']).toBe('test');
38
+ });
39
+
40
+ it('passes down events to the icon component', async () => {
41
+ const clickFn = jest.fn();
42
+
43
+ const wrapper = createWrapperFor(
44
+ {
45
+ template: '<PIcon icon="ant-design:build-twotone" @click="onClick" />',
46
+ components: {
47
+ PIcon,
48
+ },
49
+ methods: {
50
+ onClick: clickFn,
51
+ },
52
+ },
53
+ {
54
+ global: {
55
+ stubs: {
56
+ 'iconify-icon': true,
57
+ },
58
+ },
59
+ }
60
+ );
61
+
62
+ const icon = wrapper.findComponent('iconify-icon-stub');
63
+
64
+ await icon.trigger('click');
65
+
66
+ expect(clickFn).toHaveBeenCalled();
67
+ });
68
+
69
+ it.each(Object.entries(P_ICON_ALIASES))(
70
+ 'renders the %s icon when the %s is passed as an icon prop',
71
+ async (iconAliasKey, iconAlias) => {
72
+ const wrapper = createWrapper({ icon: iconAliasKey });
73
+
74
+ const icon = wrapper.findComponent('iconify-icon-stub');
75
+
76
+ expect(icon.attributes().icon).toBe(iconAlias);
77
+ }
78
+ );
79
+ });
@@ -0,0 +1,128 @@
1
+ import PIcon from '@squirrel/components/p-icon/p-icon.vue';
2
+ import { P_ICON_ALIASES } from '@squirrel/components/p-icon/p-icon.types';
3
+
4
+ export default {
5
+ title: 'Components/PIcon',
6
+ component: PIcon,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component: `**PIcon** is a wrapper for the [iconify-icon](https://iconify.design/docs/iconify-icon/#attributes) web component that adds custom **icon aliases**, making it easier to maintain a consistent and unified icon set.
12
+
13
+ All the customization options provided by [iconify-icon](https://iconify.design/docs/iconify-icon/#attributes) are available.
14
+
15
+ - Learn how to control icon dimensions [here](https://iconify.design/docs/iconify-icon/dimensions.html).
16
+ - Discover how to adjust icon colors [here](https://iconify.design/docs/iconify-icon/color).
17
+ - Check out the available icons [here](https://icon-sets.iconify.design/).`,
18
+ },
19
+ },
20
+ },
21
+ args: {
22
+ icon: 'ant-design:build-twotone',
23
+ mode: 'svg',
24
+ inline: false,
25
+ width: '4rem',
26
+ height: '4rem',
27
+ flip: '',
28
+ rotate: '',
29
+ },
30
+ argTypes: {
31
+ icon: {
32
+ control: { type: 'text' },
33
+ description: 'Icon',
34
+ },
35
+ mode: {
36
+ control: { type: 'select' },
37
+ options: ['svg', 'style', 'bg', 'mask'],
38
+ description: 'Sets icon rendering mode. See [rendering modes](https://iconify.design/docs/iconify-icon/modes).',
39
+ },
40
+ inline: {
41
+ control: { type: 'boolean' },
42
+ description:
43
+ 'Changes vertical alignment. See [vertical alignment](https://iconify.design/docs/iconify-icon/inline.html).',
44
+ },
45
+ width: {
46
+ control: { type: 'text' },
47
+ description: 'Icon width. See [icon dimensions](https://iconify.design/docs/iconify-icon/dimensions.html).',
48
+ },
49
+ height: {
50
+ control: { type: 'text' },
51
+ description: 'Icon height. See [icon dimensions](https://iconify.design/docs/iconify-icon/dimensions.html).',
52
+ },
53
+ flip: {
54
+ control: { type: 'select' },
55
+ options: ['', 'horizontal', 'vertical'],
56
+ description: 'Flip icon. See [icon transformations](https://iconify.design/docs/iconify-icon/transform.html).',
57
+ },
58
+ rotate: {
59
+ control: { type: 'select' },
60
+ options: ['', '90deg', '180deg', '270deg'],
61
+ description: 'Rotates icon. See [icon transformations](https://iconify.design/docs/iconify-icon/transform.html).',
62
+ },
63
+ color: {
64
+ control: { type: 'color' },
65
+ description: 'Icon color. See [icon colors](https://iconify.design/docs/iconify-icon/color).',
66
+ },
67
+ },
68
+ };
69
+
70
+ export const Default = {
71
+ render: (args) => ({
72
+ components: { PIcon },
73
+ setup() {
74
+ return { args };
75
+ },
76
+ template: `<PIcon v-bind="args" class="text-p-purple-50" :style="{ color: args.color }" />`,
77
+ }),
78
+ };
79
+
80
+ export const IconAlias = {
81
+ ...Default,
82
+ args: {
83
+ icon: 'delete',
84
+ },
85
+ argTypes: {
86
+ icon: {
87
+ control: { type: 'select' },
88
+ options: Object.keys(P_ICON_ALIASES),
89
+ },
90
+ },
91
+ parameters: {
92
+ docs: {
93
+ description: {
94
+ story: `The **icon** prop accepts an alias that points to a specific icon. This allows for a consistent and unified icon set.`,
95
+ },
96
+ },
97
+ },
98
+ };
99
+
100
+ export const AllIconAliases = {
101
+ ...Default,
102
+ render: (args) => ({
103
+ components: { PIcon },
104
+ setup() {
105
+ return { args, P_ICON_ALIASES };
106
+ },
107
+ template: `
108
+ <div class="mt-2 flex w-full gap-4">
109
+ <div
110
+ v-for="(iconClass, iconAlias) in P_ICON_ALIASES"
111
+ :key="iconAlias"
112
+ :title="iconClass"
113
+ class="flex flex-col items-center justify-center gap-y-2"
114
+ >
115
+ <PIcon v-bind="args" :icon="iconAlias" class="text-p-purple-50" :style="{ color: args.color }" />
116
+ <div>{{ iconAlias }}</div>
117
+ </div>
118
+ </div>
119
+ `,
120
+ }),
121
+ parameters: {
122
+ docs: {
123
+ description: {
124
+ story: `All available icon aliases.`,
125
+ },
126
+ },
127
+ },
128
+ };
@@ -0,0 +1,8 @@
1
+ export const P_ICON_ALIASES = {
2
+ delete: 'octicon:trash-24',
3
+ edit: 'simple-line-icons:pencil',
4
+ send: 'fa:paper-plane',
5
+ settings: 'heroicons:cog-8-tooth-20-solid',
6
+ } as const;
7
+
8
+ export type PIconAlias = keyof typeof P_ICON_ALIASES;
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <iconify-icon v-bind="{ ...$props, icon: isPIcon(icon) ? P_ICON_ALIASES[icon] : icon }" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { type IconifyIconAttributes } from 'iconify-icon';
7
+ import { type PIconAlias, P_ICON_ALIASES } from '@squirrel/components/p-icon/p-icon.types';
8
+ import 'iconify-icon';
9
+
10
+ defineOptions({
11
+ name: 'PIcon',
12
+ });
13
+
14
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
15
+ interface Props extends /* @vue-ignore */ Omit<IconifyIconAttributes, 'icon'> {
16
+ icon: IconifyIconAttributes['icon'] | PIconAlias;
17
+ }
18
+
19
+ const isPIcon = (icon: string): icon is PIconAlias => !!P_ICON_ALIASES[icon as PIconAlias];
20
+
21
+ defineProps<Props>();
22
+ </script>
@@ -34,8 +34,9 @@ describe('PInfoIcon.vue', () => {
34
34
  });
35
35
 
36
36
  expect(wrapper.text()).toBe('Lorem ipsum dolor sit amet.');
37
- expect(wrapper.attributes('placement')).toBe('bottom');
38
- expect(wrapper.attributes('distance')).toBe('10');
37
+ expect(wrapper.attributes().placement).toBe('bottom');
38
+ expect(wrapper.attributes().distance).toBe('10');
39
+ expect(wrapper.attributes().disabled).toBe('false');
39
40
  });
40
41
 
41
42
  it('passes the default slot to the VTooltip component', async () => {
@@ -76,4 +77,17 @@ describe('PInfoIcon.vue', () => {
76
77
  expect(tooltip.props().popperTriggers).toEqual(['hover']);
77
78
  expect(tooltip.props().delay).toEqual({ show: 750, hide: 0 });
78
79
  });
80
+
81
+ it.each([null, ''])('should set the disabled attribute when the text is empty (%s)', async (text) => {
82
+ const wrapper = createWrapperFor(PInfoIcon, {
83
+ props: { text },
84
+ global: {
85
+ stubs: {
86
+ VTooltip: { template: '<div class="v-tooltip-stub"><slot name="default" /><slot name="popper" /></div>' },
87
+ },
88
+ },
89
+ });
90
+
91
+ expect(wrapper.attributes().disabled).toBe('true');
92
+ });
79
93
  });
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <VTooltip :popper-triggers="['hover']" :delay="{ show: 750, hide: 0 }">
2
+ <VTooltip :popper-triggers="['hover']" :delay="{ show: 750, hide: 0 }" :disabled="!text">
3
3
  <i class="bg-info-circle-icon block h-3 w-3"></i>
4
4
  <template #popper>
5
5
  <slot>{{ text }}</slot>
@@ -12,11 +12,12 @@ defineOptions({
12
12
  name: 'PInfoIcon',
13
13
  });
14
14
 
15
- defineProps({
16
- text: {
17
- type: String,
18
- default: '',
19
- },
15
+ type Props = {
16
+ text: string | null;
17
+ };
18
+
19
+ withDefaults(defineProps<Props>(), {
20
+ text: null,
20
21
  });
21
22
  </script>
22
23