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

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 (43) hide show
  1. package/.storybook/main.js +9 -1
  2. package/dist/css/psui_styles.css +14742 -14620
  3. package/package.json +4 -1
  4. package/postcss.config.js +2 -0
  5. package/src/assets/scss/base.scss +5 -4
  6. package/src/assets/scss/components/PsInput.scss +89 -0
  7. package/src/components/accordion/PsAccordion.vue +18 -22
  8. package/src/components/accordion/PsAccordionItem.vue +5 -5
  9. package/src/components/badges-and-tags/PsChartLegend.vue +128 -0
  10. package/src/components/badges-and-tags/PsClimateZoneBadge.vue +18 -0
  11. package/src/components/badges-and-tags/PsCostEffectBar.vue +114 -0
  12. package/src/components/badges-and-tags/PsHighlightRippleDot.vue +78 -0
  13. package/src/components/badges-and-tags/PsMiniTag.vue +46 -0
  14. package/src/components/badges-and-tags/PsProgressBar.vue +0 -0
  15. package/src/components/buttons/PsButton.vue +1 -1
  16. package/src/components/chips/PsChips.vue +10 -20
  17. package/src/components/controls/PsCheckbox.vue +29 -16
  18. package/src/components/controls/PsDraggable.vue +171 -25
  19. package/src/components/controls/PsRadioButton.vue +25 -19
  20. package/src/components/forms/PsInput.vue +122 -102
  21. package/src/components/notifications/PsDialog.vue +37 -18
  22. package/src/components/tooltip/PsRichTooltip.vue +6 -0
  23. package/src/components/tooltip/PsTooltip.vue +1 -3
  24. package/src/index.js +9 -9
  25. package/src/stories/Accordion.stories.js +28 -22
  26. package/src/stories/ChartLegend.stories.js +16 -0
  27. package/src/stories/Chips.stories.js +7 -1
  28. package/src/stories/ClimateZoneBadge.stories.js +24 -0
  29. package/src/stories/Colors.stories.mdx +1 -1
  30. package/src/stories/CostEffectBar.stories.js +23 -0
  31. package/src/stories/Dialog.stories.js +141 -8
  32. package/src/stories/Draggable.stories.js +4 -6
  33. package/src/stories/Dropdown.stories.js +3 -5
  34. package/src/stories/HighlightRippleDot.stories.js +16 -0
  35. package/src/stories/Input.stories.js +36 -5
  36. package/src/stories/MiniTag.stories.js +46 -0
  37. package/src/stories/ProgressBar.stories.js +23 -0
  38. package/src/stories/RadioButton.stories.js +2 -2
  39. package/src/stories/Toggle.stories.js +7 -8
  40. package/src/stories/Tooltip.stories.js +5 -4
  41. package/src/util/GeneralFunctions.js +6 -7
  42. package/src/util/imageLoader.js +1 -1
  43. package/tailwind.config.js +72 -50
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@policystudio/policy-studio-ui-vue",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Policy Studio UI",
5
5
  "main": "src/index.js",
6
6
  "author": "Policy Studio Team",
@@ -26,6 +26,7 @@
26
26
  "@storybook/addon-actions": "^6.4.13",
27
27
  "@storybook/addon-essentials": "^6.4.13",
28
28
  "@storybook/addon-links": "^6.4.13",
29
+ "@storybook/addon-postcss": "^2.0.0",
29
30
  "@storybook/vue": "^6.4.13",
30
31
  "@vue/cli-plugin-babel": "~4.5.0",
31
32
  "@vue/cli-plugin-eslint": "~4.5.0",
@@ -38,6 +39,8 @@
38
39
  "eslint-plugin-vue": "^6.2.2",
39
40
  "postcss": "^8.3.11",
40
41
  "postcss-cli": "^9.0.2",
42
+ "postcss-import": "^14.0.2",
43
+ "postcss-nested": "^5.0.6",
41
44
  "prettier": "^2.2.1",
42
45
  "tailwindcss": "^1.9.6",
43
46
  "vue-loader": "^15.9.8",
