@policystudio/policy-studio-ui-vue 1.0.19 → 1.0.20

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/.eslintrc.js +1 -2
  2. package/.storybook/main.js +3 -3
  3. package/.storybook/preview.js +1 -1
  4. package/README.md +8 -0
  5. package/babel.config.js +3 -0
  6. package/backup-package-lock.json +37194 -0
  7. package/dist/css/psui_styles.css +31 -50
  8. package/package.json +28 -22
  9. package/src/assets/scss/base.scss +1 -28
  10. package/src/components/accordion/PsAccordion.vue +9 -1
  11. package/src/components/accordion/PsAccordionItem.vue +1 -1
  12. package/src/components/buttons/PsButton.vue +32 -12
  13. package/src/components/chips/PsChips.vue +46 -28
  14. package/src/components/controls/PsDraggable.vue +27 -2
  15. package/src/components/controls/PsRadioButton.vue +63 -38
  16. package/src/components/controls/PsSwitch.vue +75 -76
  17. package/src/components/datatable/PsDataTable.vue +25 -29
  18. package/src/components/datatable/PsDataTableItem.vue +2 -2
  19. package/src/components/tooltip/PsDialogTooltip.vue +79 -0
  20. package/src/components/tooltip/PsRichTooltip.vue +38 -0
  21. package/src/components/tooltip/PsTooltip.vue +120 -0
  22. package/src/components/ui/PsIcon.vue +87 -24
  23. package/src/index.js +15 -1
  24. package/src/stories/Accordion.stories.js +2 -2
  25. package/src/stories/Button.stories.js +11 -11
  26. package/src/stories/Checkbox.stories.js +6 -6
  27. package/src/stories/Chips.stories.js +7 -7
  28. package/src/stories/Colors.stories.mdx +35 -35
  29. package/src/stories/Datatable.stories.js +15 -8
  30. package/src/stories/Dialog.stories.js +9 -9
  31. package/src/stories/Draggable.stories.js +24 -0
  32. package/src/stories/Dropdown.stories.js +5 -5
  33. package/src/stories/Input.stories.js +10 -10
  34. package/src/stories/RadioButton.stories.js +14 -14
  35. package/src/stories/Slider.stories.js +9 -9
  36. package/src/stories/Swith.stories.js +10 -10
  37. package/src/stories/TabHeader.stories.js +9 -9
  38. package/src/stories/Toast.stories.js +13 -13
  39. package/src/stories/Toggle.stories.js +5 -5
  40. package/src/stories/Tooltip.stories.js +113 -0
  41. package/src/util/GeneralFunctions.js +8 -8
  42. package/src/util/imageLoader.js +50 -0
  43. package/tailwind.config.js +1 -0
  44. package/src/assets/scss/tailwind.css +0 -70643
  45. package/src/assets/scss/tailwind.scss +0 -61088
@@ -1,79 +1,104 @@
1
1
  <template>
2
- <label class="form-control">
3
- <span>{{ label }}</span>
4
- <input type="radio" :value="value" :name="name" v-model="radioButtonValue">
5
- <span class="radio-button"></span>
2
+ <label class="wrapper flex items-center">
3
+ {{ label }}
4
+ <input class="checkbox" type="radio" :checked="isChecked" :value="value" @change="$emit('change', $event.target.value)" />
5
+ <span class="checkmark" :class="{ 'checkmark-small' : small }"></span>
6
6
  </label>
7
7
  </template>
8
8
 
9
9
  <script>
