comand-component-library 3.1.66 → 3.1.67

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,6 +1,6 @@
1
1
  {
2
2
  "name": "comand-component-library",
3
- "version": "3.1.66",
3
+ "version": "3.1.67",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
package/src/App.vue CHANGED
@@ -418,7 +418,7 @@
418
418
  labelText="Label (inline) for inputfield (search) without search-button:"
419
419
  :displayLabelInline="true"
420
420
  type="search"
421
- id="inputfield-search"
421
+ id="inputfield-search-without-searchbutton"
422
422
  placeholder="Keyword(s)"
423
423
  v-model="inputSearch"
424
424
  :showSearchButton="false"
@@ -427,7 +427,7 @@
427
427
  labelText="Label (inline) for inputfield (search):"
428
428
  :displayLabelInline="true"
429
429
  type="search"
430
- id="inputfield-search"
430
+ id="inputfield-search-with-searchbutton"
431
431
  placeholder="Keyword(s)"
432
432
  v-model="inputSearch"
433
433
  :status="formElementStatus"/>
@@ -544,6 +544,24 @@
544
544
  :status="formElementStatus"/>
545
545
  </div>
546
546
  </div>
547
+ <CmdInputGroup labelText="Group label for radio group">
548
+ <CmdFormElement element="input"
549
+ labelText="Label for radiobutton"
550
+ type="radio"
551
+ id="input-group-radiobutton"
552
+ name="radiogroup2"
553
+ inputValue="radiobuttonValue1"
554
+ v-model="radiobuttonValue"
555
+ :status="formElementStatus"/>
556
+ <CmdFormElement element="input"
557
+ labelText="Label for radiobutton"
558
+ type="radio"
559
+ id="input-group-radiobutton"
560
+ name="radiogroup2"
561
+ inputValue="radiobuttonValue2"
562
+ v-model="radiobuttonValue"
563
+ :status="formElementStatus"/>
564
+ </CmdInputGroup>
547
565
  <CmdMultipleSwitch labelText="Label for multiple-switch with checkboxes:"
548
566
  :multipleSwitches="multipleSwitchCheckboxData"
549
567
  switchTypes="checkbox"
@@ -687,13 +705,13 @@
687
705
  <h3>Product boxes</h3>
688
706
  <div class="grid-container-create-columns">
689
707
  <div class="grid-small-item" v-for="(product, index) in boxProductData" :key="index">
690
- <CmdBox boxType="product" :product="product"/>
708
+ <CmdBox boxType="product" :product="product" :cmdCustomHeadline="{headlineLevel: 4}" />
691
709
  </div>
692
710
  </div>
693
711
  <h3>User boxes</h3>
694
712
  <div class="grid-container-create-columns">
695
713
  <div class="grid-small-item" v-for="(user, index) in boxUserData" :key="index">
696
- <CmdBox boxType="user" :user="user"/>
714
+ <CmdBox boxType="user" :user="user" :cmdCustomHeadline="{headlineLevel: 4}" />
697
715
  </div>
698
716
  </div>
699
717
  <h3>Box Site Search</h3>
@@ -863,19 +881,19 @@
863
881
  <h2 class="headline-demopage">Tabs</h2>
864
882
  <h3>Tabs with content from json-file</h3>
865
883
  <CmdTabs :stretchTabs="false" :tabs="tabsData"/>
866
- <h3>Tabs with HTML-content from used component</h3>
884
+ <h3>Tabs with HTML-content (given by slot))</h3>
867
885
  <CmdTabs :stretchTabs="true" :tabs="[{name: 'Tab 1'}, {name: 'Tab 2'}, {name: 'Tab 3'}]" :useSlot="true">
868
886
  <template v-slot:tab-content-0>
869
- <h3>Tab 1</h3>
887
+ <h4>Tab 1 headline</h4>
870
888
  <p>Content</p>
871
889
  </template>
872
890
  <template v-slot:tab-content-1>
873
- <h3>Tab 2</h3>
891
+ <h4>Tab 2</h4>
874
892
  <p>Content</p>
875
893
  <p>Content</p>
876
894
  </template>
877
895
  <template v-slot:tab-content-2>
878
- <h3>Tab 3</h3>
896
+ <h4>Tab 3</h4>
879
897
  <p>Content</p>
