@mixd-id/web-scaffold 0.1.230406144 → 0.1.230406146

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406144",
4
+ "version": "0.1.230406146",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -1,42 +1,47 @@
1
1
  <template>
2
2
  <Teleport to=".YWxl">
3
3
  <Transition name="alert-outer">
4
- <div v-if="!!state" :class="$style.alert" ref="alert">
4
+ <div v-if="isOpen" :class="$style.alert" ref="alert">
5
5
  <Transition name="alert" @after-appear="onAfterAppear" appear>
6
6
  <div :class="$style.cont1">
7
- <slot v-if="$slots['icon']" name="icon"></slot>
8
- <svg v-else-if="mode === 'alert'" width="100" height="100" class="fill-red-500" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
9
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12 13.75C12.4142 13.75 12.75 13.4142 12.75 13V8.00001C12.75 7.5858 12.4142 7.25001 12 7.25001C11.5858 7.25001 11.25 7.5858 11.25 8.00001V13C11.25 13.4142 11.5858 13.75 12 13.75Z"/>
10
- <path d="M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z"/>
11
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12 20.5C16.6944 20.5 20.5 16.6944 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 16.6944 7.30558 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>
12
- </svg>
13
- <svg v-else-if="mode === 'confirm'" width="100" height="100" class="fill-text-300" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
14
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12 13.75C12.4142 13.75 12.75 13.4142 12.75 13V8.00001C12.75 7.5858 12.4142 7.25001 12 7.25001C11.5858 7.25001 11.25 7.5858 11.25 8.00001V13C11.25 13.4142 11.5858 13.75 12 13.75Z"/>
15
- <path d="M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z"/>
16
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12 20.5C16.6944 20.5 20.5 16.6944 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 16.6944 7.30558 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>
17
- </svg>
18
7
 
19
8
  <div :class="$style.cont2">
9
+ <slot v-if="$slots['icon']" name="icon"></slot>
10
+ <svg width="100" height="100" class="fill-red-500" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
11
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 13.75C12.4142 13.75 12.75 13.4142 12.75 13V8.00001C12.75 7.5858 12.4142 7.25001 12 7.25001C11.5858 7.25001 11.25 7.5858 11.25 8.00001V13C11.25 13.4142 11.5858 13.75 12 13.75Z"/>
12
+ <path d="M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z"/>
13
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 20.5C16.6944 20.5 20.5 16.6944 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 16.6944 7.30558 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>
14
+ </svg>
20
15
  <h5 :class="$style.title">{{ title }}</h5>
21
- <p :class="$style.description">{{ description }}</p>
22
16
  </div>
23
17
 
24
- <div class="mt-4" v-if="mode === 'alert'">
25
- <Button ref="btnOK" @click="$emit('dismiss')" class="min-w-[88px]">
26
- <strong class="px-4">
27
- {{ text }}
28
- </strong>
29
- </Button>
18
+ <div :class="$style.details" v-if="message">
19
+ <p class="text-center whitespace-pre-line">{{ message }}</p>
20
+ </div>
21
+
22
+ <div :class="$style.details" v-if="details">
23
+ <div v-if="!showDetails" class="text-center">
24
+ <button type="button" class="text-primary" @click="showDetails = true">Open Details</button>
25
+ </div>
26
+ <div v-else class="flex flex-col gap-4">
27
+ <div v-for="(v, k) in details">
28
+ <small class="font-bold">{{ k }}</small>
29
+ <div class="block break-all text-sm">{{ v }}</div>
30
+ </div>
31
+
32
+ <div class="self-stretch text-center">
33
+ <button type="button" class="text-primary text-sm" @click="copy">Copy Details</button>
34
+ </div>
35
+ </div>
30
36
  </div>
31
- <div class="mt-4 flex flex-row gap-2" v-else-if="mode === 'confirm'">
32
- <Button ref="btnOK" @click="$emit('confirm')" class="min-w-[88px]" tabindex="0">
37
+
38
+ <div>
39
+ <br />
40
+ <Button ref="btnOK" @click="onConfirm">
33
41
  <strong class="px-4">
34
- {{ text }}
42
+ {{ buttonText }}
35
43
  </strong>
36
44
  </Button>
37
- <Button variant="minimal" @click="$emit('dismiss')" class="min-w-[88px] px-4 hover:text-primary">
38
- Cancel
39
- </Button>
40
45
  </div>
41
46
  </div>
42
47
  </Transition>
@@ -47,101 +52,104 @@
47
52
 
48
53
  <script>
49
54
 
