@stonecrop/aform 0.12.8 → 0.13.0
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/dist/directives/mask.js +102 -0
- package/dist/index.js +31 -0
- package/dist/types/index.js +0 -0
- package/package.json +5 -5
- package/dist/theme/custom_themes.css +0 -6
- package/dist/theme/fields.css +0 -84
- package/dist/theme/login.css +0 -2
- package/dist/theme/purple_theme.css +0 -9
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts a mask function from a stringified function
|
|
3
|
+
* @param mask - Mask string
|
|
4
|
+
* @returns Mask function
|
|
5
|
+
*/
|
|
6
|
+
function extractMaskFn(mask) {
|
|
7
|
+
try {
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval, @typescript-eslint/no-unsafe-call
|
|
9
|
+
return Function(`"use strict";return (${mask})`)();
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
if (error instanceof ReferenceError) {
|
|
13
|
+
// assume mask is a string
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Gets the mask for a given directive binding
|
|
19
|
+
* @param binding - Binding object from directive hook
|
|
20
|
+
* @returns Mask string
|
|
21
|
+
*/
|
|
22
|
+
function getMask(binding) {
|
|
23
|
+
const mask = binding.value;
|
|
24
|
+
if (!mask)
|
|
25
|
+
return undefined;
|
|
26
|
+
const maskFn = extractMaskFn(mask);
|
|
27
|
+
if (maskFn) {
|
|
28
|
+
// TODO: (state) replace with state management;
|
|
29
|
+
// pass the entire form/table data to the function
|
|
30
|
+
const locale = binding.instance?.['locale'];
|
|
31
|
+
return maskFn(locale);
|
|
32
|
+
}
|
|
33
|
+
return mask;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Unmasks the input string
|
|
37
|
+
* @param input - Input string
|
|
38
|
+
* @param maskToken - Mask token character
|
|
39
|
+
* @returns Unmasked input string
|
|
40
|
+
*/
|
|
41
|
+
function unmaskInput(input, maskToken) {
|
|
42
|
+
if (!maskToken) {
|
|
43
|
+
maskToken = '#';
|
|
44
|
+
}
|
|
45
|
+
let unmaskedInput = input;
|
|
46
|
+
const maskChars = [maskToken, '/', '-', '(', ')', ' '];
|
|
47
|
+
for (const char of maskChars) {
|
|
48
|
+
unmaskedInput = unmaskedInput.replaceAll(char, '');
|
|
49
|
+
}
|
|
50
|
+
return unmaskedInput;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Fills the mask with the input string
|
|
54
|
+
* @param input - Input string
|
|
55
|
+
* @param mask - Mask string
|
|
56
|
+
* @param maskToken - Mask token character
|
|
57
|
+
* @returns Masked input string
|
|
58
|
+
*/
|
|
59
|
+
function fillMask(input, mask, maskToken) {
|
|
60
|
+
if (!maskToken) {
|
|
61
|
+
maskToken = '#';
|
|
62
|
+
}
|
|
63
|
+
let replacement = mask;
|
|
64
|
+
for (const inputChar of input) {
|
|
65
|
+
const replaceIndex = replacement.indexOf(maskToken);
|
|
66
|
+
if (replaceIndex !== -1) {
|
|
67
|
+
const prefix = replacement.substring(0, replaceIndex);
|
|
68
|
+
const suffix = replacement.substring(replaceIndex + 1);
|
|
69
|
+
replacement = prefix + inputChar + suffix;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return replacement.slice(0, mask.length);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Applies a mask to an input element
|
|
76
|
+
* @param el - Input element
|
|
77
|
+
* @param binding - Binding object from directive hook
|
|
78
|
+
* @returns void
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export function useStringMask(el, binding) {
|
|
82
|
+
const mask = getMask(binding);
|
|
83
|
+
if (!mask)
|
|
84
|
+
return;
|
|
85
|
+
const maskToken = '#';
|
|
86
|
+
const inputText = el.value;
|
|
87
|
+
// process input value with mask
|
|
88
|
+
const unmaskedInput = unmaskInput(inputText, maskToken);
|
|
89
|
+
if (unmaskedInput) {
|
|
90
|
+
const replacement = fillMask(unmaskedInput, mask, maskToken);
|
|
91
|
+
// TODO: (state) this is very opinionated;
|
|
92
|
+
// most likely fixed with state management;
|
|
93
|
+
// a better way could be to emit back to instance;
|
|
94
|
+
if (binding.instance?.['maskFilled']) {
|
|
95
|
+
binding.instance['maskFilled'] = !replacement.includes(maskToken);
|
|
96
|
+
}
|
|
97
|
+
el.value = replacement;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
el.value = mask;
|
|
101
|
+
}
|
|
102
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { install as installATable } from '@stonecrop/atable';
|
|
2
|
+
import ACheckbox from './components/form/ACheckbox.vue';
|
|
3
|
+
import AComboBox from './components/form/AComboBox.vue';
|
|
4
|
+
import ADate from './components/form/ADate.vue';
|
|
5
|
+
import ADropdown from './components/form/ADropdown.vue';
|
|
6
|
+
import ADatePicker from './components/form/ADatePicker.vue';
|
|
7
|
+
import AFieldset from './components/form/AFieldset.vue';
|
|
8
|
+
import AFileAttach from './components/form/AFileAttach.vue';
|
|
9
|
+
import AForm from './components/AForm.vue';
|
|
10
|
+
import ANumericInput from './components/form/ANumericInput.vue';
|
|
11
|
+
import ATextInput from './components/form/ATextInput.vue';
|
|
12
|
+
import Login from './components/utilities/Login.vue';
|
|
13
|
+
/**
|
|
14
|
+
* Install all AForm components
|
|
15
|
+
* @param app - Vue app instance
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
function install(app /* options */) {
|
|
19
|
+
app.use(installATable); // Install ATable components for use within AForm
|
|
20
|
+
app.component('ACheckbox', ACheckbox);
|
|
21
|
+
app.component('AComboBox', AComboBox);
|
|
22
|
+
app.component('ADate', ADate);
|
|
23
|
+
app.component('ADropdown', ADropdown);
|
|
24
|
+
app.component('ADatePicker', ADatePicker);
|
|
25
|
+
app.component('AFieldset', AFieldset);
|
|
26
|
+
app.component('AFileAttach', AFileAttach);
|
|
27
|
+
app.component('AForm', AForm);
|
|
28
|
+
app.component('ANumericInput', ANumericInput);
|
|
29
|
+
app.component('ATextInput', ATextInput);
|
|
30
|
+
}
|
|
31
|
+
export { ACheckbox, AComboBox, ADate, ADropdown, ADatePicker, AFieldset, AFileAttach, AForm, ANumericInput, ATextInput, Login, install, };
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/aform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@vueuse/core": "^14.2.1",
|
|
37
37
|
"@vueuse/components": "^14.2.1",
|
|
38
|
-
"@stonecrop/atable": "0.
|
|
39
|
-
"@stonecrop/schema": "0.
|
|
40
|
-
"@stonecrop/themes": "0.
|
|
41
|
-
"@stonecrop/utilities": "0.
|
|
38
|
+
"@stonecrop/atable": "0.13.0",
|
|
39
|
+
"@stonecrop/schema": "0.13.0",
|
|
40
|
+
"@stonecrop/themes": "0.13.0",
|
|
41
|
+
"@stonecrop/utilities": "0.13.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"pinia": "^3.0.4",
|
package/dist/theme/fields.css
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/* Styles for all types of fields: Text and Number Inputs, Radios, Checkboxes, etc. */
|
|
2
|
-
/* .form-element {
|
|
3
|
-
min-width: 40ch;
|
|
4
|
-
border: 1px solid transparent;
|
|
5
|
-
padding: 0;
|
|
6
|
-
margin: 0;
|
|
7
|
-
margin-right: 0.5rem;
|
|
8
|
-
margin-bottom: 0.5rem;
|
|
9
|
-
} */
|
|
10
|
-
/* .input-field {
|
|
11
|
-
outline: 1px solid transparent;
|
|
12
|
-
border: 1px solid var(--sc-input-border-color);
|
|
13
|
-
padding: 0.25rem;
|
|
14
|
-
margin: 0 0 0 0;
|
|
15
|
-
border-radius: 0 0 0.25rem 0.25rem;
|
|
16
|
-
box-sizing: border-box;
|
|
17
|
-
width: 100%;
|
|
18
|
-
}
|
|
19
|
-
.field-label {
|
|
20
|
-
color: var(--sc-input-label-color);
|
|
21
|
-
display: block;
|
|
22
|
-
min-height: 1.15rem;
|
|
23
|
-
padding: 0.25rem;
|
|
24
|
-
margin: 0rem;
|
|
25
|
-
z-index: 2;
|
|
26
|
-
font-size: 1rem;
|
|
27
|
-
font-weight: bold;
|
|
28
|
-
background: white;
|
|
29
|
-
width: 100%;
|
|
30
|
-
box-sizing: border-box;
|
|
31
|
-
background: var(--sc-gray-5);
|
|
32
|
-
border: 1px solid var(--sc-input-border-color);
|
|
33
|
-
border-bottom: none;
|
|
34
|
-
}
|
|
35
|
-
p.error {
|
|
36
|
-
display: block;
|
|
37
|
-
min-height: 1.15rem;
|
|
38
|
-
padding: 0rem;
|
|
39
|
-
padding-left: 0.5rem;
|
|
40
|
-
margin: 0.5rem 0 0.25rem 0rem;
|
|
41
|
-
border: 1px solid transparent;
|
|
42
|
-
width: 100%;
|
|
43
|
-
color: var(--sc-brand-danger);
|
|
44
|
-
font-size: 0.8rem;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.input-field:focus {
|
|
48
|
-
border: 1px solid var(--sc-input-active-border-color);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.input-field:focus + .field-label {
|
|
52
|
-
color: var(--sc-input-active-label-color);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** CHECKBOX **/
|
|
56
|
-
/* .checkbox {
|
|
57
|
-
visibility: hidden;
|
|
58
|
-
display: none;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.checkbox + .custom-checkbox:before {
|
|
62
|
-
content: '⬡';
|
|
63
|
-
font-size: 1.2rem;
|
|
64
|
-
cursor: pointer;
|
|
65
|
-
margin-right: 0.25rem;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.checkbox:checked + .custom-checkbox:before {
|
|
69
|
-
content: '⬣';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.custom-checkbox {
|
|
73
|
-
display: inline-block;
|
|
74
|
-
line-height: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.checkbox-container {
|
|
78
|
-
width: 100%;
|
|
79
|
-
display: inline-block;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.checkbox-container:hover + .field-label {
|
|
83
|
-
color: var(--sc-input-active-label-color);
|
|
84
|
-
} */
|
package/dist/theme/login.css
DELETED