880
898
  <p>Content</p>
881
899
  <p>Content</p>
@@ -908,8 +926,7 @@
908
926
  <CmdWidthLimitationWrapper>
909
927
  <h2 class="headline-demopage">Upload-Form</h2>
910
928
  <h3>Simple mode</h3>
911
- <CmdUploadForm :cmdCustomHeadlineFieldset="{headlineText: 'Select files to upload', headlineLevel: 3}"
912
- :enableDragAndDrop="true"
929
+ <CmdUploadForm :enableDragAndDrop="true"
913
930
  :allowedFileExtensions="['jpg', 'png']"
914
931
  :allowMultipleFileUploads="true"
915
932
  :advancedMode="false"
@@ -918,7 +935,7 @@
918
935
  :uploadOptions="{url: 'http://localhost:8888'}"
919
936
  />
920
937
  <h3>Advanced mode</h3>
921
- <CmdUploadForm headline="Select files to upload"
938
+ <CmdUploadForm :cmdCustomHeadlineFieldset="{headlineText: 'Select files to upload', headlineLevel: 3}"
922
939
  :enableDragAndDrop="true"
923
940
  :allowedFileExtensions="['jpg', 'png']"
924
941
  :allowMultipleFileUploads="true"
@@ -1015,7 +1032,9 @@ import CmdFormFilters from "@/components/CmdFormFilters.vue"
1015
1032
  import CmdGoogleMaps from "./components/CmdGoogleMaps"
1016
1033
  import CmdImageGallery from "@/components/CmdImageGallery.vue"
1017
1034
  import CmdImageZoom from "@/components/CmdImageZoom.vue"
1035
+ import CmdInputGroup from "./components/CmdInputGroup"
1018
1036
  import CmdLoginForm from "@/components/CmdLoginForm.vue"
1037
+ import CmdListOfLinks from "./components/CmdListOfLinks"
1019
1038
  import CmdMainNavigation from "@/components/CmdMainNavigation.vue"
1020
1039
  import CmdMultipleSwitch from "@/components/CmdMultipleSwitch.vue"
1021
1040
  import CmdMultistepFormProgressBar from "@/components/CmdMultistepFormProgressBar.vue"
@@ -1038,7 +1057,6 @@ import {openFancyBox} from "@/components/CmdFancyBox"
1038
1057
 
1039
1058
  // import external functions
1040
1059
  import * as functions from "@/mixins/FieldValidation.js"
1041
- import CmdListOfLinks from "./components/CmdListOfLinks";
1042
1060
 