10
10
  export default {
11
11
  name: 'PsRadioButton',
12
- props: ['name', 'label', 'value'],
12
+ props: {
13
+ label: {
14
+ type: String,
15
+ default: "",
16
+ required:true
17
+ },
18
+ modelValue: {
19
+ default: ""
20
+ },
21
+ value: {
22
+ type: String,
23
+ default: undefined
24
+ },
25
+ small: {
26
+ type: Boolean,
27
+ default: false
28
+ }
29
+ },
30
+ model: {
31
+ prop: 'modelValue',
32
+ event: 'change'
33
+ },
13
34
  computed: {
14
- radioButtonValue: {
15
- get: function() {
16
- return this.value
17
- },
18
- set: function() {
19
- this.$emit("change", this.value)
20
- }
35
+ isChecked() {
36
+ return this.modelValue == this.value
21
37
  }
22
38
  }
23
39
  }
24
40
  </script>
25
41
 
26
42
  <style scoped>
27
- .form-control {
43
+ .wrapper {
28
44
  display: block;
29
45
  position: relative;
30
- padding-left: 35px;
46
+ padding-left: 32px;
31
47
  cursor: pointer;
32
48
  -webkit-user-select: none;
33
49
  -moz-user-select: none;
34
50
  -ms-user-select: none;
35
51
  user-select: none;
36
52
  }
37
-
38
- .form-control input {
53
+ .wrapper input {
39
54
  position: absolute;
40
55
  opacity: 0;
41
56
  cursor: pointer;
57
+ height: 0;
58
+ width: 0;
42
59
  }
43
-
44
- .radio-button {
60
+ .checkmark {
45
61
  position: absolute;
46
62
  top: 0;
47
63
  left: 0;
48
- height: 20px;
49
- width: 20px;
50
- background-color: #FFF;
51
- border: 2px solid #A2ACB7;
64
+ height: 24px;
65
+ width: 24px;
52
66
  border-radius: 50%;
67
+ background-color: white;
68
+ border: 2px solid #A2ACB7;
53
69
  }
54
-
55
- .form-control input:checked ~ .radio-button {
56
- background-color: #FFF;
57
- border: 2px solid #64B5CE;
70
+ .checkmark-small {
71
+ top: 3px;
72
+ height: 18px !important;
73
+ width: 18px !important;
58
74
  }
59
-
60
- .radio-button:after {
75
+ .wrapper input:checked ~ .checkmark {
76
+ background-color: white;
77
+ border-color: #64B5CE;
78
+ border-width: 2px;
79
+ }
80
+ .checkmark:after {
61
81
  content: "";
62
82
  position: absolute;
63
83
  display: none;
64
84
  }
65
-
66
- .form-control input:checked ~ .radio-button:after {
85
+ .wrapper input:checked ~ .checkmark:after {
67
86
  display: block;
68
87
  }
69
-
70
- .form-control .radio-button:after {
88
+ .wrapper .checkmark:after {
89
+ top: 4px;
90
+ left: 4px;
91
+ width: 12px;
92
+ height: 12px;
93
+ border-radius: 50%;
94
+ background: #64B5CE;
95
+ }
96
+ .wrapper .checkmark-small:after {
71
97
  top: 3px;
72
- left: 3px;
73
- width: 10px;
74
- height: 10px;
75
- border-radius: 50%;
76
- background-color: #64B5CE;
98
+ left: 3px;
99
+ width: 8px;
100
+ height: 8px;
101
+ border-radius: 50%;
102
+ background: #64B5CE;
77
103
  }
78
-
79
104
  </style>
@@ -1,98 +1,97 @@
1
1
  <template>
2
- <label for="ps-switch" class="psui-flex psui-items-center psui-cursor-pointer psui-relative">
3
- <input type="checkbox" id="ps-switch" class="psui-hidden" :checked="active">
4
- <div
5
- :class="classes"
6
- @click="change()"
7
- ></div>
8
- <span class="psui-ml-3 psui-text-gray-50 psui-text-sm psui-font-medium">{{ label }}</span>
9
- </label>
2
+ <div class="switch-button-control">
3
+ <div
4
+ :class="{ enabled: active, 'switch-button': !small, 'switch-button-small': small }"
5
+ @click="toggle"
6
+ :style="{'--color': color}"
7
+ >
8
+ <div class="button"></div>
9
+ </div>
10
+ <div class="switch-button-label">
11
+ <slot></slot>
12
+ </div>
13
+ </div>
10
14
  </template>
11
15
 
12
16
  <script>
13
- export const sizes = ['big', 'small']
14
17
  export default {
15
18
  name: 'PsSwitch',
16
19
  props: {
17
- label: String,
18
- active: {
19
- type: Boolean,
20
- default: false
21
- },
22
- disabled: {
23
- type: Boolean,
24
- default: false
25
- },
26
- size: {
27
- type: String,
28
- default: 'big',
29
- validator: (value) => sizes.indexOf(value) !== -1
30
- }
20
+ small: Boolean,
21
+ active: Boolean,
22
+ color: {
23
+ type: String,
24
+ required: false,
25
+ default: '#5DB883'
26
+ }
31
27
  },
32
- computed: {
33
- text() {
34
- if (this.label && this.labelActived) {
35
- return this.active ? this.labelActived : this.label
36
- } else if (this.label) {
37
- return this.label
38
- } else {
39
- return false
40
- }
41
- },
42
- classes() {
43
- if (this.size === 'small') {
44
- return 'toggle-bg psui-bg-gray-40 psui-border-gray-40 psui-border-2 psui-h-4 ps-switch-small psui-rounded-full'
45
- }
46
- return 'toggle-bg psui-bg-gray-40 psui-border-gray-40 psui-border-2 psui-h-6 ps-switch psui-rounded-full'
47
- }
28
+ model: {
29
+ prop: "active",
30
+ event: "toggle"
48
31
  },
49
32
  methods: {
50
- change() {
51
- if (!this.disabled) {
52
- this.$emit('update:active', !this.active)
53
- this.$emit('change', !this.active)
54
- }
33
+ toggle: function() {
34
+ this.$emit('toggle', !this.active)
55
35
  }
56
36
  }
57
37
  }
58
38
  </script>
59
39
 
60
40
  <style scoped>
61
-
62
- .ps-switch {
63
- width: 46px;
41
+ .switch-button-control {
42
+ display: flex;
43
+ flex-direction: row;
44
+ align-items: center;
64
45
  }
65
- .ps-switch-small {
66
- width: 30px;
46
+ .switch-button-control .switch-button {
47
+ height: 24px;
48
+ width: calc(24px * 2);
49
+ background-color: #A2ACB7;
50
+ border: 2px solid #A2ACB7;
51
+ border-radius: 24px;
52
+ transition: all 0.3s ease-in-out;
53
+ cursor: pointer;
67
54
  }
68
-
69
- /*
70
- @TODO - Fix the apply error
71
- https://www.dropbox.com/s/83vwthcdvdt5t97/Screen%20Shot%202022-01-06%20at%2011.49.00%20AM.png?dl=0
72
- .toggle-bg:after {
73
- content: '';
74
- @apply psui-absolute psui-bg-white psui-border-gray-40 psui-rounded-full psui-h-5 psui-w-5 psui-transition;
55
+ .switch-button-control .switch-button-small {
56
+ height: 16px;
57
+ width: calc(16px * 2);
58
+ background-color: #A2ACB7;
59
+ border: 2px solid #A2ACB7;
60
+ border-radius: 16px;
61
+ transition: all 0.3s ease-in-out;
62
+ cursor: pointer;
75
63
  }
76
- .toggle-bg:after + .ps-switch-small {
77
- content: '';
78
- @apply psui-absolute psui-bg-white psui-border-gray-40 psui-rounded-full psui-h-2 psui-w-2 psui-transition;
64
+ .switch-button-control .switch-button .button {
65
+ height: calc(24px - (2 * 2px));
66
+ width: calc(24px - (2 * 2px));
67
+ border-radius: calc(24px - (2 * 2px));
68
+ background:#F3F6F9;
69
+ transition: all 0.3s ease-in-out;
79
70
  }
80
-
81
- input:checked + .toggle-bg:after + .ps-switch-small {
82
- transform: translateX(100%);
83
- position: absolute;
84
- left: 2px;
85
- @apply border-white;
71
+ .switch-button-control .switch-button-small .button {
72
+ height: calc(16px - (2 * 2px));
73
+ width: calc(16px - (2 * 2px));
74
+ border-radius: calc(16px - (2 * 2px));
75
+ background:#F3F6F9;
76
+ transition: all 0.3s ease-in-out;
86
77
  }
87
-
88
- input:checked + .toggle-bg:after {
89
- transform: translateX(100%);
90
- position: absolute;
91
- left: 4px;
92
- @apply border-white;
78
+ .switch-button-control .switch-button.enabled {
79
+ background-color: var(--color);
80
+ border: 2px solid var(--color);
93
81
  }
94
-
95
- input:checked + .toggle-bg {
96
- @apply psui-bg-green-20 psui-border-green-20;
97
- } */
98
- </style>
82
+ .switch-button-control .switch-button-small.enabled {
83
+ background-color: var(--color);
84
+ border: 2px solid var(--color);
85
+ }
86
+ .switch-button-control .switch-button.enabled .button {
87
+ background: white;
88
+ transform: translateX(calc(calc(24px - (2 * 2px)) + (2 *2px)));
89
+ }
90
+ .switch-button-control .switch-button-small.enabled .button {
91
+ background: white;
92
+ transform: translateX(calc(calc(16px - (2 * 2px)) + (2 *2px)));
93
+ }
94
+ .switch-button-control .switch-button-label {
95
+ margin-left: 10px;
96
+ }
97
+ </style>
@@ -1,10 +1,10 @@
1
1
  <template>
2
- <div class="table" :class="cssAlign">
2
+ <table :class='cssAlign' class='table psui-w-full psui-border-2 psui-border-gray-10' >
3
3
  <thead v-if="header">
4
4
  <th
5
5
  v-for="head in header"
6
6
  :key="head"
7
- :class="'psui-text-gray-80 psui-font-bold psui-bg-gray-10 psui-capitalize'"
7
+ class='psui-bg-gray-10 psui-text-gray-80 psui-capitalize psui-font-bold'
8
8
  >
9
9
  {{ head }}
10
10
  </th>
@@ -21,26 +21,26 @@
21
21
  <th
22
22
  v-for="ft in footer"
23
23
  :key="ft"
24
- :class="'psui-text-gray-80 psui-bg-gray-10'"
24
+ class='psui-bg-gray-10 psui-text-gray-80'
25
25
  >
26
26
  {{ ft }}
27
27
  </th>
28
28
  </tfoot>
29
- </div>
29
+ </table>
30
30
  </template>
31
31
 
32
32
  <script>
33
- export const type = ["simple", "rich"]
34
- export const alignment = ["center", "right", "left"]
33
+ export const type = ['simple', 'rich']
34
+ export const alignment = ['center', 'right', 'left']
35
35
 
36
36
  export default {
37
- name: "PsDataTable",
37
+ name: 'PsDataTable',
38
38
  props: {
39
39
  type: {
40
40
  type: String,
41
41
  required: true,
42
42
  validator: (value) => {
43
- return ["simple", "rich"].indexOf(value) !== -1
43
+ return ['simple', 'rich'].indexOf(value) !== -1
44
44
  },
45
45
  },
46
46
  header: {
@@ -49,45 +49,41 @@ export default {
49
49
  },
50
50
  data: {
51
51
  type: Array,
52
- default: () => {
53
- return []
54
- }
52
+ required: true
55
53
  },
56
54
  footer: {
57
55
  type: Array,
58
- default: () => {
59
- return []
60
- }
61
56
  },
62
57
  align: {
63
58
  type: String,
64
- default: "left",
59
+ default: 'left',
60
+ validator: (value) => {
61
+ return ['center', 'right', 'left'].indexOf(value) !== -1
62
+ }
65
63
  },
64
+ cssStyle: {
65
+ type: String,
66
+ default: 'psui-text-gray-60'
67
+ }
66
68
  },
67
69
  computed: {
68
70
  cssAlign() {
69
- if (this.align === "right") return "psui-text-right"
70
- if (this.align === "left") return "psui-text-left"
71
- return "psui-text-center"
71
+ if (this.align === 'right') return `psui-text-right ${this.cssStyle}`
72
+ if (this.align === 'center') return `psui-text-center ${this.cssStyle}`
73
+ return `psui-text-left ${this.cssStyle}`
72
74
  },
73
75
  },
74
76
  }
75
77
  </script>
76
78
 
77
- <style>
78
- .table {
79
- width: fit-content;
80
- border: 1px solid #e6ecf2;
81
- border-radius: 4px;
82
- }
79
+ <style scoped>
83
80
 
84
- th,
85
- td,
86
- tr {
81
+ .table th,
82
+ .table td,
83
+ .table tr {
87
84
  height: 40px;
88
85
  border: 1px solid #e6ecf2;
89
86
  padding: 11px 16px;
90
- font-weight: 400;
91
- color: #515e6a;
92
87
  }
88
+
93
89
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <tbody v-if="data">
3
- <tr v-for="(dt, index) in data" :key="index">
4
- <td v-for="(el, elIndex) in dt" :key="elIndex">
3
+ <tr v-for="(dt, index) in data" :key="index" >
4
+ <td v-for="(el, elIndex) in dt" :key="elIndex" class="psui-px-4 psui-py-2">
5
5
  <div class="psui-flex psui-gap-1 psui-items-center">
6
6
  <span class="psui-text-gray-80">
7
7
  {{ el[Object.keys(el)[1]].toFixed(3) }}
@@ -0,0 +1,79 @@
1
+ <template>
2
+ <PsTooltip :cssClass="getCssClass.content" :title="title">
3
+ <template v-slot:trigger>
4
+ <slot></slot>
5
+ </template>
6
+ <template
7
+ v-slot:dialog
8
+ class="psui-flex psui-fkex-col psui-gap-3 psui-items-start"
9
+ >
10
+ <p :class="type === 'white' ? 'psui-text-gray-50' : ''">{{ text }}</p>
11
+ <button
12
+ v-if="buttonText"
13
+ class="psui-py-2 psui-px-4 psui-rounded-md"
14
+ :class="getCssClass.button"
15
+ @click="onClick"
16
+ >
17
+ {{ buttonText }}
18
+ </button>
19
+ </template>
20
+ </PsTooltip>
21
+ </template>
22
+
23
+ <script>
24
+ import PsTooltip from "./PsTooltip.vue"
25
+
26
+ export default {
27
+ name: "PsDialogTooltip",
28
+ components: { PsTooltip },
29
+ props: {
30
+ text: {
31
+ type: String,
32
+ },
33
+ title: {
34
+ type: String,
35
+ },
36
+ buttonText: {
37
+ type: String,
38
+ },
39
+ type: {
40
+ type: String,
41
+ default: "white",
42
+ validator: (value) => ["white", "dark", "color"].includes(value),
43
+ },
44
+ cssClass: {
45
+ type: String,
46
+ required: false,
47
+ },
48
+ },
49
+ emits: ["click"],
50
+ computed: {
51
+ getCssClass() {
52
+
53
+ if (this.type === "dark")
54
+ return {
55
+ content: `psui-bg-blue-70 psui-text-white ${this.cssClass}`,
56
+ button: `psui-bg-blue-60 psui-text-white`,
57
+ }
58
+ if (this.type === "color")
59
+ return {
60
+ content: `psui-bg-blue-50 psui-text-white ${this.cssClass}`,
61
+ button: `psui-bg-blue-60 psui-text-white`,
62
+ }
63
+
64
+ return { content: `psui-bg-white psui-text-gray-80 ${this.cssClass}`, button: `psui-bg-blue-20 psui-text-blue-60`,}
65
+ },
66
+ },
67
+ methods: {
68
+ onClick() {
69
+ this.$emit("click")
70
+ },
71
+ },
72
+ }
73
+ </script>
74
+
75
+ <style scoped>
76
+ button {
77
+ width: fit-content;
78
+ }
79
+ </style>>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <PsTooltip :cssClass="`${textColorClass} ${cssClass}`" :title="title">
3
+ <template v-slot:trigger>
4
+ <slot></slot>
5
+ </template>
6
+ </PsTooltip>
7
+ </template>
8
+
9
+ <script>
10
+ import PsTooltip from "../tooltip/PsTooltip.vue"
11
+
12
+ export default {
13
+ name: "PsRichTooltip",
14
+ components: { PsTooltip },
15
+ props: {
16
+ title: {
17
+ type: String,
18
+ default: "",
19
+ },
20
+ type: {
21
+ type: String,
22
+ default: "gray",
23
+ validator: (type) => ["gray", "red", "blue"].includes(type),
24
+ },
25
+ cssClass: {
26
+ type: String,
27
+ default: "",
28
+ },
29
+ },
30
+ computed: {
31
+ textColorClass() {
32
+ if (this.type === "red") return `psui-text-red-70 psui-bg-red-10 `
33
+ if (this.type === "blue") return `psui-bg-blue-70 psui-text-white`
34
+ return `psui-text-gray-80 psui-bg-gray-30 `
35
+ },
36
+ },
37
+ }
38
+ </script>
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <div @mouseover="open" @mouseleave="close" ref="tooltip">
3
+ <div ref="tooltiptrigger">
4
+ <slot name="trigger"></slot>
5
+ </div>
6
+
7
+ <div class="psui-relative">
8
+ <div
9
+ role="menu"
10
+ ref="dialog"
11
+ class="
12
+ psui-fixed
13
+ psui-hidden
14
+ psui-opacity-0
15
+ psui-transition-opacity
16
+ psui-duration-500
17
+ psui-ease-in-out
18
+ "
19
+ >
20
+ <div
21
+ class="
22
+ psui-flex
23
+ psui-flex-col
24
+ psui-py-1
25
+ psui-px-2
26
+ psui-rounded-md
27
+ psui-shadow-md
28
+ psui-z-20
29
+ "
30
+ aria-orientation="vertical"
31
+ :class="cssClass"
32
+ >
33
+ <h2 v-if="title" class="psui-font-bold">{{ title}}</h2>
34
+ <slot name="dialog" class="psui-font-normal"
35
+ >
36
+ </slot
37
+ >
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </template>
43
+
44
+ <script>
45
+ export default {
46
+ name: "PsTooltip",
47
+ props: {
48
+ title: {
49
+ type: String,
50
+ },
51
+ ignoreDialog: {
52
+ type: Boolean,
53
+ default: false,
54
+ },
55
+ keepOpen: {
56
+ default: false,
57
+ },
58
+ cssClass:{
59
+ type: String,
60
+ default: 'psui-bg-gray-50 psui-text-white'
61
+ }
62
+ },
63
+ inheritAttrs: true,
64
+ emits: ["show"],
65
+ data() {
66
+ return {
67
+ show: false,
68
+ closingTimeout: null,
69
+ }
70
+ },
71
+ mounted() {
72
+ console.log(this.$attrs)
73
+ document.addEventListener("resize", this.updatePosition)
74
+ },
75
+ beforeDestroy() {
76
+ document.removeEventListener("resize", this.updatePosition)
77
+ },
78
+ methods: {
79
+ open() {
80
+ if (this.show || this.ignoreDialog) return
81
+ this.$emit("show")
82
+ this.show = true
83
+
84
+ this.$refs.dialog.style.display = "block"
85
+ this.$refs.dialog.style.opacity = 0
86
+
87
+ setTimeout(() => {
88
+ this.updatePosition()
89
+ }, 10)
90
+ },
91
+ close() {
92
+ if (this.show && this.$refs.dialog) {
93
+ this.$emit("close")
94
+ this.show = false
95
+
96
+ this.$refs.dialog.style.display = "none"
97
+ }
98
+ },
99
+ updatePosition() {
100
+ const dialog = this.$refs.dialog
101
+ const trigger = this.$refs.tooltiptrigger
102
+
103
+ const rectDialog = dialog.getBoundingClientRect()
104
+ const rectTrigger = trigger.getBoundingClientRect()
105
+ const windowWidth = document.documentElement.clientWidth
106
+ dialog.style.top = `${rectTrigger.y + rectTrigger.height}px`
107
+
108
+ if (rectTrigger.x + rectDialog.width + 20 > windowWidth) {
109
+ dialog.style.left = `${windowWidth - rectDialog.width - 30}px`
110
+ } else {
111
+ dialog.style.left = `${rectTrigger.x}px`
112
+ }
113
+
114
+ setTimeout(() => {
115
+ dialog.style.opacity = 100
116
+ }, 100)
117
+ },
118
+ },
119
+ }
120
+ </script>