@ramathibodi/nuxt-commons 0.1.42 → 0.1.43
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.json +1 -1
- package/dist/runtime/components/document/TemplateBuilder.vue +3 -2
- package/dist/runtime/components/form/CheckboxGroup.vue +90 -0
- package/dist/runtime/components/form/Date.vue +44 -37
- package/dist/runtime/components/form/DateTime.vue +40 -34
- package/dist/runtime/components/form/Time.vue +42 -36
- package/dist/runtime/composables/document/template.js +8 -1
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -138,6 +138,7 @@ const inputTypeChoice = ref([
|
|
|
138
138
|
{ label: 'Radio Buttons', value: 'VRadio' },
|
|
139
139
|
{ label: 'Radio Buttons Inline', value: 'VRadioInline' },
|
|
140
140
|
{ label: 'Checkbox', value: 'VCheckbox' },
|
|
141
|
+
{ label: 'Checkbox Group', value: 'FormCheckboxGroup' },
|
|
141
142
|
{ label: 'Switch', value: 'VSwitch' },
|
|
142
143
|
{ label: 'File Upload', value: 'FormFile' },
|
|
143
144
|
{ label: 'Signature Pad', value: 'FormSignPad' },
|
|
@@ -149,7 +150,7 @@ const inputTypeChoice = ref([
|
|
|
149
150
|
{ label: '[Advanced] Custom Code', value: 'CustomCode' },
|
|
150
151
|
]);
|
|
151
152
|
|
|
152
|
-
const requireOption = ref(['VSelect', 'VAutocomplete', 'VCombobox', 'VRadio', 'VRadioInline', 'MasterAutocomplete','FormTable','DocumentForm'])
|
|
153
|
+
const requireOption = ref(['VSelect', 'VAutocomplete', 'VCombobox', 'VRadio', 'VRadioInline', 'MasterAutocomplete','FormTable','DocumentForm','FormCheckboxGroup'])
|
|
153
154
|
const notRequireVariable = ref(['Header', 'Separator', 'CustomCode','DocumentForm'])
|
|
154
155
|
const notRequireLabel = ref(['Separator', 'CustomCode', 'FormFile', 'FormHidden','DocumentForm'])
|
|
155
156
|
const notRequireWidth = ref(['Separator', 'FormHidden','DocumentForm'])
|
|
@@ -161,7 +162,7 @@ const notRequireAdvancedSetting = ref(['Separator','CustomCode', 'FormHidden'])
|
|
|
161
162
|
|
|
162
163
|
const hasSpecificOption = ref(['FormHidden','FormTable'])
|
|
163
164
|
|
|
164
|
-
const choiceOption = ref(['VRadio', 'VRadioInline','VSelect', 'VAutocomplete', 'VCombobox'])
|
|
165
|
+
const choiceOption = ref(['VRadio', 'VRadioInline','VSelect', 'VAutocomplete', 'VCombobox','FormCheckboxGroup'])
|
|
165
166
|
const inputOptionsLabel = ref<Record<string,string>>({
|
|
166
167
|
'MasterAutocomplete' : "Group Key",
|
|
167
168
|
'Header' : "Class",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, watch, computed} from 'vue'
|
|
3
|
+
import { VCheckbox } from 'vuetify/components/VCheckbox'
|
|
4
|
+
import { join,without,filter,head,reject } from 'lodash-es'
|
|
5
|
+
interface Items {
|
|
6
|
+
label : string
|
|
7
|
+
value : any
|
|
8
|
+
}
|
|
9
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof VCheckbox['$props']>{
|
|
10
|
+
items : Items[]
|
|
11
|
+
label? : string
|
|
12
|
+
modelValue : []
|
|
13
|
+
inline? : boolean
|
|
14
|
+
rules?: typeof import('vuetify/components')['VCheckbox']['rules']
|
|
15
|
+
}
|
|
16
|
+
const props =defineProps<Props>()
|
|
17
|
+
const emit = defineEmits(['update:modelValue'])
|
|
18
|
+
const values = ref([])
|
|
19
|
+
const valuesOther = ref()
|
|
20
|
+
|
|
21
|
+
const computedRules = computed(() => {
|
|
22
|
+
if (props.rules){
|
|
23
|
+
let rules = props.rules.map((rule : any) => rule(values.value.length ? values.value : null))
|
|
24
|
+
rules = without(rules,true)
|
|
25
|
+
return join(rules,',')
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
const computedOther = computed(() => {
|
|
29
|
+
const itemOther = filter(props.items,{value:'other'})
|
|
30
|
+
return head(itemOther)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const computeItems = computed(() => {
|
|
34
|
+
return reject(props.items , {value:'other'})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
watch(values, () => {
|
|
38
|
+
emit('update:modelValue', [...values.value, valuesOther.value].filter(Boolean))
|
|
39
|
+
}, {deep: true});
|
|
40
|
+
|
|
41
|
+
watch(valuesOther, () => {
|
|
42
|
+
emit('update:modelValue', [...values.value, valuesOther.value].filter(Boolean))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
watch(props.modelValue, () => {
|
|
46
|
+
if (!props.modelValue) {
|
|
47
|
+
values.value = []
|
|
48
|
+
valuesOther.value = ''
|
|
49
|
+
} else {
|
|
50
|
+
// Separate regular values and the "other" value if applicable
|
|
51
|
+
if (Array.isArray(props.modelValue)) {
|
|
52
|
+
valuesOther.value = props.modelValue.find(item => !props.items.some(({ value }) => value === item)) || ''
|
|
53
|
+
values.value = props.modelValue.filter(item => item !== valuesOther.value)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, { deep: true, immediate: true })
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<template>
|
|
60
|
+
<v-container fluid>
|
|
61
|
+
<label class="text-body-1 opacity-60">{{props.label}}</label>
|
|
62
|
+
<div :class="`d-flex ${inline ? 'flex-row':'flex-column'}`">
|
|
63
|
+
<v-checkbox v-for="item in computeItems"
|
|
64
|
+
:value="item.value"
|
|
65
|
+
v-model="values"
|
|
66
|
+
density="compact"
|
|
67
|
+
hide-details
|
|
68
|
+
:error = "!!computedRules"
|
|
69
|
+
:="$attrs"
|
|
70
|
+
:label="item.label">
|
|
71
|
+
</v-checkbox>
|
|
72
|
+
</div>
|
|
73
|
+
<v-text-field hide-details
|
|
74
|
+
:error = "!!computedRules"
|
|
75
|
+
v-if="computedOther"
|
|
76
|
+
v-model="valuesOther"
|
|
77
|
+
:="$attrs"
|
|
78
|
+
:label="computedOther.label">
|
|
79
|
+
|
|
80
|
+
</v-text-field>
|
|
81
|
+
<label class="text-error text-subtitle-2 ml-1">
|
|
82
|
+
{{computedRules}}
|
|
83
|
+
</label>
|
|
84
|
+
</v-container>
|
|
85
|
+
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<style scoped>
|
|
89
|
+
|
|
90
|
+
</style>
|
|
@@ -6,6 +6,7 @@ import '@vuepic/vue-datepicker/dist/main.css'
|
|
|
6
6
|
import {isArray, isString} from "lodash-es";
|
|
7
7
|
import { type dateFormat, Datetime } from '../../utils/datetime'
|
|
8
8
|
import { useRules } from "../../composables/utils/validation";
|
|
9
|
+
import {VInput} from "vuetify/components/VInput";
|
|
9
10
|
|
|
10
11
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VTextField['$props']> {
|
|
11
12
|
locale?: 'TH' | 'EN'
|
|
@@ -179,44 +180,50 @@ defineExpose({
|
|
|
179
180
|
</script>
|
|
180
181
|
|
|
181
182
|
<template>
|
|
182
|
-
<v-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
<v-text-field
|
|
188
|
-
ref="textFieldRef"
|
|
189
|
-
v-model="displayedDate"
|
|
190
|
-
:rules="computedRules"
|
|
191
|
-
v-bind="$attrs"
|
|
192
|
-
@focus="handleTextFieldFocus"
|
|
193
|
-
@blur="handleTextFieldBlur"
|
|
194
|
-
@keydown="handleTextFieldInput"
|
|
195
|
-
@keyup.enter="handleTextFieldEnterKey"
|
|
196
|
-
@click:clear="handleTextFieldClear"
|
|
197
|
-
@click="toggleMenuOpen('textField')"
|
|
183
|
+
<v-input v-model="displayedDate" v-bind="$attrs" ref="inputRef">
|
|
184
|
+
<template #default="{isReadonly,isDisabled}">
|
|
185
|
+
<v-menu
|
|
186
|
+
v-model="isMenuOpen"
|
|
187
|
+
:open-on-click="false"
|
|
198
188
|
>
|
|
199
|
-
<template #
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
<template #activator="{ props: activatorProps }">
|
|
190
|
+
<v-text-field
|
|
191
|
+
ref="textFieldRef"
|
|
192
|
+
v-model="displayedDate"
|
|
193
|
+
:rules="computedRules"
|
|
194
|
+
v-bind="$attrs"
|
|
195
|
+
@focus="handleTextFieldFocus"
|
|
196
|
+
@blur="handleTextFieldBlur"
|
|
197
|
+
@keydown="handleTextFieldInput"
|
|
198
|
+
@keyup.enter="handleTextFieldEnterKey"
|
|
199
|
+
@click:clear="handleTextFieldClear"
|
|
200
|
+
@click="toggleMenuOpen('textField')"
|
|
201
|
+
>
|
|
202
|
+
<template #append-inner>
|
|
203
|
+
<v-icon v-if="!isReadonly.value"
|
|
204
|
+
v-bind="activatorProps"
|
|
205
|
+
@click="toggleMenuOpen('icon')"
|
|
206
|
+
>
|
|
207
|
+
fa:fa-regular fa-calendar
|
|
208
|
+
</v-icon>
|
|
209
|
+
</template>
|
|
210
|
+
</v-text-field>
|
|
206
211
|
</template>
|
|
207
|
-
|
|
212
|
+
<Datepicker
|
|
213
|
+
v-model="selectedDate"
|
|
214
|
+
model-type="yyyy-MM-dd"
|
|
215
|
+
:enable-time-picker="false"
|
|
216
|
+
:flow="flow"
|
|
217
|
+
:min-date="props.minDate"
|
|
218
|
+
:max-date="props.maxDate"
|
|
219
|
+
auto-apply
|
|
220
|
+
inline
|
|
221
|
+
:locale="locale"
|
|
222
|
+
@update:model-value="updateDatePicker"
|
|
223
|
+
/>
|
|
224
|
+
</v-menu>
|
|
208
225
|
</template>
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
:enable-time-picker="false"
|
|
213
|
-
:flow="flow"
|
|
214
|
-
:min-date="props.minDate"
|
|
215
|
-
:max-date="props.maxDate"
|
|
216
|
-
auto-apply
|
|
217
|
-
inline
|
|
218
|
-
:locale="locale"
|
|
219
|
-
@update:model-value="updateDatePicker"
|
|
220
|
-
/>
|
|
221
|
-
</v-menu>
|
|
226
|
+
|
|
227
|
+
</v-input>
|
|
228
|
+
|
|
222
229
|
</template>
|
|
@@ -4,6 +4,7 @@ import { union,isBoolean,isArray,isString } from 'lodash-es'
|
|
|
4
4
|
import { VTextField } from 'vuetify/components/VTextField'
|
|
5
5
|
import { type dateFormat, Datetime } from '../../utils/datetime'
|
|
6
6
|
import { useRules } from '../../composables/utils/validation'
|
|
7
|
+
import {VInput} from "vuetify/components/VInput";
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
9
10
|
modelValue?: string | null
|
|
@@ -158,38 +159,43 @@ watch(() => props.modelValue, () => {
|
|
|
158
159
|
</script>
|
|
159
160
|
|
|
160
161
|
<template>
|
|
161
|
-
<v-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
<
|
|
168
|
-
v-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
v-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
162
|
+
<v-input v-model="datePart" v-bind="$attrs" ref="inputRef">
|
|
163
|
+
<template #default="{isReadonly,isDisabled}">
|
|
164
|
+
<v-container
|
|
165
|
+
:fluid="true"
|
|
166
|
+
class="pa-0"
|
|
167
|
+
>
|
|
168
|
+
<v-row :dense="dense">
|
|
169
|
+
<v-col cols="8">
|
|
170
|
+
<FormDate
|
|
171
|
+
v-model="datePart"
|
|
172
|
+
ref="dateRef"
|
|
173
|
+
:rules="computedDateRules"
|
|
174
|
+
:label="label"
|
|
175
|
+
:format="format"
|
|
176
|
+
:picker-only="pickerOnly"
|
|
177
|
+
:readonly="isReadonly.value"
|
|
178
|
+
:disabled="fixedDate"
|
|
179
|
+
:min-date="minDate"
|
|
180
|
+
:max-date="maxDate"
|
|
181
|
+
v-bind="$attrs"
|
|
182
|
+
/>
|
|
183
|
+
</v-col>
|
|
184
|
+
<v-col cols="4">
|
|
185
|
+
<FormTime
|
|
186
|
+
v-model="timePart"
|
|
187
|
+
ref="timeRef"
|
|
188
|
+
:rules="computedTimeRules"
|
|
189
|
+
:label="label"
|
|
190
|
+
:enable-seconds="enableSeconds"
|
|
191
|
+
:picker-only="pickerOnly"
|
|
192
|
+
:readonly="isReadonly.value"
|
|
193
|
+
v-bind="$attrs"
|
|
194
|
+
/>
|
|
195
|
+
</v-col>
|
|
196
|
+
</v-row>
|
|
197
|
+
</v-container>
|
|
198
|
+
</template>
|
|
199
|
+
</v-input>
|
|
200
|
+
|
|
195
201
|
</template>
|
|
@@ -4,6 +4,7 @@ import { VTextField } from 'vuetify/components/VTextField'
|
|
|
4
4
|
import Datepicker from '@vuepic/vue-datepicker'
|
|
5
5
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
6
6
|
import { Datetime } from '../../utils/datetime'
|
|
7
|
+
import {VInput} from "vuetify/components/VInput";
|
|
7
8
|
|
|
8
9
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VTextField['$props']> {
|
|
9
10
|
enableSeconds?: boolean
|
|
@@ -122,44 +123,49 @@ defineExpose({
|
|
|
122
123
|
</script>
|
|
123
124
|
|
|
124
125
|
<template>
|
|
125
|
-
<v-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<v-text-field
|
|
132
|
-
ref="textFieldRef"
|
|
133
|
-
v-model="tempTime"
|
|
134
|
-
v-bind="$attrs"
|
|
135
|
-
@focus="onTextFieldFocus"
|
|
136
|
-
@blur="onTextFieldBlur"
|
|
137
|
-
@keydown="onTextFieldTyped"
|
|
138
|
-
@keyup.enter="onTextFieldEnterKey"
|
|
139
|
-
@click:clear="onTextFieldClear"
|
|
140
|
-
@click="toggleMenuOpen('textField')"
|
|
126
|
+
<v-input v-model="displayedDate" v-bind="$attrs" ref="inputRef">
|
|
127
|
+
<template #default="{isReadonly,isDisabled}">
|
|
128
|
+
<v-menu
|
|
129
|
+
v-model="isMenuOpen"
|
|
130
|
+
:close-on-content-click="false"
|
|
131
|
+
:open-on-click="false"
|
|
141
132
|
>
|
|
142
|
-
<template #
|
|
143
|
-
<v-
|
|
144
|
-
|
|
145
|
-
|
|
133
|
+
<template #activator="{ props }">
|
|
134
|
+
<v-text-field
|
|
135
|
+
ref="textFieldRef"
|
|
136
|
+
v-model="tempTime"
|
|
137
|
+
v-bind="$attrs"
|
|
138
|
+
@focus="onTextFieldFocus"
|
|
139
|
+
@blur="onTextFieldBlur"
|
|
140
|
+
@keydown="onTextFieldTyped"
|
|
141
|
+
@keyup.enter="onTextFieldEnterKey"
|
|
142
|
+
@click:clear="onTextFieldClear"
|
|
143
|
+
@click="toggleMenuOpen('textField')"
|
|
146
144
|
>
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
<template #append-inner>
|
|
146
|
+
<v-icon v-if="!isReadonly.value"
|
|
147
|
+
v-bind="props"
|
|
148
|
+
@click="toggleMenuOpen('icon')"
|
|
149
|
+
>
|
|
150
|
+
fa:fa-regular fa-clock
|
|
151
|
+
</v-icon>
|
|
152
|
+
</template>
|
|
153
|
+
</v-text-field>
|
|
149
154
|
</template>
|
|
150
|
-
|
|
155
|
+
<Datepicker
|
|
156
|
+
v-model="time"
|
|
157
|
+
model-type="HH:mm:ss"
|
|
158
|
+
:enable-seconds="enableSeconds"
|
|
159
|
+
minutes-grid-increment="1"
|
|
160
|
+
time-picker
|
|
161
|
+
auto-apply
|
|
162
|
+
:close-on-auto-apply="false"
|
|
163
|
+
inline
|
|
164
|
+
:locale="locale"
|
|
165
|
+
@update:model-value="setDatePicker"
|
|
166
|
+
/>
|
|
167
|
+
</v-menu>
|
|
151
168
|
</template>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
model-type="HH:mm:ss"
|
|
155
|
-
:enable-seconds="enableSeconds"
|
|
156
|
-
minutes-grid-increment="1"
|
|
157
|
-
time-picker
|
|
158
|
-
auto-apply
|
|
159
|
-
:close-on-auto-apply="false"
|
|
160
|
-
inline
|
|
161
|
-
:locale="locale"
|
|
162
|
-
@update:model-value="setDatePicker"
|
|
163
|
-
/>
|
|
164
|
-
</v-menu>
|
|
169
|
+
</v-input>
|
|
170
|
+
|
|
165
171
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { processTemplateFormTable } from "./templateFormTable.js";
|
|
2
2
|
import { processTemplateFormHidden } from "./templateFormHidden.js";
|
|
3
|
+
import { some, includes } from "lodash-es";
|
|
3
4
|
export const validationRulesRegex = /^(require(?:\([^)]*\))?|requireIf(?:\([^)]*\))?|requireTrue(?:\([^)]*\))?|requireTrueIf(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range(?:\([^)]*\))?|integer(?:\([^)]*\))?|unique(?:\([^)]*\))?|length(?:\([^)]*\))?|lengthGreater(?:\([^)]*\))?|lengthLess(?:\([^)]*\))?|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex(?:\([^)]*\))?)(,(require(?:\([^)]*\))?|requireIf(?:\([^)]*\))?|requireTrue(?:\([^)]*\))?|requireTrueIf(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range(?:\([^)]*\))?|integer(?:\([^)]*\))?|unique(?:\([^)]*\))?|length(?:\([^)]*\))?|lengthGreater(?:\([^)]*\))?|lengthLess(?:\([^)]*\))?|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex(?:\([^)]*\))?))*$/;
|
|
4
5
|
export function useDocumentTemplate(items, parentTemplates) {
|
|
5
6
|
if (!items) return "";
|
|
@@ -26,6 +27,10 @@ function templateItemToString(item, parentTemplates) {
|
|
|
26
27
|
const choice = optionStringToChoiceObject(item.inputOptions);
|
|
27
28
|
optionString = `item-value="value" item-title="label" :items='${escapeObjectForInlineBinding(choice)}' `;
|
|
28
29
|
}
|
|
30
|
+
if (["FormCheckboxGroup"].includes(item.inputType)) {
|
|
31
|
+
const choice = optionStringToChoiceObject(item.inputOptions);
|
|
32
|
+
optionString = ` :items='${escapeObjectForInlineBinding(choice)}'`;
|
|
33
|
+
}
|
|
29
34
|
if (["VRadio", "VRadioInline"].includes(item.inputType)) {
|
|
30
35
|
const choice = optionStringToChoiceObject(item.inputOptions);
|
|
31
36
|
optionString = choice.map((choiceItem) => `<v-radio label="${choiceItem.label || ""}" value="${choiceItem.value || ""}" ${item.inputAttributes ? " " + item.inputAttributes : ""}></v-radio>`).join("");
|
|
@@ -117,5 +122,7 @@ export function buildValidationRules(validationString) {
|
|
|
117
122
|
}
|
|
118
123
|
export function processDefaultTemplate(item, insideTemplate, optionString, validationRules) {
|
|
119
124
|
if (!validationRules) validationRules = item.validationRules ? buildValidationRules(item.validationRules) || "" : "";
|
|
120
|
-
|
|
125
|
+
const hasVariant = some([item.inputAttributes], (str) => includes(str, "variant"));
|
|
126
|
+
const defaultAttributes = `${!hasVariant ? `variant="underlined"` : ""} :active=isReadonly`;
|
|
127
|
+
return `<${item.inputType} ${defaultAttributes} v-model="data.${item.variableName || ""}" label="${item.inputLabel || item.variableName || ""}"${item.inputAttributes ? " " + item.inputAttributes : ""}${optionString ? " " + optionString.trim() : ""}${validationRules ? " " + validationRules.trim() : ""}>${insideTemplate || ""}</${item.inputType}>`;
|
|
121
128
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ramathibodi/nuxt-commons",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.43",
|
|
4
4
|
"description": "Ramathibodi Nuxt modules for common components",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -115,5 +115,5 @@
|
|
|
115
115
|
"vitest": "^1.6.0",
|
|
116
116
|
"vue-tsc": "2.0.29"
|
|
117
117
|
},
|
|
118
|
-
"packageManager": "pnpm@9.15.
|
|
118
|
+
"packageManager": "pnpm@9.15.5+sha512.845196026aab1cc3f098a0474b64dfbab2afe7a1b4e91dd86895d8e4aa32a7a6d03049e2d0ad770bbe4de023a7122fb68c1a1d6e0d033c7076085f9d5d4800d4"
|
|
119
119
|
}
|