classcard-ui 0.2.1541 → 0.2.1543

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": "classcard-ui",
3
- "version": "0.2.1541",
3
+ "version": "0.2.1543",
4
4
  "main": "dist/classcard-ui.umd.min.js",
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -2,8 +2,11 @@
2
2
  <div>
3
3
  <div class="flex items-center justify-between">
4
4
  <div class="flex items-center">
5
- <label v-if="label" class="block text-sm font-medium text-gray-900">
6
- {{ label }}
5
+ <label
6
+ v-if="label"
7
+ class="block text-sm font-medium text-gray-900"
8
+ v-html="formattedLabel"
9
+ >
7
10
  </label>
8
11
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
9
12
  </div>
@@ -94,6 +97,7 @@
94
97
  import { COLOR_CONFIG } from "../../colorConfig";
95
98
  import CIcon from "../CIcon/CIcon.vue";
96
99
  import VDatePicker from "v-calendar/lib/components/date-picker.umd";
100
+ import { linkifyText } from "../../helper.js";
97
101
  export default {
98
102
  name: "CDatepicker",
99
103
  components: {
@@ -221,6 +225,10 @@ export default {
221
225
  };
222
226
  },
223
227
  computed: {
228
+ // label with any URLs rendered as clickable links
229
+ formattedLabel() {
230
+ return linkifyText(this.label);
231
+ },
224
232
  computedStyles() {
225
233
  const colors = COLOR_CONFIG[this.preferredColor] || COLOR_CONFIG.indigo;
226
234
  return {
@@ -6,8 +6,8 @@
6
6
  <label
7
7
  :for="controlId"
8
8
  class="block text-sm font-medium text-gray-900"
9
+ v-html="formattedLabel"
9
10
  >
10
- {{ label }}
11
11
  </label>
12
12
  <!-- asterisk sign to render if field is required -->
13
13
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
@@ -104,6 +104,7 @@
104
104
  <script>
105
105
  import CIcon from "../CIcon/CIcon.vue";
106
106
  import CToolTip from "../CToolTip/CToolTip.vue";
107
+ import { linkifyText } from "../../helper.js";
107
108
  export default {
108
109
  name: "CInput",
109
110
  components: { CIcon, CToolTip },
@@ -202,6 +203,10 @@ export default {
202
203
  },
203
204
  },
204
205
  computed: {
206
+ // label with any URLs rendered as clickable links
207
+ formattedLabel() {
208
+ return linkifyText(this.label);
209
+ },
205
210
  // Use the id prop when the parent gives one. If not, make a stable id.
206
211
  // The stable id links the label to the input control.
207
212
  controlId() {
@@ -9,8 +9,8 @@
9
9
  <label
10
10
  :for="controlId"
11
11
  class="block text-sm font-medium text-gray-900"
12
+ v-html="formattedLabel"
12
13
  >
13
- {{ label }}
14
14
  </label>
15
15
  <!-- asterisk sign to render if field is required -->
16
16
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
@@ -200,6 +200,7 @@
200
200
 
201
201
  <script>
202
202
  import CIcon from "../CIcon/CIcon.vue";
203
+ import { linkifyText } from "../../helper.js";
203
204
  export default {
204
205
  name: "CInputAddon",
205
206
  components: { CIcon },
@@ -249,6 +250,10 @@ export default {
249
250
  },
250
251
  },
251
252
  computed: {
253
+ // label with any URLs rendered as clickable links
254
+ formattedLabel() {
255
+ return linkifyText(this.label);
256
+ },
252
257
  // Use the id prop when the parent gives one. If not, make a stable id.
253
258
  // The stable id links the label to the input control.
254
259
  controlId() {
@@ -7,8 +7,8 @@
7
7
  v-if="label"
8
8
  :for="controlId"
9
9
  class="block text-sm font-medium text-gray-900"
10
+ v-html="formattedLabel"
10
11
  >
11
- {{ label }}
12
12
  </label>
13
13
  <!-- asterisk sign to render if field is required -->
14
14
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
@@ -49,6 +49,7 @@
49
49
 
50
50
  <script>
51
51
  import CIcon from "../CIcon/CIcon.vue";
52
+ import { linkifyText } from "../../helper.js";
52
53
  export default {
53
54
  name: "CInputEmail",
54
55
  components: { CIcon },
@@ -91,6 +92,10 @@ export default {
91
92
  };
92
93
  },
93
94
  computed: {
95
+ // label with any URLs rendered as clickable links
96
+ formattedLabel() {
97
+ return linkifyText(this.label);
98
+ },
94
99
  // Use the id prop when the parent gives one. If not, make a stable id.
95
100
  // The stable id links the label to the input control.
96
101
  controlId() {
@@ -3,9 +3,11 @@
3
3
  <div class="mb-1 flex w-full items-center justify-between" v-if="label">
4
4
  <div class="flex items-center">
5
5
  <!-- label of multiselect field -->
6
- <label v-if="label" class="text-sm font-medium text-gray-900">{{
7
- label
8
- }}</label>
6
+ <label
7
+ v-if="label"
8
+ class="text-sm font-medium text-gray-900"
9
+ v-html="formattedLabel"
10
+ ></label>
9
11
  <!-- asterisk sign to render if field is required -->
10
12
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
11
13
  </div>
@@ -541,7 +543,7 @@ import CIcon from "../CIcon/CIcon.vue";
541
543
  import CCheckbox from "../CCheckbox/CCheckbox.vue";
542
544
  import { debounce } from "lodash-es";
543
545
  import "vue-select/dist/vue-select.css";
544
- import { getActionID } from "../../helper";
546
+ import { getActionID, linkifyText } from "../../helper";
545
547
  import CTag from "../CTag/CTag.vue";
546
548
  export default {
547
549
  name: "CMultiselect",
@@ -742,6 +744,10 @@ export default {
742
744
  },
743
745
  },
744
746
  computed: {
747
+ // label with any URLs rendered as clickable links
748
+ formattedLabel() {
749
+ return linkifyText(this.label);
750
+ },
745
751
  groupedArray() {
746
752
  const groups = {};
747
753
 
@@ -6,8 +6,8 @@
6
6
  <label
7
7
  class="text-sm text-gray-900"
8
8
  :class="[isBlock ? ' font-medium' : '']"
9
- >{{ label }}</label
10
- >
9
+ v-html="formattedLabel"
10
+ ></label>
11
11
  <!-- asterisk sign to render if field is required -->
12
12
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
13
13
  </div>
@@ -52,6 +52,7 @@
52
52
  <script>
53
53
  import { VueTelInput } from "vue-tel-input";
54
54
  import CIcon from "../CIcon/CIcon.vue";
55
+ import { linkifyText } from "../../helper.js";
55
56
  export default {
56
57
  name: "CPhoneNumber",
57
58
  components: {
@@ -123,6 +124,12 @@ export default {
123
124
  },
124
125
  };
125
126
  },
127
+ computed: {
128
+ // label with any URLs rendered as clickable links
129
+ formattedLabel() {
130
+ return linkifyText(this.label);
131
+ },
132
+ },
126
133
  methods: {
127
134
  handleBlur() {
128
135
  this.isFocused = false;
@@ -7,14 +7,13 @@
7
7
  <div
8
8
  v-for="(item, index) in items"
9
9
  :class="[
10
- 'relative first:rounded-t-md last:rounded-b-md',
10
+ 'relative cursor-pointer first:rounded-t-md last:rounded-b-md',
11
11
  index != items.length - 1
12
12
  ? useIncreasedPadding
13
13
  ? 'pb-6'
14
14
  : 'pb-4'
15
15
  : '',
16
16
  customClasses ? classes(item, index) : '',
17
- isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',
18
17
  ]"
19
18
  v-bind:key="item[labelName]"
20
19
  >
@@ -10,8 +10,8 @@
10
10
  <label
11
11
  :for="controlId"
12
12
  class="block text-sm font-medium text-gray-900"
13
+ v-html="formattedLabel"
13
14
  >
14
- {{ label }}
15
15
  </label>
16
16
  <!-- asterisk sign to render if field is required -->
17
17
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
@@ -629,7 +629,7 @@
629
629
  <script>
630
630
  import { isNumber, isEmpty } from "lodash-es";
631
631
  import CIcon from "../CIcon/CIcon.vue";
632
- import { getActionID } from "../../helper";
632
+ import { getActionID, linkifyText } from "../../helper";
633
633
  import CTag from "../CTag/CTag.vue";
634
634
  import CAvatar from "../CAvatar/CAvatar.vue";
635
635
  export default {
@@ -798,6 +798,10 @@ export default {
798
798
  };
799
799
  },
800
800
  computed: {
801
+ // label with any URLs rendered as clickable links
802
+ formattedLabel() {
803
+ return linkifyText(this.label);
804
+ },
801
805
  // Use the id prop when the parent gives one. If not, make a stable id.
802
806
  // The stable id links the label to the main trigger input.
803
807
  controlId() {
@@ -7,8 +7,8 @@
7
7
  v-if="label"
8
8
  :for="controlId"
9
9
  class="block text-sm font-medium text-gray-900"
10
+ v-html="formattedLabel"
10
11
  >
11
- {{ label }}
12
12
  </label>
13
13
  <!-- asterisk sign to render if field is required -->
14
14
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
@@ -46,6 +46,7 @@
46
46
  </template>
47
47
  <script>
48
48
  // import CIcon from "../CIcon/CIcon.vue";
49
+ import { linkifyText } from "../../helper.js";
49
50
  export default {
50
51
  name: "CTextarea",
51
52
  // components: { CIcon },
@@ -94,6 +95,10 @@ export default {
94
95
  },
95
96
  },
96
97
  computed: {
98
+ // label with any URLs rendered as clickable links
99
+ formattedLabel() {
100
+ return linkifyText(this.label);
101
+ },
97
102
  // Use the id prop when the parent gives one. If not, make a stable id.
98
103
  // The stable id links the label to the textarea control.
99
104
  controlId() {
@@ -3,9 +3,10 @@
3
3
  <div class="flex items-center justify-between">
4
4
  <div class="flex items-center">
5
5
  <!-- label of input field -->
6
- <label class="block text-sm font-medium text-gray-900">{{
7
- label
8
- }}</label>
6
+ <label
7
+ class="block text-sm font-medium text-gray-900"
8
+ v-html="formattedLabel"
9
+ ></label>
9
10
  <!-- asterisk sign to render if field is required -->
10
11
  <p v-if="isRequired" class="ml-1 text-red-600">*</p>
11
12
  </div>
@@ -109,6 +110,7 @@
109
110
  import * as filestack from "filestack-js";
110
111
  import CIcon from "../CIcon/CIcon.vue";
111
112
  import CAvatar from "../CAvatar/CAvatar.vue";
113
+ import { linkifyText } from "../../helper.js";
112
114
 
113
115
  export default {
114
116
  name: "CUpload",
@@ -308,6 +310,10 @@ export default {
308
310
  },
309
311
  },
310
312
  computed: {
313
+ // label with any URLs rendered as clickable links
314
+ formattedLabel() {
315
+ return linkifyText(this.label);
316
+ },
311
317
  errorClasses() {
312
318
  return {
313
319
  "border-red-300 text-red-900 placeholder-red-300 focus:ring-red-500 focus:border-red-500":
package/src/helper.js CHANGED
@@ -1,3 +1,22 @@
1
+ // Escapes HTML, then wraps any http(s) URL in a clickable anchor.
2
+ // Safe to bind with v-html because the source text is escaped first.
3
+ export const linkifyText = (text) => {
4
+ if (!text) {
5
+ return "";
6
+ }
7
+ const escaped = String(text)
8
+ .replace(/&/g, "&amp;")
9
+ .replace(/</g, "&lt;")
10
+ .replace(/>/g, "&gt;")
11
+ .replace(/"/g, "&quot;")
12
+ .replace(/'/g, "&#39;");
13
+ return escaped.replace(
14
+ /(https?:\/\/[^\s]+)/g,
15
+ (url) =>
16
+ `<a href="${url}" target="_blank" rel="noopener noreferrer" class="text-indigo-600 hover:underline">${url}</a>`
17
+ );
18
+ };
19
+
1
20
  export const getActionID = (name, id) => {
2
21
  if (name == null) {
3
22
  return "";
@@ -65,6 +65,14 @@ Default.args = {
65
65
  trailingIconClass: "h-5 w-5 text-gray-400",
66
66
  };
67
67
 
68
+ export const LabelWithLink = Template.bind({});
69
+ LabelWithLink.args = {
70
+ label: "I agree to the terms https://example.com/terms",
71
+ placeholder: "Enter your name",
72
+ isValidate: true,
73
+ type: "text",
74
+ };
75
+
68
76
  export const TrailingIcon = Template.bind({});
69
77
  TrailingIcon.args = {
70
78
  label: "Email",