package/postcss.config.js CHANGED
@@ -1,5 +1,7 @@
1
1
  module.exports = {
2
2
  plugins: {
3
+ 'postcss-nested': {},
4
+ "postcss-import": {},
3
5
  tailwindcss: {},
4
6
  autoprefixer: {},
5
7
  },
@@ -1,7 +1,8 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
1
  @import url('https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Round');
2
+ @import './components/PsInput.scss';
3
+ @import "tailwindcss/base";
4
+ @import "tailwindcss/components";
5
+ @import "tailwindcss/utilities";
5
6
 
6
7
  *:focus {
7
8
  outline: none;
@@ -9,4 +10,4 @@
9
10
  html {
10
11
  -webkit-font-smoothing: antialiased;
11
12
  -moz-osx-font-smoothing: grayscale;
12
- }
13
+ }
@@ -0,0 +1,89 @@
1
+ @layer components{
2
+
3
+ .psui-el-input {
4
+
5
+ input {
6
+ @apply psui-w-full psui-border psui-border-gray-30 psui-rounded-md psui-block
7
+ }
8
+
9
+ &-prepend {
10
+ @apply psui-absolute psui-inset-y-0 psui-left-0 psui-pl-2 psui-flex psui-items-center psui-pointer-events-none
11
+ }
12
+
13
+ &-append {
14
+ @apply psui-absolute psui-inset-y-0 psui-right-0 psui-pr-2 psui-flex psui-items-center
15
+ }
16
+
17
+ &-hint {
18
+ @apply psui-text-gray-50 psui-text-xsmall
19
+ }
20
+
21
+ &-wrapper {
22
+ @apply psui-relative;
23
+ &.hover input {
24
+ @apply psui-border-blue-50
25
+ }
26
+ }
27
+
28
+ label {
29
+ @apply psui-font-bold psui-text-gray-80
30
+ }
31
+
32
+ input {
33
+ @apply psui-bg-white psui-text-gray-60
34
+ }
35
+
36
+
37
+ /* Layout Default */
38
+ /* ----------------------------------------- */
39
+
40
+ &.layout-default {
41
+
42
+ input {
43
+ @apply psui-text-p;
44
+ padding: 11.5px 16px;
45
+ }
46
+
47
+ &.status-active {
48
+ input {
49
+ @apply psui-border-blue-60
50
+ }
51
+ }
52
+
53
+ &.status-error {
54
+ input {
55
+ @apply psui-border-red-20
56
+ }
57
+ &-hint {
58
+ @apply psui-text-red-20
59
+ }
60
+ }
61
+
62
+ &.status-disabled {
63
+
64
+ input {
65
+ @apply psui-bg-gray-20 psui-border-gray-20 psui-text-gray-40
66
+ }
67
+
68
+ label {
69
+ @apply psui-text-gray-40
70
+ }
71
+
72
+ }
73
+ }
74
+ /* ----------------------------------------- Layout Default */
75
+
76
+
77
+ /* Layout Mini */
78
+ /* ----------------------------------------- */
79
+ &.layout-mini {
80
+ input {
81
+ @apply psui-text-small;
82
+ padding: 7px 8px;
83
+ }
84
+ }
85
+ /* ----------------------------------------- Layout Mini */
86
+
87
+ }
88
+
89
+ }
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <div :class="classes" class='accordion' >
3
- <slot></slot>
2
+ <div :class="classes" class="accordion">
3
+ <slot></slot>
4
4
  </div>
5
5
  </template>
6
6
 
@@ -8,37 +8,33 @@
8
8
  export const sizes = ['big', 'medium']
9
9
 
10
10
  export default {
11
- name:"PsAccordion",
11
+ name: 'PsAccordion',
12
12
  props: {
13
- size:{
13
+ size: {
14
14
  type: String,
15
15
  default: 'medium',
16
- required: true
17
- }
16
+ required: true,
17
+ },
18
18
  },
19
- computed:{
20
- classes(){
21
- if( this.size === 'big') return 'big'
19
+ computed: {
20
+ classes() {
21
+ if (this.size === 'big') return 'big'
22
22
  return 'medium'
23
- }
24
- }
25
-
23
+ },
24
+ },
26
25
  }
27
26
  </script>
28
27
  <style scoped>
29
- .medium {
30
- width: 390px;
31
- }
28
+ .medium {
29
+ width: 390px;
30
+ }
32
31
 
33
- .big {
34
- width: 580px;
35
- }
32
+ .big {
33
+ width: 580px;
34
+ }
36
35
 
37
36
  .accordion {
38
37
  display: flex;
39
38
  flex-direction: column;
40
- border-right:1px solid #e6ecf2;
41
- border-left:1px solid #e6ecf2;
42
- border-top:1px solid #e6ecf2;
43
39
  }
44
- </style>
40
+ </style>
@@ -14,10 +14,10 @@
14
14
  >
15
15
  {{ title }}
16
16
  </div>
17
- <span v-if="!display" class="material-icons">{{ iconClass.closed }}</span>
18
- <span v-else :class="display ? 'selected' : ''" class="material-icons">{{
17
+ <i v-if="!display" class="material-icons">{{ iconClass.closed }}</i>
18
+ <i v-else :class="display ? 'selected' : ''" class="material-icons">{{
19
19
  iconClass.open
20
- }}</span>
20
+ }}</i>
21
21
  </div>
22
22
  <div v-if="display" class="psui-transition-all psui-duration-300">
23
23
  <slot></slot>
@@ -38,7 +38,6 @@ export default {
38
38
  },
39
39
  iconType: {
40
40
  type: String,
41
- required: true,
42
41
  default: "chevron",
43
42
  },
44
43
  fontCss: {
@@ -76,7 +75,8 @@ export default {
76
75
  <style scoped>
77
76
  .container {
78
77
  border-bottom: 1px solid #e6ecf2;
79
- padding: 16px;
78
+ padding-top: 16px;
79
+ padding-bottom: 16px;
80
80
  }
81
81
 
82
82
  span {
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div class="toView psui-flex psui-flex-row psui-p-8 psui-rounded">
3
+ <div class="container psui-p-2 psui-rounded">
4
+ <div class="psui-flex">
5
+ <div class="dot"></div>
6
+ <div class="text">{{ text }}</div>
7
+ </div>
8
+ <div class="container1">
9
+ <span v-if="this.value" :class="isValue">{{ value }}</span>
10
+ <span :class="isBar"></span>
11
+ <span :class="isPercentage">{{ percentage }}</span>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ props: {
20
+ text: {
21
+ type: String,
22
+ default: 'Climate Zone 10',
23
+ },
24
+ value: {
25
+ type: Number,
26
+ // required: true,
27
+ default: null,
28
+ },
29
+ percentage: {
30
+ type: String,
31
+ // required: true,
32
+ default: '',
33
+ },
34
+ },
35
+ computed: {
36
+ isValue() {
37
+ if (this.value) {
38
+ return 'value'
39
+ } else {
40
+ return 'hide'
41
+ }
42
+ },
43
+ isPercentage() {
44
+ if (this.percentage) {
45
+ return 'percentage'
46
+ } else {
47
+ return 'hide'
48
+ }
49
+ },
50
+ isBar() {
51
+ if (this.value !== 0 && this.percentage !== '') {
52
+ return 'bar'
53
+ } else {
54
+ return 'hide'
55
+ }
56
+ },
57
+ },
58
+ }
59
+ </script>
60
+
61
+ <style scoped>
62
+ .toView {
63
+ /* display: flex; */
64
+ /* flex-direction: row; */
65
+ /* padding: 32px; */
66
+
67
+ width: 351px;
68
+ height: 119px;
69
+
70
+ background: #f3ebfa;
71
+ border: 1.5px dashed #7b61ff;
72
+ /* border-radius: 5px; */
73
+ }
74
+
75
+ .container {
76
+ /* padding: 8px; */
77
+
78
+ width: fit-content;
79
+ height: fit-content;
80
+
81
+ background: #ffffff;
82
+ /* border-radius: 4px; */
83
+
84
+ /* margin: 0px 32px; */
85
+ }
86
+
87
+ .hide {
88
+ display: none;
89
+ }
90
+
91
+ .dot {
92
+ width: 14px;
93
+ height: 14px;
94
+ background: #43cec2;
95
+ border-radius: 8px;
96
+ margin: 0px 6px 0px 0px;
97
+ }
98
+
99
+ .text {
100
+ font-weight: bold;
101
+ font-size: 12px;
102
+ line-height: 120%;
103
+
104
+ color: #798490;
105
+ }
106
+
107
+ .container1 {
108
+ margin: 0px 0px 0px 20px;
109
+ }
110
+
111
+ .value {
112
+ color: #28323b;
113
+ }
114
+
115
+ .percentage {
116
+ color: #798490;
117
+ }
118
+
119
+ .bar {
120
+ background-color: #d6dde5;
121
+ height: 14px;
122
+
123
+ border-radius: 2px;
124
+
125
+ padding: 0px 1px;
126
+ margin-right: 3px;
127
+ }
128
+ </style>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <button
3
+ class="psui-flex psui-p-3 psui-bg-gray-10 psui-text-gray-50 hover:psui-text-blue-60 hover:psui-bg-blue-20 psui-transition-all psui-duration-300 psui-ease-out psui-shadow-lg psui-rounded"
4
+ >
5
+ <i v-if="icon" class="material-icons psui-text-base"> {{ icon }} </i>
6
+ <p class="psui-text-sm">10</p>
7
+ </button>
8
+ </template>
9
+
10
+ <script>
11
+ export default {
12
+ props: {
13
+ icon: {
14
+ type: String,
15
+ },
16
+ },
17
+ }
18
+ </script>
@@ -0,0 +1,114 @@
1
+ <template>
2
+ <div>
3
+ <div class="container">
4
+ <div
5
+ class="loading-bar"
6
+ :class="{
7
+ 'psui-bg-blue-20': value >= breakEven,
8
+ 'psui-bg-red-10': value < breakEven,
9
+ }"
10
+ >
11
+ <span class="breakEven" :style="breakEvenPosition"> </span>
12
+
13
+ <input
14
+ type="number"
15
+ min="0"
16
+ max="100"
17
+ class="percentage"
18
+ :style="{ width: `${value}px` }"
19
+ :class="{
20
+ 'psui-bg-blue-60': value >= breakEven,
21
+ 'psui-bg-red-20': value < breakEven,
22
+ }"
23
+ />
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </template>
28
+
29
+ <script>
30
+ export default {
31
+ props: {
32
+ value: {
33
+ type: Number,
34
+ required: true,
35
+ default: 0,
36
+ },
37
+ breakEven: {
38
+ type: Number,
39
+ required: true,
40
+ default: 1,
41
+ },
42
+ },
43
+ data() {
44
+ return {
45
+ errors: [],
46
+ }
47
+ },
48
+
49
+ computed: {
50
+ valueBar() {
51
+ if (this.value > 100) return 100
52
+ else if (this.value < 0) return 0
53
+ else return this.value
54
+ },
55
+
56
+ breakEvenPosition() {
57
+ return `left: ${this.breakEven}px`
58
+ },
59
+ getIsBreakEven() {
60
+ if (this.breakEven < 0) return 0
61
+ else if (this.breakEven > 100) return 100
62
+ else return this.breakEven
63
+ // else return true;
64
+ // return this.value > this.breakEven ? true : false;
65
+ },
66
+ },
67
+ }
68
+ </script>
69
+
70
+ <style scoped>
71
+ .container {
72
+ overflow: visible;
73
+ }
74
+
75
+ .loading-bar {
76
+ position: relative;
77
+ width: 100px;
78
+ height: 8px;
79
+ border-radius: 15px;
80
+ }
81
+
82
+ .loading-bar .percentage {
83
+ position: absolute;
84
+ display: block;
85
+ max-width: 100px;
86
+ height: 100%;
87
+ border-radius: 15px;
88
+ overflow: visible;
89
+ background-size: 30px 30px;
90
+ animation: animate-stripes 3s linear infinite;
91
+ }
92
+
93
+ .breakEven {
94
+ position: absolute;
95
+ background-color: #d6dde5;
96
+ width: 2px;
97
+ height: 14px;
98
+ /* max-width: 100px; */
99
+ border-radius: 2px;
100
+ top: -3px;
101
+ z-index: 1;
102
+ /* left: 2px; */
103
+ /* right: -2px; */
104
+ }
105
+
106
+ @keyframes animate-stripes {
107
+ 0% {
108
+ background-position: 0 0;
109
+ }
110
+ 100% {
111
+ background-position: 60px 0;
112
+ }
113
+ }
114
+ </style>
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <div class="example">
3
+ <div class="dot"></div>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {}
9
+ </script>
10
+
11
+ <style scoped>
12
+ .example {
13
+ position: static;
14
+ /* margin: 0px 32px; */
15
+ /* width: 275px;
16
+ height: 229px; */
17
+ /* left: 0px;
18
+ top: 0px; */
19
+ /* border: 1.5px dashed #9b51e0; */
20
+ /* background: #f3f6f9; */
21
+ box-sizing: border-box;
22
+ }
23
+ .dot {
24
+ background: #5db883;
25
+ /* border: solid 1px #2bb24c; */
26
+ border-radius: 50%;
27
+ /* box-shadow: 0px 0 2px #2bb24c; */
28
+ width: 8px;
29
+ height: 8px;
30
+ /* left: 6px;
31
+ top: 6px; */
32
+ margin: 100px auto;
33
+ position: relative;
34
+ }
35
+
36
+ .dot::before,
37
+ .dot::after {
38
+ background: #def8e8;
39
+ border: solid 0px #2bb24c;
40
+ border-radius: 50%;
41
+ content: '';
42
+ width: 36px;
43
+ height: 36px;
44
+ left: -8px;
45
+ top: -8px;
46
+ position: absolute;
47
+ transform-origin: center center;
48
+ transform: scale(1) translate(-1px, -1px);
49
+ }
50
+ .dot::before {
51
+ animation: ripple 1s infinite;
52
+ }
53
+ .dot::after {
54
+ animation: ripple 1s infinite;
55
+ /* animation-delay: 0.4s; */
56
+ }
57
+
58
+ @keyframes ripple {
59
+ 0% {
60
+ /* transform: scale(1) translate(-1px, -1px);
61
+ opacity: 0.75; */
62
+ left: 5px;
63
+ top: 5px;
64
+ opacity: 0.95;
65
+ width: 0;
66
+ height: 0;
67
+ }
68
+ 100% {
69
+ /* transform: scale(2) translate(-1px, -1px);
70
+ opacity: 0; */
71
+ left: -13px;
72
+ top: -13px;
73
+ opacity: 0;
74
+ width: 36px;
75
+ height: 36px;
76
+ }
77
+ }
78
+ </style>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <div :class="cssClass">
3
+ <div class="psui-w-full">{{ message }}</div>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export const typeOptions = ['informative', 'success', 'warning', 'error']
9
+ export default {
10
+ name: 'PsMiniTag',
11
+ props: {
12
+ type: {
13
+ type: String,
14
+ default: 'informative',
15
+ validator: (value) => typeOptions.indexOf(value) !== -1,
16
+ },
17
+ message: {
18
+ type: String,
19
+ required: true,
20
+ },
21
+ },
22
+ data() {
23
+ return {
24
+ colors: {
25
+ informative: { background: 'blue-20', color: 'blue-60' },
26
+ success: { background: 'green-10', color: 'green-70' },
27
+ warning: { background: 'yellow-10', color: 'yellow-70' },
28
+ error: { background: 'red-10', color: 'red-20' },
29
+ },
30
+ }
31
+ },
32
+ computed: {
33
+ cssClass() {
34
+ return `fit-content psui-flex psui-rounded-lg psui-px-2 psui-items-center psui-justify-center psui-flex-row psui-mx-6 psui-bg-${
35
+ this.colors[this.type].background
36
+ } psui-text-${this.colors[this.type].color}`
37
+ },
38
+ },
39
+ }
40
+ </script>
41
+
42
+ <style scoped>
43
+ .fit-content {
44
+ width: fit-content;
45
+ }
46
+ </style>
@@ -126,4 +126,4 @@ export default {
126
126
  padding: 9.5px 16px 9.5px 16px;
127
127
  font-size: 16px;
128
128
  }
129
- </style>
129
+ </style>
@@ -2,7 +2,7 @@
2
2
  <label
3
3
  @click="onClick"
4
4
  :for="title"
5
- :class="cssClass"
5
+ :class="getCssClass"
6
6
  class="
7
7
  psui-flex
8
8
  psui-gap-2
@@ -42,6 +42,7 @@ export default {
42
42
  type: {
43
43
  type: String,
44
44
  required: true,
45
+ validator: (type) => ["text", "radio", "checkbox", "button"].includes(type)
45
46
  },
46
47
  icon: {
47
48
  type: String,
@@ -53,28 +54,20 @@ export default {
53
54
  },
54
55
  checked: {
55
56
  type: Boolean,
57
+ default: false
56
58
  },
57
59
  },
58
60
  emits: ["click", "change"],
59
61
  data() {
60
62
  return {
61
63
  isChecked: false,
62
- value: null,
63
64
  }
64
65
  },
65
66
  computed: {
66
- cssClass() {
67
+ getCssClass() {
67
68
  let cssClass = ''
68
69
 
69
- if (this.isChecked === true && this.type === "radio") {
70
- cssClass = "psui-text-blue-50 psui-bg-blue-20"
71
- }
72
-
73
- if (this.isChecked === true && this.type === "checkbox") {
74
- cssClass = "psui-text-blue-50 psui-bg-blue-20"
75
- }
76
-
77
- if (this.isChecked === true) {
70
+ if (this.checked === true ) {
78
71
  cssClass = "psui-text-blue-50 psui-bg-blue-20"
79
72
  }
80
73
 
@@ -83,18 +76,15 @@ export default {
83
76
  },
84
77
  methods: {
85
78
  onClick() {
86
- if (this.disabled) return false
87
-
88
- if (this.type !== "checkbox" || this.type !== "radio") {
89
- this.isChecked = !this.isChecked
90
- }
91
-
79
+ this.isChecked = !this.isChecked
92
80
  this.$emit("click")
93
81
  },
94
82
  onChange(event) {
83
+
95
84
  this.isChecked = event.target.checked
96
- this.checked = event.target.checked
97
- this.$emit("change", event.target.checked)
85
+
86
+ this.$emit('update:checked', event.target.checked)
87
+ this.$emit("change")
98
88
  },
99
89
  onClose() {
100
90
  this.$emit("close")