55
+ import {copyToClipboard, unPascalCase} from "../utils/helpers.mjs";
56
+
50
57
  export default{
51
58
 
52
- props: {
59
+ methods: {
60
+
61
+ /**
62
+ * @param {object} obj - The alert object
63
+ * @param {string} [obj.title] - The title of the alert
64
+ * @param {string} obj.message - The message of the alert
65
+ * @param {string} [obj.buttonText] - The text of the button
66
+ * @param {function} [obj.onConfirm] - The callback function when the alert button is clicked
67
+ */
68
+ open(obj){
69
+ this.alert = obj
70
+ this.isOpen = true
71
+ this.showDetails = false
72
+ console.log('alert', this.alert)
73
+ },
53
74
 
54
- state: Object,
75
+ close(){
76
+ this.isOpen = false
77
+ },
55
78
 
56
- mode: {
57
- type: String,
58
- default: 'alert' // alert | confirm
79
+ copy(){
80
+ const text = []
81
+ for(let key in this.details){
82
+ text.push(`${key}\n${this.details[key]}\n\n`)
83
+ }
84
+ copyToClipboard(text.join("\n"))
59
85
  },
60
86
 
61
- text: {
62
- type: String,
63
- default: 'OK'
87
+ onAfterAppear(){
88
+ this.$refs.btnOK.focus()
89
+ this.$emit('appear')
64
90
  },
65
91
 
92
+ onConfirm(){
93
+ if(typeof this.alert.onConfirm === 'function'){
94
+ this.alert.onConfirm()
95
+ }
96
+ this.close()
97
+ }
98
+
66
99
  },
67
100
 
68
101
  computed: {
69
102
 
103
+ buttonText(){
104
+ return this.alert.buttonText ?? this.$t('OK')
105
+ },
106
+
70
107
  title(){
71
- let title
72
-
73
- if(this.state && this.state.title){
74
- if(typeof this.state.title === 'object'){
75
- if(this.state.title.response){
76
- title = this.state.title.response.data.message
77
- }
78
- else if(this.state.title.type === 'ValidationError'){
79
- title = 'Validation error'
80
- }
81
- else if(this.state.title.status){
82
- title = 'Error ' + this.state.title.status
83
- }
84
- else if(this.state.title.reason && this.state.title.reason.status){
85
- title = 'Error ' + this.state.title.reason.status
86
- }
87
- }
88
- else{
89
- title = this.state.title
90
- }
108
+ if(this.alert.title){
109
+ return this.alert.title
110
+ }
111
+ else if(this.alert.name){
112
+ return unPascalCase(this.alert.name)
113
+ }
114
+ else if(this.alert.type){
115
+ return unPascalCase(this.alert.type)
91
116
  }
117
+ else if(this.alert.status){
118
+ return `Error ${this.alert.status}`
119
+ }
120
+ else{
121
+ return this.$t('Alert')
122
+ }
123
+ },
92
124
 
93
- return title
125
+ message(){
126
+ return this.alert.message ?? ''
94
127
  },
95
128
 
96
- description(){
97
- let description
98
-
99
- if(this.state){
100
- if(typeof this.state.title === 'object'){
101
- if(this.state.title.response || this.state.title.type === 'ValidationError'){
102
- const errors = this.state.title.response ?
103
- this.state.title.response.data.errors :
104
- this.state.title.errors
105
-
106
- description = {}
107
- for(let key in errors){
108
- if(Array.isArray(errors[key])){
109
- errors[key].forEach((text) => {
110
- description[text] = 1
111
- })
112
- }
113
- else{
114
- errors[errors[key]] = 1
115
- }
116
- }
117
- description = Object.keys(description).join("\n")
118
- }
119
- else if(this.state.title.message){
120
- description = this.state.title.message
121
- }
122
- else if(this.state.title.reason && this.state.title.reason.message){
123
- description = this.state.title.reason.message
124
- }
125
- }
126
- else{
127
- description = this.state.description
129
+ details(){
130
+
131
+ if(this.alert.details && typeof this.alert.details === 'object'){
132
+ const details = {}
133
+ for(let key in this.alert.details){
134
+ if([ 'name', 'title', 'message' ].includes(key)) continue
135
+
136
+ details[key] = typeof this.alert.details[key] === 'object' ?
137
+ JSON.stringify(this.alert.details[key]) :
138
+ this.alert.details[key]
128
139
  }
140
+ return Object.keys(details).length > 0 ? details : null
129
141
  }
130
142
 
131
- return description
132
143
  }
133
144
 
134
145
  },
135
146
 
136
- emits: [ 'appear', 'confirm', 'dismiss' ],
137
-
138
- methods: {
139
-
140
- onAfterAppear(){
141
- this.$refs.btnOK.focus()
142
- this.$emit('appear')
147
+ data(){
148
+ return {
149
+ alert: {},
150
+ isOpen: false,
151
+ showDetails: false
143
152
  }
144
-
145
153
  }
146
154
 
147
155
  }
@@ -151,7 +159,7 @@ export default{
151
159
  <style module>
152
160
 
153
161
  .alert{
154
- @apply fixed top-0 left-0 flex w-screen h-screen px-8;
162
+ @apply fixed top-0 left-0 flex w-screen h-screen;
155
163
  @apply items-center justify-center bg-black/70 backdrop-blur-md;
156
164
  z-index: 60;
157
165
  }
@@ -163,27 +171,22 @@ export default{
163
171
  }
164
172
 
165
173
  .cont1{
166
- @apply p-4 flex flex-col items-center leading-6;
174
+ @apply flex flex-col items-center p-6 gap-1;
167
175
  }
168
176
 
169
177
  .cont2{
170
- @apply my-4 text-center flex-1 overflow-y-auto;
178
+ @apply flex flex-col items-center;
171
179
  }
172
180
 
173
181
  .title{
174
- @apply my-1 break-words whitespace-pre-line;
182
+ @apply whitespace-nowrap overflow-hidden;
175
183
  }
176
184
 
177
- .description{
178
- @apply overflow-y-auto whitespace-pre-line text-center;
179
- overflow-wrap: break-word;
180
- word-wrap: break-word;
181
- -ms-word-break: break-all;
182
- word-break: break-word;
183
- -ms-hyphens: auto;
184
- -moz-hyphens: auto;
185
- -webkit-hyphens: auto;
186
- hyphens: auto;
185
+ .details{
186
+ @apply flex-1 flex flex-col gap-4 overflow-y-auto min-h-[1.6rem];
187
+ }
188
+ .details::-webkit-scrollbar {
189
+ display: none;
187
190
  }
188
191
 
189
192
  </style>
@@ -0,0 +1,175 @@
1
+ <template>
2
+ <Teleport to=".YWxl">
3
+ <Transition name="confirm-outer">
4
+ <div v-if="isOpen" :class="$style.confirm" ref="confirm">
5
+ <Transition name="confirm" @after-appear="onAfterAppear" appear>
6
+ <div :class="$style.cont1">
7
+
8
+ <slot v-if="$slots['icon']" name="icon"></slot>
9
+ <svg width="100" height="100" class="fill-text-300" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
10
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 13.75C12.4142 13.75 12.75 13.4142 12.75 13V8.00001C12.75 7.5858 12.4142 7.25001 12 7.25001C11.5858 7.25001 11.25 7.5858 11.25 8.00001V13C11.25 13.4142 11.5858 13.75 12 13.75Z"/>
11
+ <path d="M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z"/>
12
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 20.5C16.6944 20.5 20.5 16.6944 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 16.6944 7.30558 20.5 12 20.5ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>
13
+ </svg>
14
+
15
+ <div :class="$style.cont2">
16
+ <h5 :class="$style.title">{{ title }}</h5>
17
+ <p :class="$style.description">{{ message }}</p>
18
+ </div>
19
+
20
+ <div class="mt-4 flex flex-row gap-2">
21
+ <Button ref="btnOK" @click="onConfirm" class="min-w-[88px]" tabindex="0">
22
+ <strong class="px-4">
23
+ {{ buttonText[0] }}
24
+ </strong>
25
+ </Button>
26
+ <Button variant="minimal" @click="onDismiss" class="min-w-[88px] px-4 hover:text-primary">
27
+ {{ buttonText[1] }}
28
+ </Button>
29
+ </div>
30
+
31
+ </div>
32
+ </Transition>
33
+ </div>
34
+ </Transition>
35
+ </Teleport>
36
+ </template>
37
+
38
+ <script>
39
+
40
+ export default{
41
+
42
+ methods: {
43
+
44
+ /**
45
+ * @param {object} obj - The confirm object
46
+ * @param {string} [obj.title] - The title of the confirm
47
+ * @param {string} obj.message - The message of the confirm
48
+ * @param {string[]} [obj.buttonText] - The text of the buttons
49
+ * @param {function} [obj.onConfirm] - The callback function when the confirm button is clicked
50
+ * @param {function} [obj.onDismiss] - The callback function when the dismiss button is clicked
51
+ */
52
+ open(obj){
53
+ this.confirm = obj
54
+ this.isOpen = true
55
+ },
56
+
57
+ close(){
58
+ this.isOpen = false
59
+ },
60
+
61
+ onAfterAppear(){
62
+ this.$refs.btnOK.focus()
63
+ this.$emit('appear')
64
+ },
65
+
66
+ onConfirm(){
67
+ if(typeof this.confirm.onConfirm === 'function'){
68
+ this.confirm.onConfirm()
69
+ }
70
+ this.close()
71
+ },
72
+
73
+ onDismiss(){
74
+ if(typeof this.confirm.onDismiss === 'function'){
75
+ this.confirm.onDismiss()
76
+ }
77
+ this.close()
78
+ },
79
+
80
+ },
81
+
82
+ computed: {
83
+
84
+ buttonText(){
85
+ return Array.isArray(this.confirm.buttonText) && this.confirm.buttonText.length === 2 ?
86
+ this.confirm.buttonText :
87
+ [ 'OK', 'Cancel' ]
88
+ },
89
+
90
+ title(){
91
+ return this.confirm.title ?? this.$t('Confirm')
92
+ },
93
+
94
+ message(){
95
+ return this.confirm.message ?? ''
96
+ },
97
+
98
+ },
99
+
100
+ data(){
101
+ return {
102
+ confirm: {},
103
+ isOpen: false
104
+ }
105
+ }
106
+
107
+ }
108
+
109
+ </script>
110
+
111
+ <style module>
112
+
113
+ .confirm{
114
+ @apply fixed top-0 left-0 flex w-screen h-screen px-8;
115
+ @apply items-center justify-center bg-black/70 backdrop-blur-md;
116
+ z-index: 60;
117
+ }
118
+
119
+ .confirm>*{
120
+ @apply max-h-[60vh] overflow-y-auto bg-base-500 rounded-xl;
121
+ @apply border-[1px] border-text-50;
122
+ @apply min-w-[280px] max-w-[80vw] md:max-w-[480px];
123
+ }
124
+
125
+ .cont1{
126
+ @apply p-4 flex flex-col items-center leading-6;
127
+ }
128
+
129
+ .cont2{
130
+ @apply my-4 text-center flex-1 overflow-y-auto;
131
+ }
132
+
133
+ .title{
134
+ @apply my-1 break-words whitespace-pre-line;
135
+ }
136
+
137
+ .description{
138
+ @apply overflow-y-auto whitespace-pre-line text-center;
139
+ overflow-wrap: break-word;
140
+ word-wrap: break-word;
141
+ -ms-word-break: break-all;
142
+ word-break: break-word;
143
+ -ms-hyphens: auto;
144
+ -moz-hyphens: auto;
145
+ -webkit-hyphens: auto;
146
+ hyphens: auto;
147
+ }
148
+
149
+ </style>
150
+
151
+ <style>
152
+
153
+ .confirm-outer-enter-active,
154
+ .confirm-outer-leave-active {
155
+ transition: opacity 100ms cubic-bezier(0.25, 1, 0.5, 1);
156
+ }
157
+
158
+ .confirm-outer-enter-from,
159
+ .confirm-outer-leave-to {
160
+ opacity: 0;
161
+ }
162
+
163
+ .confirm-enter-active,
164
+ .confirm-leave-active {
165
+ transition: all 300ms cubic-bezier(0.25, 1, 0.5, 1);
166
+ transform: translate3d(0, 0, 0);
167
+ }
168
+
169
+ .confirm-enter-from,
170
+ .confirm-leave-to {
171
+ transform: translate3d(0, 20px, 0);
172
+ opacity: 0;
173
+ }
174
+
175
+ </style>
package/src/index.js CHANGED
@@ -339,6 +339,7 @@ export default{
339
339
  app.component('Box', defineAsyncComponent(() => import("./components/Box.vue")))
340
340
  app.component('ChartBar', defineAsyncComponent(() => import("./components/ChartBar.vue")))
341
341
  app.component('ColorPicker', defineAsyncComponent(() => import("./components/ColorPicker.vue")))
342
+ app.component('Confirm', defineAsyncComponent(() => import("./components/Confirm.vue")))
342
343
  app.component('SearchButton', defineAsyncComponent(() => import("./components/SearchButton.vue")))
343
344
  app.component('ChatTyping', defineAsyncComponent(() => import("./components/ChatTyping.vue")))
344
345
  app.component('Checkbox', defineAsyncComponent(() => import("./components/Checkbox.vue")))
@@ -233,6 +233,10 @@ const getComponentUids = function(components, excepts = []){
233
233
  return arr
234
234
  }
235
235
 
236
+ const unPascalCase = function(str){
237
+ return str.replace(/([A-Z])/g, ' $1').trim()
238
+ }
239
+
236
240
  export {
237
241
  downsizeImage,
238
242
  uid,
@@ -246,6 +250,7 @@ export {
246
250
  _applyClass,
247
251
  copyToClipboard,
248
252
  getComponentUids,
253
+ unPascalCase
249
254
  }
250
255
 
251
256
  function observeInit(){