1043
1061
  export default {
1044
1062
  name: "App",
@@ -1062,6 +1080,7 @@ export default {
1062
1080
  CmdGoogleMaps,
1063
1081
  CmdImageGallery,
1064
1082
  CmdImageZoom,
1083
+ CmdInputGroup,
1065
1084
  CmdLoginForm,
1066
1085
  CmdMainNavigation,
1067
1086
  CmdMultistepFormProgressBar,
@@ -8,7 +8,6 @@
8
8
  "links": [
9
9
  {
10
10
  "path": "mailto:",
11
- "target": "",
12
11
  "iconClass": "icon-mail",
13
12
  "tooltip": "Send mail"
14
13
  }
@@ -22,7 +21,6 @@
22
21
  "links": [
23
22
  {
24
23
  "path": "mailto:",
25
- "target": "",
26
24
  "iconClass": "icon-mail",
27
25
  "tooltip": "Send mail"
28
26
  },
@@ -42,7 +40,6 @@
42
40
  "links": [
43
41
  {
44
42
  "path": "mailto:",
45
- "target": "",
46
43
  "iconClass": "icon-mail",
47
44
  "tooltip": "Send mail"
48
45
  },
@@ -54,7 +51,6 @@
54
51
  },
55
52
  {
56
53
  "path": "tel:",
57
- "target": "",
58
54
  "iconClass": "icon-phone",
59
55
  "tooltip": "Make call"
60
56
  }
@@ -68,7 +64,6 @@
68
64
  "links": [
69
65
  {
70
66
  "path": "mailto:",
71
- "target": "",
72
67
  "iconClass": "icon-mail",
73
68
  "tooltip": "Send mail"
74
69
  },
@@ -80,7 +75,6 @@
80
75
  },
81
76
  {
82
77
  "path": "tel:",
83
- "target": "",
84
78
  "iconClass": "icon-phone",
85
79
  "tooltip": "Make call"
86
80
  }
@@ -94,7 +88,6 @@
94
88
  "links": [
95
89
  {
96
90
  "path": "mailto:",
97
- "target": "",
98
91
  "iconClass": "icon-mail",
99
92
  "tooltip": "Send mail"
100
93
  },
@@ -106,7 +99,6 @@
106
99
  },
107
100
  {
108
101
  "path": "tel:",
109
- "target": "",
110
102
  "iconClass": "icon-phone",
111
103
  "tooltip": "Make call"
112
104
  }
@@ -1,17 +1,20 @@
1
1
  [
2
2
  {
3
3
  "name": "Tab 1",
4
- "headline": "Tab 1 Headline",
4
+ "headlineText": "Tab 1 Headline",
5
+ "headlineLevel": 4,
5
6
  "htmlContent": "<p>Inhalt 1</p>"
6
7
  },
7
8
  {
8
9
  "name": "Tab 2",
9
- "headline": "Tab 2 Headline",
10
+ "headlineText": "Tab 2 Headline",
11
+ "headlineLevel": 4,
10
12
  "htmlContent": "<p>Inhalt 2</p>"
11
13
  },
12
14
  {
13
15
  "name": "Tab 3",
14
- "headline": "Tab 3 Headline",
16
+ "headlineText": "Tab 3 Headline",
17
+ "headlineLevel": 4,
15
18
  "htmlContent": "<p>Inhalt 3</p>"
16
19
  }
17
20
  ]
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <div class="cmd-company-logo">
3
- <a v-if="link.type === 'router'" href="./" :title="link.tooltip">
4
- <img :src="pathCurrentLogo" :alt="altText"/>
5
- </a>
6
- <router-link v-else to="./" :title="link.tooltip">
3
+ <router-link v-if="link.type === 'router'" :href="link.path" :title="link.tooltip">
7
4
  <img :src="pathCurrentLogo" :alt="altText"/>
8
5
  </router-link>
6
+ <a v-else :to="link.path" :title="link.tooltip">
7
+ <img :src="pathCurrentLogo" :alt="altText"/>
8
+ </a>
9
9
  </div>
10
10
  </template>
11
11
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <header :class="['cmd-custom-headline', { 'has-pre-headline-text': preHeadlineText}]">
2
+ <div :class="['cmd-custom-headline', { 'has-pre-headline-text': preHeadlineText}]">
3
3
  <span v-if="iconClass" :class="iconClass"></span>
4
4
  <div v-if="preHeadlineText">
5
5
  <span class="pre-headline-text">{{ preHeadlineText }}</span>
@@ -10,7 +10,7 @@
10
10
  <component v-else :is="getHeadlineTag">
11
11
  <slot>{{ headlineText }}</slot>
12
12
  </component>
13
- </header>
13
+ </div>
14
14
  </template>
15
15
 
16
16
  <script>
@@ -22,7 +22,7 @@ export default {
22
22
  */
23
23
  headlineText: {
24
24
  type: String,
25
- required: true
25
+ required: false
26
26
  },
27
27
  /**
28
28
  * level for headline
@@ -8,13 +8,13 @@
8
8
  'has-state': validationStatus && validationStatus !== 'none'
9
9
  }
10
10
  ]"
11
- :aria-labelledby="labelText"
11
+ :aria-labelledby="labelId"
12
12
  :aria-required="$attrs.required !== undefined"
13
13
  ref="fakeselect"
14
14
  >
15
15
  <span v-if="showLabel">
16
16
  <!-- begin label -->
17
- <span>
17
+ <span :id="labelId">
18
18
  {{ labelText }}<sup v-if="$attrs.required !== undefined">*</sup>
19
19
  </span>
20
20
  <!-- end label -->
@@ -149,6 +149,9 @@
149
149
  </template>
150
150
 
151
151
  <script>
152
+ // import utils
153
+ import {createUuid} from "../utils/common.js"
154
+
152
155
  // import mixins
153
156
  import I18n from "../mixins/I18n"
154
157
  import DefaultMessageProperties from "../mixins/CmdBox/DefaultMessageProperties"
@@ -327,6 +330,13 @@ export default {
327
330
  },
328
331
  selectAllOptionsIcon() {
329
332
  return "icon-check"
333
+ },
334
+ // get ID for accessibility
335
+ labelId() {
336
+ if(this.$attrs.id !== undefined) {
337
+ return this.$attrs.id
338
+ }
339
+ return "label-" + createUuid()
330
340
  }
331
341
  },
332
342
  mounted() {
@@ -13,7 +13,7 @@
13
13
  off: colored && !isChecked,
14
14
  'has-state': validationStatus
15
15
  }]"
16
- :for="id"
16
+ :for="labelId"
17
17
  ref="label">
18
18
 
19
19
  <!-- begin label-text (+ required asterisk) -->
@@ -50,17 +50,17 @@
50
50
  <template
51
51
  v-if="element === 'input' && $attrs.type !== 'checkbox' && $attrs.type !== 'radio' && $attrs.type !== 'search'">
52
52
  <input v-bind="$attrs"
53
- :id="id"
53
+ :id="labelId"
54
54
  :class="htmlClass"
55
55
  @focus="tooltip = true"
56
56
  @blur="onBlur"
57
57
  @input="onInput"
58
58
  @mouseover="datalistFocus"
59
59
  @keyup="checkForCapsLock"
60
- :autocomplete="datalist ? 'off' : 'on'"
61
- :list="datalist ? datalist.id : false"
60
+ :autocomplete="autocomplete"
61
+ :list="datalist ? datalist.id : null"
62
62
  :value="modelValue"
63
- :maxlength="$attrs.maxlength > 0 ? $attrs.maxlength : 255"
63
+ :maxlength="getMaxLength()"
64
64
  ref="input"
65
65
  />
66
66
  </template>
@@ -92,27 +92,24 @@
92
92
  @change="onChange"
93
93
  @blur="onBlur"
94
94
  :checked="isChecked"
95
- :role="$attrs.type"
96
- :aria-checked="isChecked"
97
95
  :value="inputValue"
98
96
  :class="[htmlClass, validationStatus, { 'replace-input-type': replaceInputType, 'toggle-switch': toggleSwitch }]"
99
- :id="id"
97
+ :id="labelId"
100
98
  :aria-invalid="validationStatus === 'error'"
101
- :aria-describedby="`status-message-${id}`"
102
99
  />
103
-
104
- <!-- begin labels for toggle-switch -->
105
100
  <span v-if="!(onLabel && offLabel)" :class="{ hidden: !showLabel }">
106
101
  <span v-if="labelText">{{ labelText }}<sup v-if="$attrs.required">*</sup></span>
107
102
  </span>
103
+
104
+ <!-- begin labels for toggle-switch -->
108
105
  <template v-else-if="onLabel && offLabel">
109
106
  <span v-if="labelText">
110
107
  <span>{{ labelText }}<sup v-if="$attrs.required">*</sup></span>
111
108
  </span>
112
- <div class="toggle-switch switch-label">
109
+ <span class="toggle-switch switch-label">
113
110
  <span class="label">{{ onLabel }}</span>
114
111
  <span class="label">{{ offLabel }}</span>
115
- </div>
112
+ </span>
116
113
  </template>
117
114
  <slot v-else></slot>
118
115
  <!-- end labels for toggle-switch -->
@@ -122,7 +119,7 @@
122
119
  <!-- begin selectbox -->
123
120
  <select v-if="element === 'select'"
124
121
  v-bind="$attrs"
125
- :id="id"
122
+ :id="labelId"
126
123
  @blur="onBlur"
127
124
  @change="$emit('update:modelValue', $event.target.value)">
128
125
  <option v-for="(option, index) in selectOptions" :key="index" :value="option.value"
@@ -134,9 +131,9 @@
134
131
  <!-- begin textarea -->
135
132
  <textarea v-if="element === 'textarea'"
136
133
  v-bind="$attrs"
137
- :id="id"
134
+ :id="labelId"
138
135
  :value="modelValue"
139
- :maxlength="getMaxLength"
136
+ :maxlength="getMaxLength()"
140
137
  @input="onInput"
141
138
  @focus="tooltip = true"
142
139
  @blur="onBlur">
@@ -150,15 +147,15 @@
150
147
  <a v-if="iconDelete.show" href="#" @click.prevent="$emit('update:modelValue', '')" :class="iconDelete.iconClass" :title="iconDelete.tooltip"/>
151
148
  <input
152
149
  v-bind="$attrs"
153
- :id="id"
150
+ :id="labelId"
154
151
  @input="onInput"
155
152
  :maxlength="$attrs.maxlength > 0 ? $attrs.maxlength : 255"
156
153
  :value="modelValue"
157
154
  />
158
155
  </div>
159
- <button v-if="showSearchButton" class="no-flex" type="button" :title="iconSearch.tooltip">
156
+ <a v-if="showSearchButton" href="#" class="button no-flex" :title="iconSearch.tooltip" @click.prevent="executeSearch">
160
157
  <span :class="iconSearch.iconClass"></span>
161
- </button>
158
+ </a>
162
159
  </template>
163
160
  </label>
164
161
  <!-- end searchfield -->
@@ -215,6 +212,9 @@
215
212
  </template>
216
213
 
217
214
  <script>
215
+ // import utils
216
+ import {createUuid} from "../utils/common.js"
217
+
218
218
  // import mixins
219
219
  import I18n from "../mixins/I18n"
220
220
  import DefaultMessageProperties from "../mixins/CmdBox/DefaultMessageProperties"
@@ -631,6 +631,19 @@ export default {
631
631
  return this.getMessage("cmdformelement.validationTooltip.caps_lock_is_activated")
632
632
  }
633
633
  return this.getMessage("cmdformelement.validationTooltip.open_field_requirements")
634
+ },
635
+ autocomplete() {
636
+ if(this.$attrs.type !== 'file') {
637
+ return this.datalist ? 'off' : 'on'
638
+ }
639
+ return null
640
+ },
641
+ // get ID for accessibility
642
+ labelId() {
643
+ if(this.$attrs.id !== undefined) {
644
+ return this.$attrs.id
645
+ }
646
+ return "label-" + createUuid()
634
647
  }
635
648
  },
636
649
  methods: {
@@ -638,7 +651,15 @@ export default {
638
651
  return this.$refs.label
639
652
  },
640
653
  getMaxLength() {
641
- return this.$attrs.maxlength > 0 ? this.$attrs.maxlength : 5000
654
+ if (this.$attrs.element === 'textarea') {
655
+ return this.$attrs.maxlength > 0 ? this.$attrs.maxlength : 5000
656
+ }
657
+
658
+ if (this.$attrs.type !== 'file') {
659
+ return this.$attrs.maxlength > 0 ? this.$attrs.maxlength : 255
660
+ }
661
+
662
+ return null
642
663
  },
643
664
  onBlur(event) {
644
665
  // check if surrounding form with data-use-validation exists
@@ -711,6 +732,9 @@ export default {
711
732
  hidePassword() {
712
733
  this.$refs.input.nextElementSibling.classList.replace(this.iconPasswordInvisible.iconClass, this.iconPasswordVisible.iconClass)
713
734
  this.$refs.input.setAttribute("type", "password")
735
+ },
736
+ executeSearch() {
737
+ this.$emit("search", this.value)
714
738
  }
715
739
  },
716
740
  watch: {
@@ -25,7 +25,7 @@ export default {
25
25
  },
26
26
  props: {
27
27
  /**
28
- * list of all selected options
28
+ * model-value to support v-model
29
29
  */
30
30
  modelValue: {
31
31
  type: Array,
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div class="cmd-input-group">
3
+ <span :class="['label', { hidden: !showLabel, inline: labelInline }]">{{ labelText }}</span>
4
+ <div class="flex-container no-flex">
5
+ <slot></slot>
6
+ </div>
7
+ </div>
8
+ </template>
9
+
10
+ <script>
11
+ export default {
12
+ props: {
13
+ /**
14
+ * toggle label-text visibility
15
+ */
16
+ showLabel: {
17
+ type: Boolean,
18
+ default: true
19
+ },
20
+ /**
21
+ * label-text for input-group
22
+ *
23
+ * @requiredForAccessibility: true
24
+ */
25
+ labelText: {
26
+ type: String,
27
+ required: true
28
+ },
29
+ /**
30
+ * toggle label-position (inline/left of input-elements or above input-elements)
31
+ */
32
+ labelInline: {
33
+ type: Boolean,
34
+ default: false
35
+ }
36
+ }
37
+ }
38
+ </script>
@@ -16,7 +16,7 @@
16
16
  :name="cmdFormElementUsername.name"
17
17
  :id="cmdFormElementUsername.id"
18
18
  v-model="username"
19
- :inner-icon-class="cmdFormElementUsername.innerIconClass"
19
+ :fieldIconClass="cmdFormElementUsername.innerIconClass"
20
20
  :labelText="cmdFormElementUsername.labelText"
21
21
  :placeholder="cmdFormElementUsername.placeholder"
22
22
  />
@@ -28,7 +28,7 @@
28
28
  type="password"
29
29
  :name="cmdFormElementPassword.name"
30
30
  :id="cmdFormElementPassword.id"
31
- :inner-icon-class="cmdFormElementPassword.innerIconClass"
31
+ :fieldIconClass="cmdFormElementPassword.innerIconClass"
32
32
  v-model="password"
33
33
  :labelText="cmdFormElementPassword.labelText"
34
34
  :placeholder="cmdFormElementPassword.placeholder"
@@ -133,7 +133,7 @@
133
133
  <CmdFormElement
134
134
  element="input"
135
135
  type="email"
136
- :inner-icon-class="cmdFormElementSendLogin.innerIconClass"
136
+ :fieldIconClass="cmdFormElementSendLogin.innerIconClass"
137
137
  :labelText="cmdFormElementSendLogin.labelText"
138
138
  :placeholder="cmdFormElementSendLogin.placeholder"
139
139
  :name="cmdFormElementSendLogin.name"
@@ -11,6 +11,7 @@
11
11
  <script>
12
12
  export default {
13
13
  name: "CmdProgressBar",
14
+ inheritAttrs: false,
14
15
  data() {
15
16
  return {
16
17
  loadingStatus: 30
@@ -81,7 +81,7 @@ export default {
81
81
  z-index: 300;
82
82
  }
83
83
 
84
- header, .cmd-main-navigation nav, .cmd-top-header-navigation > ul {
84
+ header, .cmd-main-navigation nav, .cmd-list-of-links > ul {
85
85
  max-width: var(--max-width);
86
86
  margin: 0 auto;
87
87
  padding: 0 var(--default-padding);
@@ -92,6 +92,8 @@ export default {
92
92
  }
93
93
 
94
94
  header {
95
+ padding: calc(var(--default-padding) * 2) 0;
96
+
95
97
  &.flex-container {
96
98
  width: 100%;
97
99
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="cmd-tabs">
3
- <ul :class="{'stretch-tabs' : stretchTabs}">
3
+ <ul :class="{'stretch-tabs' : stretchTabs}" role="tablist">
4
4
  <li :class="{active : showTab === index}" v-for="(tab, index) in tabs" :key="index" role="tab">
5
5
  <a @click.prevent="setActiveTab(index)" :title="!tab.name ? tab.tooltip : false">
6
6
  <span v-if="tab.iconClass">{{ tab.iconClass }}</span>
@@ -212,7 +212,7 @@
212
212
  :labelText="getMessage('cmduploadform.labeltext.comment')"
213
213
  v-model="comment"
214
214
  :required="commentRequired"
215
- :statusMessage="commentStatusMessage"
215
+ :validationMessage="commentStatusMessage"
216
216
  :placeholder="getMessage('cmduploadform.placeholder.comment')"
217
217
  :status="commentStatusMessage ? 'error' : ''"
218
218
  />
@@ -157,7 +157,7 @@ export default {
157
157
  return this.getMessage("cmdfieldvalidation.information_filled_correctly")
158
158
  }
159
159
  }
160
- return ""
160
+ return null
161
161
  },
162
162
  getStatusIconClass() {
163
163
  if (this.validationStatus !== "") {
@@ -3,4 +3,13 @@ function isFrameMode() {
3
3
  return frameUrl.searchParams.has("frameMode")
4
4
  }
5
5
 
6
- export {isFrameMode}
6
+ function createUuid(){
7
+ let dt = new Date().getTime()
8
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
9
+ const r = (dt + Math.random() * 16) % 16 | 0
10
+ dt = Math.floor(dt / 16)
11
+ return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16)
12
+ })
13
+ }
14
+
15
+ export {isFrameMode, createUuid}