@mouseless/baked 1.8.6 → 1.9.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/module.d.mts +5 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +5 -2
- package/dist/runtime/assets/components.css +2 -2
- package/dist/runtime/components/Check.d.vue.ts +13 -0
- package/dist/runtime/components/Check.vue +28 -0
- package/dist/runtime/components/Check.vue.d.ts +13 -0
- package/dist/runtime/components/Date.d.vue.ts +21 -0
- package/dist/runtime/components/Date.vue +41 -0
- package/dist/runtime/components/Date.vue.d.ts +21 -0
- package/dist/runtime/components/InputCheckbox.d.vue.ts +25 -0
- package/dist/runtime/components/InputCheckbox.vue +59 -0
- package/dist/runtime/components/InputCheckbox.vue.d.ts +25 -0
- package/dist/runtime/components/InputDate.d.vue.ts +25 -0
- package/dist/runtime/components/InputDate.vue +94 -0
- package/dist/runtime/components/InputDate.vue.d.ts +25 -0
- package/dist/runtime/components/InputMailAddress.d.vue.ts +25 -0
- package/dist/runtime/components/InputMailAddress.vue +49 -0
- package/dist/runtime/components/InputMailAddress.vue.d.ts +25 -0
- package/dist/runtime/components/InputMoney.d.vue.ts +25 -0
- package/dist/runtime/components/InputMoney.vue +53 -0
- package/dist/runtime/components/InputMoney.vue.d.ts +25 -0
- package/dist/runtime/components/InputRate.d.vue.ts +25 -0
- package/dist/runtime/components/InputRate.vue +86 -0
- package/dist/runtime/components/InputRate.vue.d.ts +25 -0
- package/dist/runtime/components/InputText.vue +1 -1
- package/dist/runtime/components/InputUrl.d.vue.ts +25 -0
- package/dist/runtime/components/InputUrl.vue +59 -0
- package/dist/runtime/components/InputUrl.vue.d.ts +25 -0
- package/dist/runtime/components/MissingComponent.vue +4 -4
- package/dist/runtime/components/MultiSelect.d.vue.ts +33 -0
- package/dist/runtime/components/MultiSelect.vue +98 -0
- package/dist/runtime/components/MultiSelect.vue.d.ts +33 -0
- package/dist/runtime/components/MultiSelectButton.d.vue.ts +33 -0
- package/dist/runtime/components/MultiSelectButton.vue +74 -0
- package/dist/runtime/components/MultiSelectButton.vue.d.ts +33 -0
- package/dist/runtime/components/NavLink.vue +13 -12
- package/dist/runtime/components/Select.vue +16 -39
- package/dist/runtime/components/SelectButton.vue +14 -37
- package/dist/runtime/components/TextLink.d.vue.ts +21 -0
- package/dist/runtime/components/TextLink.vue +43 -0
- package/dist/runtime/components/TextLink.vue.d.ts +21 -0
- package/dist/runtime/components/Textarea.d.vue.ts +25 -0
- package/dist/runtime/components/Textarea.vue +36 -0
- package/dist/runtime/components/Textarea.vue.d.ts +25 -0
- package/dist/runtime/composables/useInputValidator.d.ts +20 -0
- package/dist/runtime/composables/useInputValidator.js +111 -0
- package/dist/runtime/composables/useSelection.d.ts +13 -0
- package/dist/runtime/composables/useSelection.js +94 -0
- package/dist/runtime/composables/useToken.js +8 -2
- package/dist/types.d.mts +1 -1
- package/package.json +16 -15
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<AwaitLoading :skeleton="{ height: '1.5rem' }">
|
|
3
3
|
<div
|
|
4
4
|
v-if="data"
|
|
5
|
-
class="flex gap-
|
|
5
|
+
class="flex gap-1"
|
|
6
6
|
>
|
|
7
7
|
<Button
|
|
8
8
|
:icon
|
|
@@ -14,21 +14,22 @@
|
|
|
14
14
|
@mouseenter="openPopover"
|
|
15
15
|
@mouseleave="closePopover"
|
|
16
16
|
/>
|
|
17
|
-
<
|
|
17
|
+
<Button
|
|
18
18
|
v-if="summary"
|
|
19
|
-
class="
|
|
19
|
+
class="popover-icon hidden"
|
|
20
|
+
:class="popover?.visible && summaryShown ? 'text-yellow-500' : 'text-inherit'"
|
|
21
|
+
icon="pi pi-lightbulb"
|
|
22
|
+
size="small"
|
|
23
|
+
variant="text"
|
|
24
|
+
rounded
|
|
25
|
+
severity="secondary"
|
|
20
26
|
data-icon
|
|
21
27
|
@click="openPopover"
|
|
22
|
-
|
|
23
|
-
<i class="pi pi-eye" />
|
|
24
|
-
</span>
|
|
28
|
+
/>
|
|
25
29
|
<PersistentPopover
|
|
26
30
|
v-if="summary"
|
|
27
31
|
ref="popover"
|
|
28
|
-
class="
|
|
29
|
-
mx-4 max-w-96
|
|
30
|
-
max-md:w-[calc(100%-2rem)]
|
|
31
|
-
"
|
|
32
|
+
class="max-w-96 max-md:w-[65%]"
|
|
32
33
|
>
|
|
33
34
|
<Bake
|
|
34
35
|
v-if="summaryShown"
|
|
@@ -82,8 +83,8 @@ function openPopover(event) {
|
|
|
82
83
|
}
|
|
83
84
|
clearTimeout(loadPopoverTask);
|
|
84
85
|
clearTimeout(hidePopoverTask);
|
|
85
|
-
const target = event.target || event;
|
|
86
|
-
const onIcon =
|
|
86
|
+
const target = event.currentTarget || event.target || event;
|
|
87
|
+
const onIcon = target.dataset["icon"] !== void 0;
|
|
87
88
|
loadPopoverTask = setTimeout(
|
|
88
89
|
() => {
|
|
89
90
|
if (summaryShown.value) {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
v-model="selected"
|
|
16
16
|
:input-id="path"
|
|
17
17
|
:options="data"
|
|
18
|
+
:option-value
|
|
18
19
|
:placeholder
|
|
19
20
|
:show-clear
|
|
20
21
|
:filter
|
|
@@ -35,9 +36,8 @@
|
|
|
35
36
|
</template>
|
|
36
37
|
|
|
37
38
|
<script setup>
|
|
38
|
-
import { ref, watch } from "vue";
|
|
39
39
|
import { Select } from "primevue";
|
|
40
|
-
import { useContext, useUiStates, useLocalization } from "#imports";
|
|
40
|
+
import { useContext, useUiStates, useLocalization, useSelection } from "#imports";
|
|
41
41
|
import { AwaitLoading, Labeler, Validation } from "#components";
|
|
42
42
|
const context = useContext();
|
|
43
43
|
const { localize: l } = useLocalization();
|
|
@@ -47,50 +47,27 @@ const { schema, data } = defineProps({
|
|
|
47
47
|
data: { type: null, required: true }
|
|
48
48
|
});
|
|
49
49
|
const model = defineModel({ type: null, required: true });
|
|
50
|
-
const { filter, label, localizeOptionLabels, optionLabel, optionValue, showClear, stateful, targetProp } = schema;
|
|
50
|
+
const { autoSelectFirst, filter, label, localizeOptionLabels, optionLabel, optionValue, showClear, stateful, targetProp } = schema;
|
|
51
51
|
const path = context.injectPath();
|
|
52
|
-
const selected =
|
|
52
|
+
const { selected } = useSelection({
|
|
53
|
+
data,
|
|
54
|
+
model,
|
|
55
|
+
path,
|
|
56
|
+
stateStore: selectStates,
|
|
57
|
+
stateful,
|
|
58
|
+
targetProp,
|
|
59
|
+
autoSelectFirst,
|
|
60
|
+
optionValue,
|
|
61
|
+
mode: "single"
|
|
62
|
+
});
|
|
53
63
|
const placeholder = label?.text ? l(label.text) : null;
|
|
54
|
-
watch(
|
|
55
|
-
[() => data, getModel],
|
|
56
|
-
([_data, _model]) => {
|
|
57
|
-
if (!_data) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const value = stateful ? selectStates[path] ?? _model : _model;
|
|
61
|
-
setSelected(value);
|
|
62
|
-
},
|
|
63
|
-
{ immediate: true }
|
|
64
|
-
);
|
|
65
|
-
watch(selected, (newSelected) => setModel(newSelected));
|
|
66
64
|
function getOptionLabel(slotProps) {
|
|
67
65
|
const result = slotProps.option[optionLabel] ?? slotProps.option;
|
|
68
66
|
return localizeOptionLabels ? l(result) : result;
|
|
69
67
|
}
|
|
70
68
|
function getValueLabel(slotProps) {
|
|
71
|
-
const
|
|
69
|
+
const option = optionValue && slotProps.value != null ? data?.find((item) => item[optionValue] === slotProps.value) : slotProps.value;
|
|
70
|
+
const result = option?.[optionLabel] ?? option ?? placeholder;
|
|
72
71
|
return (localizeOptionLabels ? l(result) : result) ?? "\xA0";
|
|
73
72
|
}
|
|
74
|
-
function getModel() {
|
|
75
|
-
return targetProp ? model.value?.[targetProp] : model.value;
|
|
76
|
-
}
|
|
77
|
-
function setModel(selected2) {
|
|
78
|
-
const selectedValue = optionValue ? selected2?.[optionValue] : selected2;
|
|
79
|
-
if (stateful) {
|
|
80
|
-
selectStates[path] = selectedValue;
|
|
81
|
-
}
|
|
82
|
-
model.value = selectedValue ? targetProp ? { [targetProp]: selectedValue } : selectedValue : void 0;
|
|
83
|
-
}
|
|
84
|
-
function setSelected(value) {
|
|
85
|
-
if (!data) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
selected.value = optionValue ? data.filter((o) => o[optionValue] === value)[0] : value;
|
|
89
|
-
if (stateful) {
|
|
90
|
-
const selectedValue = optionValue ? selected.value?.[optionValue] : selected.value;
|
|
91
|
-
if (getModel() !== selectedValue) {
|
|
92
|
-
setModel(selected.value);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
73
|
</script>
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
:allow-empty
|
|
33
33
|
:data-key="optionValue"
|
|
34
34
|
:option-label
|
|
35
|
+
:option-value
|
|
35
36
|
class="!w-auto"
|
|
36
37
|
pt:pc-toggle-button:root="text-[length:inherit]"
|
|
37
38
|
>
|
|
@@ -45,9 +46,8 @@
|
|
|
45
46
|
</template>
|
|
46
47
|
|
|
47
48
|
<script setup>
|
|
48
|
-
import { ref, watch } from "vue";
|
|
49
49
|
import { SelectButton } from "primevue";
|
|
50
|
-
import { useContext, useLocalization, useUiStates } from "#imports";
|
|
50
|
+
import { useContext, useLocalization, useUiStates, useSelection } from "#imports";
|
|
51
51
|
import { AwaitLoading, Labeler, Validation } from "#components";
|
|
52
52
|
const context = useContext();
|
|
53
53
|
const { localize: l } = useLocalization();
|
|
@@ -59,6 +59,7 @@ const { schema, data } = defineProps({
|
|
|
59
59
|
const model = defineModel({ type: null, required: true });
|
|
60
60
|
const {
|
|
61
61
|
allowEmpty = false,
|
|
62
|
+
autoSelectFirst,
|
|
62
63
|
label,
|
|
63
64
|
localizeOptionLabels,
|
|
64
65
|
optionLabel,
|
|
@@ -67,43 +68,19 @@ const {
|
|
|
67
68
|
targetProp
|
|
68
69
|
} = schema;
|
|
69
70
|
const path = context.injectPath();
|
|
70
|
-
const selected =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
82
|
-
watch(selected, (newSelected) => setModel(newSelected));
|
|
71
|
+
const { selected } = useSelection({
|
|
72
|
+
data,
|
|
73
|
+
model,
|
|
74
|
+
path,
|
|
75
|
+
stateStore: selectButtonStates,
|
|
76
|
+
stateful,
|
|
77
|
+
targetProp,
|
|
78
|
+
autoSelectFirst,
|
|
79
|
+
optionValue,
|
|
80
|
+
mode: "single"
|
|
81
|
+
});
|
|
83
82
|
function getOptionLabel(slotProps) {
|
|
84
83
|
const result = slotProps.option[optionLabel] ?? slotProps.option;
|
|
85
84
|
return localizeOptionLabels ? l(result) : result;
|
|
86
85
|
}
|
|
87
|
-
function getModel() {
|
|
88
|
-
return targetProp ? model.value?.[targetProp] : model.value;
|
|
89
|
-
}
|
|
90
|
-
function setModel(selected2) {
|
|
91
|
-
const selectedValue = optionValue ? selected2?.[optionValue] : selected2;
|
|
92
|
-
if (stateful) {
|
|
93
|
-
selectButtonStates[path] = selectedValue;
|
|
94
|
-
}
|
|
95
|
-
model.value = selectedValue ? targetProp ? { [targetProp]: selectedValue } : selectedValue : void 0;
|
|
96
|
-
}
|
|
97
|
-
function setSelected(value) {
|
|
98
|
-
if (!data) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
selected.value = optionValue ? data.filter((o) => o[optionValue] === value)[0] : value;
|
|
102
|
-
if (stateful) {
|
|
103
|
-
const selectedValue = optionValue ? selected.value?.[optionValue] : selected.value;
|
|
104
|
-
if (getModel() !== selectedValue) {
|
|
105
|
-
setModel(selected.value);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
86
|
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
schema: {
|
|
5
|
+
type: null;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
data: {
|
|
9
|
+
type: null;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
13
|
+
schema: {
|
|
14
|
+
type: null;
|
|
15
|
+
required: true;
|
|
16
|
+
};
|
|
17
|
+
data: {
|
|
18
|
+
type: null;
|
|
19
|
+
required: true;
|
|
20
|
+
};
|
|
21
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<AwaitLoading :skeleton="{ height: '1.5rem' }">
|
|
3
|
+
<Button
|
|
4
|
+
v-if="rawData"
|
|
5
|
+
v-tooltip.bottom="tooltip"
|
|
6
|
+
:icon
|
|
7
|
+
icon-pos="right"
|
|
8
|
+
:label="text"
|
|
9
|
+
:href="rawData"
|
|
10
|
+
variant="link"
|
|
11
|
+
as="a"
|
|
12
|
+
target="_blank"
|
|
13
|
+
rel="noopener"
|
|
14
|
+
class="m-0 p-0 justify-start text-[length:inherit]"
|
|
15
|
+
/>
|
|
16
|
+
<span v-else>-</span>
|
|
17
|
+
</AwaitLoading>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import { computed } from "vue";
|
|
22
|
+
import { Button } from "primevue";
|
|
23
|
+
import { useFormat } from "#imports";
|
|
24
|
+
import { AwaitLoading } from "#components";
|
|
25
|
+
const { truncate } = useFormat();
|
|
26
|
+
const { schema, data: rawData } = defineProps({
|
|
27
|
+
schema: { type: null, required: true },
|
|
28
|
+
data: { type: null, required: true }
|
|
29
|
+
});
|
|
30
|
+
const { icon = "pi pi-external-link", maxLength = 50 } = schema;
|
|
31
|
+
const data = computed(() => rawData.includes("://") ? rawData.split("://")[1] : rawData);
|
|
32
|
+
const lengthIsExceeded = computed(() => maxLength && data.value.length > maxLength);
|
|
33
|
+
const text = computed(() => lengthIsExceeded.value ? truncate(data.value, maxLength) : data.value);
|
|
34
|
+
const tooltip = computed(() => ({
|
|
35
|
+
value: `${data.value}`,
|
|
36
|
+
disabled: !lengthIsExceeded.value,
|
|
37
|
+
pt: {
|
|
38
|
+
root: {
|
|
39
|
+
style: maxLength ? `min-width: ${maxLength / 4}rem;` : ""
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
schema: {
|
|
5
|
+
type: null;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
data: {
|
|
9
|
+
type: null;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
13
|
+
schema: {
|
|
14
|
+
type: null;
|
|
15
|
+
required: true;
|
|
16
|
+
};
|
|
17
|
+
data: {
|
|
18
|
+
type: null;
|
|
19
|
+
required: true;
|
|
20
|
+
};
|
|
21
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
schema: {
|
|
5
|
+
type: null;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
modelValue: {
|
|
9
|
+
type: import("vue").PropType<any>;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
"update:modelValue": (value: any) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
15
|
+
schema: {
|
|
16
|
+
type: null;
|
|
17
|
+
required: true;
|
|
18
|
+
};
|
|
19
|
+
modelValue: {
|
|
20
|
+
type: import("vue").PropType<any>;
|
|
21
|
+
required: true;
|
|
22
|
+
};
|
|
23
|
+
}>> & Readonly<{
|
|
24
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
25
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<AwaitLoading
|
|
3
|
+
:skeleton="{
|
|
4
|
+
height: label.mode === 'ifta' ? '10rem' : '9.6rem',
|
|
5
|
+
class: 'min-w-60'
|
|
6
|
+
}"
|
|
7
|
+
>
|
|
8
|
+
<Validation>
|
|
9
|
+
<Labeler
|
|
10
|
+
:label
|
|
11
|
+
:path
|
|
12
|
+
>
|
|
13
|
+
<Textarea
|
|
14
|
+
:id="path"
|
|
15
|
+
v-model="model"
|
|
16
|
+
v-bind="$attrs"
|
|
17
|
+
rows="5"
|
|
18
|
+
fluid
|
|
19
|
+
/>
|
|
20
|
+
</Labeler>
|
|
21
|
+
</Validation>
|
|
22
|
+
</AwaitLoading>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { Textarea } from "primevue";
|
|
27
|
+
import { useContext } from "#imports";
|
|
28
|
+
import { AwaitLoading, Labeler, Validation } from "#components";
|
|
29
|
+
const context = useContext();
|
|
30
|
+
const { schema } = defineProps({
|
|
31
|
+
schema: { type: null, required: true }
|
|
32
|
+
});
|
|
33
|
+
const model = defineModel({ type: null, required: true });
|
|
34
|
+
const { label } = schema;
|
|
35
|
+
const path = context.injectPath();
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
schema: {
|
|
5
|
+
type: null;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
modelValue: {
|
|
9
|
+
type: import("vue").PropType<any>;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
"update:modelValue": (value: any) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
15
|
+
schema: {
|
|
16
|
+
type: null;
|
|
17
|
+
required: true;
|
|
18
|
+
};
|
|
19
|
+
modelValue: {
|
|
20
|
+
type: import("vue").PropType<any>;
|
|
21
|
+
required: true;
|
|
22
|
+
};
|
|
23
|
+
}>> & Readonly<{
|
|
24
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
25
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default function _default(): {
|
|
2
|
+
date: {
|
|
3
|
+
message: any;
|
|
4
|
+
validate: (value: any, { silent }?: {
|
|
5
|
+
silent?: boolean | undefined;
|
|
6
|
+
}) => any;
|
|
7
|
+
};
|
|
8
|
+
mailAddress: {
|
|
9
|
+
message: any;
|
|
10
|
+
validate: (value: any, { silent }?: {
|
|
11
|
+
silent?: boolean | undefined;
|
|
12
|
+
}) => any;
|
|
13
|
+
};
|
|
14
|
+
url: {
|
|
15
|
+
message: any;
|
|
16
|
+
validate: (value: any, { silent }?: {
|
|
17
|
+
silent?: boolean | undefined;
|
|
18
|
+
}) => any;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useValidation, useLocalization } from "#imports";
|
|
2
|
+
|
|
3
|
+
export default function() {
|
|
4
|
+
const { localize: lc } = useLocalization({ group: "useInputValidator" });
|
|
5
|
+
const validation = useValidation();
|
|
6
|
+
|
|
7
|
+
const mutable = validation.injectMutable();
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
date: WithMutable(Date(lc), mutable),
|
|
11
|
+
mailAddress: WithMutable(MailAddress(lc), mutable),
|
|
12
|
+
url: WithMutable(Url(lc), mutable)
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function WithMutable(validator, mutable) {
|
|
17
|
+
function validate(value, { silent = false } = {}) {
|
|
18
|
+
const valid = validator.validate(value);
|
|
19
|
+
if(silent) { return valid; }
|
|
20
|
+
|
|
21
|
+
if(valid || !value) {
|
|
22
|
+
mutable.clear();
|
|
23
|
+
} else {
|
|
24
|
+
mutable.setError(validator.message);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return valid;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
message: validator.message,
|
|
32
|
+
validate
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function Date(lc) {
|
|
37
|
+
const message = lc("Invalid date");
|
|
38
|
+
|
|
39
|
+
function validate(value) {
|
|
40
|
+
if(value?.length != 8) { return false; }
|
|
41
|
+
if(isNaN(value)) { return false; }
|
|
42
|
+
|
|
43
|
+
const day = Number(value.slice(0, 2));
|
|
44
|
+
const month = Number(value.slice(2, 4));
|
|
45
|
+
const year = Number(value.slice(4, 8));
|
|
46
|
+
|
|
47
|
+
if(year < 1000 || year > 9999) { return false; }
|
|
48
|
+
if(month < 1 || month > 12) { return false; }
|
|
49
|
+
if(day < 1 || day > 31) { return false; }
|
|
50
|
+
|
|
51
|
+
// edge cases like Feb 30, Apr 31
|
|
52
|
+
const date = new globalThis.Date(year, month - 1, day);
|
|
53
|
+
|
|
54
|
+
return date.getFullYear() === year &&
|
|
55
|
+
date.getMonth() === month - 1 &&
|
|
56
|
+
date.getDate() === day;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
message,
|
|
61
|
+
validate
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function MailAddress(lc) {
|
|
66
|
+
const message = lc("Invalid e-mail address");
|
|
67
|
+
const regex = "/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]\\.[a-zA-Z]{2,}$/";
|
|
68
|
+
const parts = regex.match(/^\/(.*)\/([gimsuy]*)$/);
|
|
69
|
+
|
|
70
|
+
function validate(value) {
|
|
71
|
+
return new RegExp(parts[1], parts[2]).test(value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
message,
|
|
76
|
+
validate
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function Url(lc) {
|
|
81
|
+
const message = lc("Invalid URL");
|
|
82
|
+
|
|
83
|
+
function validate(value) {
|
|
84
|
+
// backend adds trailing "/" to absolute url when no query string -> account for that extra char
|
|
85
|
+
const effectiveLength = value?.length + (!value?.includes("?") && !value?.endsWith("/") ? 1 : 0);
|
|
86
|
+
if(effectiveLength > 255) { return false; }
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const url = new URL(value);
|
|
90
|
+
|
|
91
|
+
// don't accept whitespace on host part
|
|
92
|
+
if(url.host.includes("%20")) { return false; }
|
|
93
|
+
|
|
94
|
+
// "test.com." -> "test.com" -> ["test", "com"]
|
|
95
|
+
const parts = url.hostname.replace(/\.$/, "").split(".");
|
|
96
|
+
|
|
97
|
+
// "www.xxx" likely missing TLD -> require 3 parts when starts with www
|
|
98
|
+
const minParts = parts[0] === "www" ? 3 : 2;
|
|
99
|
+
|
|
100
|
+
// protocol must be http/https/ftp, TLD must be bigger than one character
|
|
101
|
+
return (url.protocol === "http:" || url.protocol === "https:" || url.protocol === "ftp:") &&
|
|
102
|
+
parts.length >= minParts &&
|
|
103
|
+
parts[parts.length - 1].length >= 2;
|
|
104
|
+
} catch { return false; }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
message,
|
|
109
|
+
validate
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default function useSelection({ data, model, path, stateStore, stateful, targetProp, optionValue, autoSelectFirst, mode }: {
|
|
2
|
+
data: any;
|
|
3
|
+
model: any;
|
|
4
|
+
path: any;
|
|
5
|
+
stateStore: any;
|
|
6
|
+
stateful: any;
|
|
7
|
+
targetProp: any;
|
|
8
|
+
optionValue: any;
|
|
9
|
+
autoSelectFirst: any;
|
|
10
|
+
mode?: string | undefined;
|
|
11
|
+
}): {
|
|
12
|
+
selected: import("vue").Ref<never[] | undefined, never[] | undefined>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ref, watch } from "vue";
|
|
2
|
+
|
|
3
|
+
export default function useSelection({
|
|
4
|
+
data,
|
|
5
|
+
model,
|
|
6
|
+
path,
|
|
7
|
+
stateStore,
|
|
8
|
+
stateful,
|
|
9
|
+
targetProp,
|
|
10
|
+
optionValue,
|
|
11
|
+
autoSelectFirst,
|
|
12
|
+
mode = "single"
|
|
13
|
+
}) {
|
|
14
|
+
const isMulti = mode === "multi";
|
|
15
|
+
const selected = ref(isMulti ? [] : undefined);
|
|
16
|
+
|
|
17
|
+
function getModel() {
|
|
18
|
+
if(isMulti) {
|
|
19
|
+
return targetProp
|
|
20
|
+
? model.value?.map(selection => selection[targetProp])
|
|
21
|
+
: model.value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return targetProp
|
|
25
|
+
? model.value?.[targetProp]
|
|
26
|
+
: model.value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function setModel(selected) {
|
|
30
|
+
let value = selected;
|
|
31
|
+
|
|
32
|
+
if(isMulti && !selected?.length) {
|
|
33
|
+
value = undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if(stateful) {
|
|
37
|
+
stateStore[path] = value;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if(isMulti) {
|
|
41
|
+
if(arrayEquals(value, getModel())) { return; }
|
|
42
|
+
|
|
43
|
+
model.value = value
|
|
44
|
+
? targetProp
|
|
45
|
+
? value.map(item => ({ [targetProp]: item }))
|
|
46
|
+
: value
|
|
47
|
+
: undefined;
|
|
48
|
+
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
model.value = value
|
|
53
|
+
? targetProp
|
|
54
|
+
? { [targetProp]: value }
|
|
55
|
+
: value
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
watch(
|
|
60
|
+
[() => data, getModel],
|
|
61
|
+
([_data, _model]) => {
|
|
62
|
+
if(!_data) { return; }
|
|
63
|
+
|
|
64
|
+
selected.value = stateful ? (stateStore[path] ?? _model) : _model ?? null;
|
|
65
|
+
|
|
66
|
+
if(!isMulti && autoSelectFirst && isEmpty(selected.value) && _data.length) {
|
|
67
|
+
selected.value = optionValue ? _data[0][optionValue] : _data[0];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if((stateful || autoSelectFirst) && !hasChanges(selected.value)) {
|
|
71
|
+
setModel(selected.value);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{ immediate: true }
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
watch(selected, setModel);
|
|
78
|
+
|
|
79
|
+
function isEmpty(value) {
|
|
80
|
+
return value === null || value === undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function arrayEquals(a, b) {
|
|
84
|
+
return a?.length === b?.length && a?.every((value, index) => value === b[index]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function hasChanges(value) {
|
|
88
|
+
return isMulti ? arrayEquals(value, getModel()) : value === getModel();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
selected
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useRuntimeConfig } from "#app";
|
|
2
2
|
import { createError, useMutex } from "#imports";
|
|
3
3
|
import { bfetch } from "../utils/bfetch.js";
|
|
4
|
+
import { Buffer } from "buffer";
|
|
4
5
|
|
|
5
6
|
export default function() {
|
|
6
7
|
const mutex = useMutex();
|
|
@@ -69,7 +70,7 @@ export default function() {
|
|
|
69
70
|
function decode(value) {
|
|
70
71
|
const { access } = JSON.parse(value);
|
|
71
72
|
|
|
72
|
-
return JSON.parse(
|
|
73
|
+
return JSON.parse(decodeBase64(access.split(".")[1]));
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
return {
|
|
@@ -94,7 +95,8 @@ function Token(tokenString) {
|
|
|
94
95
|
|
|
95
96
|
function isExpired(token) {
|
|
96
97
|
try {
|
|
97
|
-
const
|
|
98
|
+
const decoded = decodeBase64(token.split(".")[1]);
|
|
99
|
+
const claims = JSON.parse(decoded);
|
|
98
100
|
|
|
99
101
|
return parseInt(claims.exp) * 1000 < Date.now();
|
|
100
102
|
} catch {
|
|
@@ -110,3 +112,7 @@ function Token(tokenString) {
|
|
|
110
112
|
refreshIsExpired
|
|
111
113
|
};
|
|
112
114
|
}
|
|
115
|
+
|
|
116
|
+
function decodeBase64(value) {
|
|
117
|
+
return Buffer.from(value, "base64").toString("utf8");
|
|
118
|
+
}
|
package/dist/types.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default } from './module.mjs'
|
|
2
2
|
|
|
3
|
-
export { type CacheOptions, type Components, type Composables, type ModuleOptions, type NavLinkOptions, type PageOptions, type Plugins, type PrimeVueOptions, type RetryOptions, type ScreenOptions, type UseBreakpointsOptions, type UseDataFetcherOptions, type UseFormatOptions } from './module.mjs'
|
|
3
|
+
export { type CacheOptions, type Components, type Composables, type InputMoneyOptions, type ModuleOptions, type NavLinkOptions, type PageOptions, type Plugins, type PrimeVueOptions, type RetryOptions, type ScreenOptions, type UseBreakpointsOptions, type UseDataFetcherOptions, type UseFormatOptions } from './module.mjs'
|