@auronui/vue 1.2.1 → 1.3.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/ai-rules.md +243 -0
- package/dist/cjs/index.cjs +12349 -8683
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/components/autocomplete/Autocomplete.js.map +1 -1
- package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/combo-box/ComboBox.js.map +1 -1
- package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/context-menu/ContextMenu.js +7 -0
- package/dist/components/context-menu/ContextMenu.js.map +1 -0
- package/dist/components/context-menu/ContextMenu.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/context-menu/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuCheckboxItem.js +7 -0
- package/dist/components/context-menu/ContextMenuCheckboxItem.js.map +1 -0
- package/dist/components/context-menu/ContextMenuCheckboxItem.vue_vue_type_script_setup_true_lang.js +89 -0
- package/dist/components/context-menu/ContextMenuCheckboxItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuContent.js +7 -0
- package/dist/components/context-menu/ContextMenuContent.js.map +1 -0
- package/dist/components/context-menu/ContextMenuContent.vue_vue_type_script_setup_true_lang.js +135 -0
- package/dist/components/context-menu/ContextMenuContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuItem.js +7 -0
- package/dist/components/context-menu/ContextMenuItem.js.map +1 -0
- package/dist/components/context-menu/ContextMenuItem.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/components/context-menu/ContextMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuRadioGroup.js +7 -0
- package/dist/components/context-menu/ContextMenuRadioGroup.js.map +1 -0
- package/dist/components/context-menu/ContextMenuRadioGroup.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/components/context-menu/ContextMenuRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuRadioItem.js +7 -0
- package/dist/components/context-menu/ContextMenuRadioItem.js.map +1 -0
- package/dist/components/context-menu/ContextMenuRadioItem.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/components/context-menu/ContextMenuRadioItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSection.js +7 -0
- package/dist/components/context-menu/ContextMenuSection.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSection.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/context-menu/ContextMenuSection.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSub.js +7 -0
- package/dist/components/context-menu/ContextMenuSub.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSub.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/context-menu/ContextMenuSub.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSubContent.js +7 -0
- package/dist/components/context-menu/ContextMenuSubContent.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSubContent.vue_vue_type_script_setup_true_lang.js +155 -0
- package/dist/components/context-menu/ContextMenuSubContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSubTrigger.js +7 -0
- package/dist/components/context-menu/ContextMenuSubTrigger.js.map +1 -0
- package/dist/components/context-menu/ContextMenuSubTrigger.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/components/context-menu/ContextMenuSubTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/context-menu/ContextMenuTrigger.js +7 -0
- package/dist/components/context-menu/ContextMenuTrigger.js.map +1 -0
- package/dist/components/context-menu/ContextMenuTrigger.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/context-menu/ContextMenuTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/Editable.js +7 -0
- package/dist/components/editable/Editable.js.map +1 -0
- package/dist/components/editable/Editable.vue_vue_type_script_setup_true_lang.js +106 -0
- package/dist/components/editable/Editable.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditableArea.js +7 -0
- package/dist/components/editable/EditableArea.js.map +1 -0
- package/dist/components/editable/EditableArea.vue_vue_type_script_setup_true_lang.js +41 -0
- package/dist/components/editable/EditableArea.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditableCancelTrigger.js +7 -0
- package/dist/components/editable/EditableCancelTrigger.js.map +1 -0
- package/dist/components/editable/EditableCancelTrigger.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/components/editable/EditableCancelTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditableEditTrigger.js +7 -0
- package/dist/components/editable/EditableEditTrigger.js.map +1 -0
- package/dist/components/editable/EditableEditTrigger.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/editable/EditableEditTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditableInput.js +7 -0
- package/dist/components/editable/EditableInput.js.map +1 -0
- package/dist/components/editable/EditableInput.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/editable/EditableInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditablePreview.js +7 -0
- package/dist/components/editable/EditablePreview.js.map +1 -0
- package/dist/components/editable/EditablePreview.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/editable/EditablePreview.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/editable/EditableSubmitTrigger.js +7 -0
- package/dist/components/editable/EditableSubmitTrigger.js.map +1 -0
- package/dist/components/editable/EditableSubmitTrigger.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/editable/EditableSubmitTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/form/Form.js.map +1 -1
- package/dist/components/form/Form.vue_vue_type_script_setup_true_lang.js +32 -156
- package/dist/components/form/Form.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/FormField.js.map +1 -1
- package/dist/components/form/FormField.vue_vue_type_script_setup_true_lang.js +44 -23
- package/dist/components/form/FormField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/form.context.js.map +1 -1
- package/dist/components/form/form.state.js +166 -0
- package/dist/components/form/form.state.js.map +1 -0
- package/dist/components/form/useField.js +112 -0
- package/dist/components/form/useField.js.map +1 -0
- package/dist/components/form/useForm.js +17 -0
- package/dist/components/form/useForm.js.map +1 -0
- package/dist/components/hover-card/HoverCard.js +7 -0
- package/dist/components/hover-card/HoverCard.js.map +1 -0
- package/dist/components/hover-card/HoverCard.vue_vue_type_script_lang.js +52 -0
- package/dist/components/hover-card/HoverCard.vue_vue_type_script_lang.js.map +1 -0
- package/dist/components/hover-card/HoverCardArrow.js +7 -0
- package/dist/components/hover-card/HoverCardArrow.js.map +1 -0
- package/dist/components/hover-card/HoverCardArrow.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/hover-card/HoverCardArrow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/hover-card/HoverCardContent.js +7 -0
- package/dist/components/hover-card/HoverCardContent.js.map +1 -0
- package/dist/components/hover-card/HoverCardContent.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/hover-card/HoverCardContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/hover-card/HoverCardTrigger.js +7 -0
- package/dist/components/hover-card/HoverCardTrigger.js.map +1 -0
- package/dist/components/hover-card/HoverCardTrigger.vue_vue_type_script_setup_true_lang.js +26 -0
- package/dist/components/hover-card/HoverCardTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/Menubar.js +7 -0
- package/dist/components/menubar/Menubar.js.map +1 -0
- package/dist/components/menubar/Menubar.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/menubar/Menubar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarCheckboxItem.js +7 -0
- package/dist/components/menubar/MenubarCheckboxItem.js.map +1 -0
- package/dist/components/menubar/MenubarCheckboxItem.vue_vue_type_script_setup_true_lang.js +89 -0
- package/dist/components/menubar/MenubarCheckboxItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarContent.js +7 -0
- package/dist/components/menubar/MenubarContent.js.map +1 -0
- package/dist/components/menubar/MenubarContent.vue_vue_type_script_setup_true_lang.js +162 -0
- package/dist/components/menubar/MenubarContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarItem.js +7 -0
- package/dist/components/menubar/MenubarItem.js.map +1 -0
- package/dist/components/menubar/MenubarItem.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/components/menubar/MenubarItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarMenu.js +7 -0
- package/dist/components/menubar/MenubarMenu.js.map +1 -0
- package/dist/components/menubar/MenubarMenu.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/menubar/MenubarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarRadioGroup.js +7 -0
- package/dist/components/menubar/MenubarRadioGroup.js.map +1 -0
- package/dist/components/menubar/MenubarRadioGroup.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/components/menubar/MenubarRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarRadioItem.js +7 -0
- package/dist/components/menubar/MenubarRadioItem.js.map +1 -0
- package/dist/components/menubar/MenubarRadioItem.vue_vue_type_script_setup_true_lang.js +75 -0
- package/dist/components/menubar/MenubarRadioItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarSection.js +7 -0
- package/dist/components/menubar/MenubarSection.js.map +1 -0
- package/dist/components/menubar/MenubarSection.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/menubar/MenubarSection.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarSub.js +7 -0
- package/dist/components/menubar/MenubarSub.js.map +1 -0
- package/dist/components/menubar/MenubarSub.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/menubar/MenubarSub.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarSubContent.js +7 -0
- package/dist/components/menubar/MenubarSubContent.js.map +1 -0
- package/dist/components/menubar/MenubarSubContent.vue_vue_type_script_setup_true_lang.js +155 -0
- package/dist/components/menubar/MenubarSubContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarSubTrigger.js +7 -0
- package/dist/components/menubar/MenubarSubTrigger.js.map +1 -0
- package/dist/components/menubar/MenubarSubTrigger.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/components/menubar/MenubarSubTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/menubar/MenubarTrigger.js +7 -0
- package/dist/components/menubar/MenubarTrigger.js.map +1 -0
- package/dist/components/menubar/MenubarTrigger.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/menubar/MenubarTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/month-picker/MonthPicker.js +7 -0
- package/dist/components/month-picker/MonthPicker.js.map +1 -0
- package/dist/components/month-picker/MonthPicker.vue_vue_type_script_setup_true_lang.js +185 -0
- package/dist/components/month-picker/MonthPicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/month-range-picker/MonthRangePicker.js +7 -0
- package/dist/components/month-range-picker/MonthRangePicker.js.map +1 -0
- package/dist/components/month-range-picker/MonthRangePicker.vue_vue_type_script_setup_true_lang.js +196 -0
- package/dist/components/month-range-picker/MonthRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenu.js +7 -0
- package/dist/components/navigation-menu/NavigationMenu.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenu.vue_vue_type_script_setup_true_lang.js +85 -0
- package/dist/components/navigation-menu/NavigationMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuContent.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuContent.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuContent.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/navigation-menu/NavigationMenuContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuIndicator.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuIndicator.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuIndicator.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/navigation-menu/NavigationMenuIndicator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuItem.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuItem.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuItem.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/navigation-menu/NavigationMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuLink.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuLink.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuLink.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/navigation-menu/NavigationMenuLink.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuList.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuList.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuList.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/components/navigation-menu/NavigationMenuList.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuSub.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuSub.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuSub.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/navigation-menu/NavigationMenuSub.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.vue_vue_type_script_setup_true_lang.js +66 -0
- package/dist/components/navigation-menu/NavigationMenuTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuViewport.js +7 -0
- package/dist/components/navigation-menu/NavigationMenuViewport.js.map +1 -0
- package/dist/components/navigation-menu/NavigationMenuViewport.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/navigation-menu/NavigationMenuViewport.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/select/Select.js.map +1 -1
- package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/time-range-field/TimeRangeField.js +7 -0
- package/dist/components/time-range-field/TimeRangeField.js.map +1 -0
- package/dist/components/time-range-field/TimeRangeField.vue_vue_type_script_setup_true_lang.js +364 -0
- package/dist/components/time-range-field/TimeRangeField.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/year-range-picker/YearRangePicker.js +7 -0
- package/dist/components/year-range-picker/YearRangePicker.js.map +1 -0
- package/dist/components/year-range-picker/YearRangePicker.vue_vue_type_script_setup_true_lang.js +199 -0
- package/dist/components/year-range-picker/YearRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/index.d.ts +5393 -2896
- package/dist/index.js +50 -1
- package/dist/packages/styles/dist/components/hover-card/hover-card.styles.js +10 -0
- package/dist/packages/styles/dist/components/hover-card/hover-card.styles.js.map +1 -0
- package/package.json +4 -4
|
@@ -10,7 +10,8 @@ var FormField_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
|
|
|
10
10
|
defaultValue: {},
|
|
11
11
|
rules: {},
|
|
12
12
|
validate: { type: Function },
|
|
13
|
-
validationMode: {}
|
|
13
|
+
validationMode: {},
|
|
14
|
+
deps: {}
|
|
14
15
|
}, {
|
|
15
16
|
"modelValue": { default: void 0 },
|
|
16
17
|
"modelModifiers": {}
|
|
@@ -20,9 +21,13 @@ var FormField_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
|
|
|
20
21
|
const props = __props;
|
|
21
22
|
const modelValue = useModel(__props, "modelValue");
|
|
22
23
|
const ctx = useFormInject();
|
|
24
|
+
const resolvedDefault = computed(() => {
|
|
25
|
+
if (props.defaultValue !== void 0) return props.defaultValue;
|
|
26
|
+
return ctx?.defaultValues[props.name];
|
|
27
|
+
});
|
|
23
28
|
const localError = ref(void 0);
|
|
24
29
|
const touched = ref(false);
|
|
25
|
-
const dirty = ref(
|
|
30
|
+
const dirty = ref(resolvedDefault.value !== void 0 && modelValue.value !== resolvedDefault.value);
|
|
26
31
|
const fieldError = computed(() => ctx ? ctx.errors.value[props.name] : localError.value);
|
|
27
32
|
const hasBeenInvalid = ref(false);
|
|
28
33
|
watch(fieldError, (error) => {
|
|
@@ -32,20 +37,51 @@ var FormField_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
|
|
|
32
37
|
const isDisabled = computed(() => ctx?.isDisabled.value ?? false);
|
|
33
38
|
const validationMode = computed(() => props.validationMode ?? ctx?.validationMode.value ?? "on-submit");
|
|
34
39
|
watch(modelValue, (val) => {
|
|
35
|
-
dirty.value = val !==
|
|
40
|
+
dirty.value = val !== resolvedDefault.value;
|
|
36
41
|
});
|
|
42
|
+
async function triggerValidation(val) {
|
|
43
|
+
const context = ctx ? { values: ctx.getValues() } : void 0;
|
|
44
|
+
const error = await runValidation(val, props.rules, props.validate, context);
|
|
45
|
+
if (ctx) {
|
|
46
|
+
const next = { ...ctx.errors.value };
|
|
47
|
+
if (error) next[props.name] = error;
|
|
48
|
+
else delete next[props.name];
|
|
49
|
+
ctx.errors.value = next;
|
|
50
|
+
} else localError.value = error;
|
|
51
|
+
}
|
|
52
|
+
async function handleUpdate(val) {
|
|
53
|
+
modelValue.value = val;
|
|
54
|
+
if (validationMode.value === "on-change" || hasBeenInvalid.value) await triggerValidation(val);
|
|
55
|
+
}
|
|
56
|
+
async function handleBlur() {
|
|
57
|
+
touched.value = true;
|
|
58
|
+
if (validationMode.value === "on-blur") await triggerValidation(modelValue.value);
|
|
59
|
+
}
|
|
60
|
+
const depStoppers = [];
|
|
61
|
+
function setupDepWatchers(deps) {
|
|
62
|
+
for (const stop of depStoppers) stop();
|
|
63
|
+
depStoppers.length = 0;
|
|
64
|
+
if (!ctx || !deps?.length) return;
|
|
65
|
+
for (const dep of deps) {
|
|
66
|
+
const depRef = ctx.getFieldRef(dep);
|
|
67
|
+
if (!depRef) continue;
|
|
68
|
+
depStoppers.push(watch(depRef, () => void triggerValidation(modelValue.value)));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
37
71
|
function resetField() {
|
|
38
|
-
modelValue.value =
|
|
72
|
+
modelValue.value = resolvedDefault.value;
|
|
39
73
|
localError.value = void 0;
|
|
40
74
|
touched.value = false;
|
|
41
75
|
dirty.value = false;
|
|
42
76
|
hasBeenInvalid.value = false;
|
|
43
77
|
}
|
|
44
78
|
onMounted(() => {
|
|
79
|
+
if (modelValue.value === void 0 && resolvedDefault.value !== void 0) modelValue.value = resolvedDefault.value;
|
|
45
80
|
ctx?.registerField({
|
|
46
81
|
name: props.name,
|
|
82
|
+
valueRef: modelValue,
|
|
47
83
|
getValue: () => modelValue.value,
|
|
48
|
-
getDefaultValue: () =>
|
|
84
|
+
getDefaultValue: () => resolvedDefault.value,
|
|
49
85
|
setValue: (val) => {
|
|
50
86
|
modelValue.value = val;
|
|
51
87
|
},
|
|
@@ -55,28 +91,13 @@ var FormField_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
|
|
|
55
91
|
rules: props.rules,
|
|
56
92
|
validate: props.validate
|
|
57
93
|
});
|
|
94
|
+
setupDepWatchers(props.deps);
|
|
58
95
|
});
|
|
96
|
+
watch(() => props.deps?.join("\0") ?? "", () => setupDepWatchers(props.deps));
|
|
59
97
|
onUnmounted(() => {
|
|
98
|
+
for (const stop of depStoppers) stop();
|
|
60
99
|
ctx?.unregisterField(props.name);
|
|
61
100
|
});
|
|
62
|
-
async function triggerValidation(val) {
|
|
63
|
-
const context = ctx ? { values: ctx.getValues() } : void 0;
|
|
64
|
-
const error = await runValidation(val, props.rules, props.validate, context);
|
|
65
|
-
if (ctx) {
|
|
66
|
-
const next = { ...ctx.errors.value };
|
|
67
|
-
if (error) next[props.name] = error;
|
|
68
|
-
else delete next[props.name];
|
|
69
|
-
ctx.errors.value = next;
|
|
70
|
-
} else localError.value = error;
|
|
71
|
-
}
|
|
72
|
-
async function handleUpdate(val) {
|
|
73
|
-
modelValue.value = val;
|
|
74
|
-
if (validationMode.value === "on-change" || hasBeenInvalid.value) await triggerValidation(val);
|
|
75
|
-
}
|
|
76
|
-
async function handleBlur() {
|
|
77
|
-
touched.value = true;
|
|
78
|
-
if (validationMode.value === "on-blur") await triggerValidation(modelValue.value);
|
|
79
|
-
}
|
|
80
101
|
const fieldProps = computed(() => ({
|
|
81
102
|
name: props.name,
|
|
82
103
|
modelValue: modelValue.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/FormField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useFormInject } from './form.context'\nimport { runValidation } from './validation'\nimport type { FieldRules, CustomValidator } from './validation'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = defineProps<{\n name: string\n defaultValue?: unknown\n rules?: FieldRules\n validate?: CustomValidator\n /** Override validation mode for this field. */\n validationMode?: 'on-submit' | 'on-blur' | 'on-change'\n}>()\n\nconst modelValue = defineModel<unknown>({ default: undefined })\n\nconst ctx = useFormInject()\n\n// ── Field state ──────────────────────────────────────────────────────────────\n\nconst localError = ref<string | undefined>(undefined)\nconst touched = ref(false)\nconst dirty = ref(
|
|
1
|
+
{"version":3,"file":"FormField.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/FormField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useFormInject } from './form.context'\nimport { runValidation } from './validation'\nimport type { FieldRules, CustomValidator } from './validation'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = defineProps<{\n name: string\n defaultValue?: unknown\n rules?: FieldRules\n validate?: CustomValidator\n /** Override validation mode for this field. */\n validationMode?: 'on-submit' | 'on-blur' | 'on-change'\n /** Field names whose changes trigger re-validation of this field. */\n deps?: string[]\n}>()\n\nconst modelValue = defineModel<unknown>({ default: undefined })\n\nconst ctx = useFormInject()\n\n// ── Default value resolution ─────────────────────────────────────────────────\n// Priority: field-level defaultValue prop > form-level defaultValues[name] > undefined\n\nconst resolvedDefault = computed(() => {\n if (props.defaultValue !== undefined) return props.defaultValue\n return ctx?.defaultValues[props.name]\n})\n\n// ── Field state ──────────────────────────────────────────────────────────────\n\nconst localError = ref<string | undefined>(undefined)\nconst touched = ref(false)\nconst dirty = ref(\n resolvedDefault.value !== undefined && modelValue.value !== resolvedDefault.value,\n)\n\nconst fieldError = computed<string | undefined>(() =>\n ctx ? ctx.errors.value[props.name] : localError.value,\n)\n\nconst hasBeenInvalid = ref(false)\nwatch(fieldError, (error) => { if (error) hasBeenInvalid.value = true })\n\nconst isInvalid = computed(() => !!fieldError.value)\nconst isDisabled = computed(() => ctx?.isDisabled.value ?? false)\nconst validationMode = computed(() => props.validationMode ?? ctx?.validationMode.value ?? 'on-submit')\n\n// ── Dirty tracking ───────────────────────────────────────────────────────────\n\nwatch(modelValue, (val) => {\n dirty.value = val !== resolvedDefault.value\n})\n\n// ── Validation ───────────────────────────────────────────────────────────────\n\nasync function triggerValidation(val: unknown): Promise<void> {\n const context = ctx ? { values: ctx.getValues() } : undefined\n const error = await runValidation(val, props.rules, props.validate, context)\n\n if (ctx) {\n const next = { ...ctx.errors.value }\n if (error) {\n next[props.name] = error\n } else {\n delete next[props.name]\n }\n ctx.errors.value = next\n } else {\n localError.value = error\n }\n}\n\nasync function handleUpdate(val: unknown): Promise<void> {\n modelValue.value = val\n if (validationMode.value === 'on-change' || hasBeenInvalid.value) {\n await triggerValidation(val)\n }\n}\n\nasync function handleBlur(): Promise<void> {\n touched.value = true\n if (validationMode.value === 'on-blur') {\n await triggerValidation(modelValue.value)\n }\n}\n\n// ── Deps watching ─────────────────────────────────────────────────────────────\n\nconst depStoppers: (() => void)[] = []\n\nfunction setupDepWatchers(deps: string[] | undefined): void {\n for (const stop of depStoppers) stop()\n depStoppers.length = 0\n if (!ctx || !deps?.length) return\n for (const dep of deps) {\n const depRef = ctx.getFieldRef(dep)\n if (!depRef) continue\n depStoppers.push(watch(depRef, () => void triggerValidation(modelValue.value)))\n }\n}\n\n// ── Registration ─────────────────────────────────────────────────────────────\n\nfunction resetField(): void {\n modelValue.value = resolvedDefault.value\n localError.value = undefined\n touched.value = false\n dirty.value = false\n hasBeenInvalid.value = false\n}\n\nonMounted(() => {\n // Initialize to resolved default when no value was passed by the parent\n if (modelValue.value === undefined && resolvedDefault.value !== undefined) {\n modelValue.value = resolvedDefault.value\n }\n\n ctx?.registerField({\n name: props.name,\n valueRef: modelValue,\n getValue: () => modelValue.value,\n getDefaultValue: () => resolvedDefault.value,\n setValue: (val: unknown) => { modelValue.value = val },\n reset: resetField,\n touched,\n dirty,\n rules: props.rules,\n validate: props.validate,\n })\n\n setupDepWatchers(props.deps)\n})\n\n// Watch a stable string key so the watcher only tears down/rebuilds when the\n// dep list contents actually change — not on every re-render where the parent\n// passes a new array literal with the same elements (Object.is differs by ref).\nwatch(\n () => props.deps?.join('\\0') ?? '',\n () => setupDepWatchers(props.deps),\n)\n\nonUnmounted(() => {\n for (const stop of depStoppers) stop()\n ctx?.unregisterField(props.name)\n})\n\n// ── Slot bindings ─────────────────────────────────────────────────────────────\n\nconst fieldProps = computed(() => ({\n name: props.name,\n modelValue: modelValue.value,\n 'onUpdate:modelValue': handleUpdate,\n isInvalid: isInvalid.value,\n errorMessage: fieldError.value,\n isDisabled: isDisabled.value,\n onBlur: handleBlur,\n}))\n</script>\n\n<template>\n <slot\n :field-props=\"fieldProps\"\n :touched=\"touched\"\n :dirty=\"dirty\"\n :error=\"fieldError\"\n :is-invalid=\"isInvalid\"\n />\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.context.js","names":[],"sources":["../../../src/components/form/form.context.ts"],"sourcesContent":["import { inject, type Ref, type ComputedRef } from 'vue'\nimport { createContext } from '../../utils/context'\nimport type { FieldRules, CustomValidator } from './validation'\n\nexport type { FieldRules, CustomValidator }\n\nexport type ValidationMode = 'on-submit' | 'on-blur' | 'on-change'\n\nexport interface FieldRegistration {\n name: string\n getValue: () => unknown\n getDefaultValue: () => unknown\n setValue: (value: unknown) => void\n reset: () => void\n touched: Ref<boolean>\n dirty: Ref<boolean>\n rules?: FieldRules\n validate?: CustomValidator\n}\n\nexport interface FormContext {\n errors: Ref<Record<string, string>>\n isSubmitting: Ref<boolean>\n isSubmitted: Ref<boolean>\n submitCount: Ref<number>\n isDisabled: ComputedRef<boolean>\n isValid: ComputedRef<boolean>\n isDirty: ComputedRef<boolean>\n isTouched: ComputedRef<boolean>\n validationMode: ComputedRef<ValidationMode>\n registerField(reg: FieldRegistration): void\n unregisterField(name: string): void\n triggerFieldValidation(name: string): Promise<void>\n setErrors(newErrors: Record<string, string>): void\n setError(name: string, message: string): void\n clearErrors(name?: string): void\n getValues(): Record<string, unknown>\n setValue(name: string, value: unknown): void\n trigger(name?: string): Promise<boolean>\n reset(): void\n}\n\nexport const {\n useProvide: useFormProvide,\n useInject: _useFormInjectStrict,\n key: formContextKey,\n} = createContext<FormContext>('Form')\n\n/**\n * Inject Form context. Returns null when called outside a <Form> — callers\n * handle standalone mode themselves.\n */\nexport function useFormInject(): FormContext | null {\n return inject(formContextKey, null)\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"form.context.js","names":[],"sources":["../../../src/components/form/form.context.ts"],"sourcesContent":["import { inject, type Ref, type ComputedRef } from 'vue'\nimport { createContext } from '../../utils/context'\nimport type { FieldRules, CustomValidator } from './validation'\n\nexport type { FieldRules, CustomValidator }\n\nexport type ValidationMode = 'on-submit' | 'on-blur' | 'on-change'\n\nexport interface FieldRegistration {\n name: string\n valueRef: Ref<unknown> // reactive ref — powers values computed and deps watching\n getValue: () => unknown\n getDefaultValue: () => unknown\n setValue: (value: unknown) => void\n reset: () => void\n touched: Ref<boolean>\n dirty: Ref<boolean>\n rules?: FieldRules\n validate?: CustomValidator\n}\n\nexport interface FormOptions {\n defaultValues?: Record<string, unknown>\n validationMode?: ValidationMode\n isDisabled?: boolean\n}\n\nexport interface FormContext {\n errors: Ref<Record<string, string>>\n isSubmitting: Ref<boolean>\n isSubmitted: Ref<boolean>\n submitCount: Ref<number>\n isDisabled: ComputedRef<boolean>\n isValid: ComputedRef<boolean>\n isDirty: ComputedRef<boolean>\n isTouched: ComputedRef<boolean>\n validationMode: ComputedRef<ValidationMode>\n values: ComputedRef<Record<string, unknown>>\n defaultValues: Record<string, unknown>\n registerField(reg: FieldRegistration): void\n unregisterField(name: string): void\n triggerFieldValidation(name: string): Promise<void>\n getFieldRef(name: string): Ref<unknown> | undefined\n setErrors(newErrors: Record<string, string>): void\n setError(name: string, message: string): void\n clearErrors(name?: string): void\n getValues(): Record<string, unknown>\n setValue(name: string, value: unknown): void\n trigger(name?: string): Promise<boolean>\n reset(): void\n handleSubmit(\n onValid: (\n values: Record<string, unknown>,\n helpers: { setErrors(errors: Record<string, string>): void },\n ) => void | Promise<void>,\n onInvalid?: (errors: Record<string, string>) => void,\n ): Promise<void>\n}\n\nexport const {\n useProvide: useFormProvide,\n useInject: _useFormInjectStrict,\n key: formContextKey,\n} = createContext<FormContext>('Form')\n\n/**\n * Inject Form context. Returns null when called outside a <Form> — callers\n * handle standalone mode themselves.\n */\nexport function useFormInject(): FormContext | null {\n return inject(formContextKey, null)\n}\n"],"mappings":";;;AA2DA,IAAa,EACX,YAAY,gBACZ,WAAW,sBACX,KAAK,mBACH,cAA2B,OAAO;;;;;AAMtC,SAAgB,gBAAoC;AAClD,QAAO,OAAO,gBAAgB,KAAK"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { runValidation } from "./validation.js";
|
|
2
|
+
import { computed, ref } from "vue";
|
|
3
|
+
//#region src/components/form/form.state.ts
|
|
4
|
+
function createFormState(options = {}) {
|
|
5
|
+
const { defaultValues = {} } = options;
|
|
6
|
+
const errors = ref({});
|
|
7
|
+
const isSubmitting = ref(false);
|
|
8
|
+
const isSubmitted = ref(false);
|
|
9
|
+
const submitCount = ref(0);
|
|
10
|
+
const fields = /* @__PURE__ */ new Map();
|
|
11
|
+
const fieldCount = ref(0);
|
|
12
|
+
function registerField(reg) {
|
|
13
|
+
fields.set(reg.name, reg);
|
|
14
|
+
fieldCount.value++;
|
|
15
|
+
}
|
|
16
|
+
function unregisterField(name) {
|
|
17
|
+
fields.delete(name);
|
|
18
|
+
fieldCount.value--;
|
|
19
|
+
const next = { ...errors.value };
|
|
20
|
+
delete next[name];
|
|
21
|
+
errors.value = next;
|
|
22
|
+
}
|
|
23
|
+
const values = computed(() => {
|
|
24
|
+
fieldCount.value;
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const [name, field] of fields.entries()) result[name] = field.valueRef.value;
|
|
27
|
+
return result;
|
|
28
|
+
});
|
|
29
|
+
function getFieldRef(name) {
|
|
30
|
+
return fields.get(name)?.valueRef;
|
|
31
|
+
}
|
|
32
|
+
const isValid = computed(() => {
|
|
33
|
+
fieldCount.value;
|
|
34
|
+
return Object.keys(errors.value).length === 0;
|
|
35
|
+
});
|
|
36
|
+
const isDirty = computed(() => {
|
|
37
|
+
fieldCount.value;
|
|
38
|
+
for (const field of fields.values()) if (field.dirty.value) return true;
|
|
39
|
+
return false;
|
|
40
|
+
});
|
|
41
|
+
const isTouched = computed(() => {
|
|
42
|
+
fieldCount.value;
|
|
43
|
+
for (const field of fields.values()) if (field.touched.value) return true;
|
|
44
|
+
return false;
|
|
45
|
+
});
|
|
46
|
+
const validationMode = computed(() => options.validationMode?.value ?? "on-submit");
|
|
47
|
+
const isDisabled = computed(() => options.isDisabled?.value ?? false);
|
|
48
|
+
function getAllValues() {
|
|
49
|
+
const result = {};
|
|
50
|
+
for (const [name, field] of fields.entries()) result[name] = field.getValue();
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
async function triggerFieldValidation(name) {
|
|
54
|
+
const field = fields.get(name);
|
|
55
|
+
if (!field) return;
|
|
56
|
+
const error = await runValidation(field.getValue(), field.rules, field.validate, { values: getAllValues() });
|
|
57
|
+
const next = { ...errors.value };
|
|
58
|
+
if (error) next[name] = error;
|
|
59
|
+
else delete next[name];
|
|
60
|
+
errors.value = next;
|
|
61
|
+
}
|
|
62
|
+
async function trigger(name) {
|
|
63
|
+
if (name) {
|
|
64
|
+
await triggerFieldValidation(name);
|
|
65
|
+
return !errors.value[name];
|
|
66
|
+
}
|
|
67
|
+
const results = await Promise.all([...fields.entries()].map(async ([fieldName, field]) => {
|
|
68
|
+
return {
|
|
69
|
+
name: fieldName,
|
|
70
|
+
error: await runValidation(field.getValue(), field.rules, field.validate, { values: getAllValues() })
|
|
71
|
+
};
|
|
72
|
+
}));
|
|
73
|
+
const next = {};
|
|
74
|
+
for (const { name: fieldName, error } of results) if (error) next[fieldName] = error;
|
|
75
|
+
errors.value = next;
|
|
76
|
+
return Object.keys(next).length === 0;
|
|
77
|
+
}
|
|
78
|
+
function setErrors(newErrors) {
|
|
79
|
+
errors.value = {
|
|
80
|
+
...errors.value,
|
|
81
|
+
...newErrors
|
|
82
|
+
};
|
|
83
|
+
isSubmitting.value = false;
|
|
84
|
+
}
|
|
85
|
+
function setError(name, message) {
|
|
86
|
+
errors.value = {
|
|
87
|
+
...errors.value,
|
|
88
|
+
[name]: message
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function clearErrors(name) {
|
|
92
|
+
if (name) {
|
|
93
|
+
const next = { ...errors.value };
|
|
94
|
+
delete next[name];
|
|
95
|
+
errors.value = next;
|
|
96
|
+
} else errors.value = {};
|
|
97
|
+
}
|
|
98
|
+
function getValues() {
|
|
99
|
+
return getAllValues();
|
|
100
|
+
}
|
|
101
|
+
function setValue(name, value) {
|
|
102
|
+
const field = fields.get(name);
|
|
103
|
+
if (field) field.setValue(value);
|
|
104
|
+
}
|
|
105
|
+
function reset() {
|
|
106
|
+
for (const field of fields.values()) field.reset();
|
|
107
|
+
errors.value = {};
|
|
108
|
+
isSubmitting.value = false;
|
|
109
|
+
isSubmitted.value = false;
|
|
110
|
+
submitCount.value = 0;
|
|
111
|
+
}
|
|
112
|
+
async function handleSubmit(onValid, onInvalid) {
|
|
113
|
+
isSubmitting.value = true;
|
|
114
|
+
submitCount.value++;
|
|
115
|
+
const currentValues = getAllValues();
|
|
116
|
+
const context = { values: currentValues };
|
|
117
|
+
const results = await Promise.all([...fields.entries()].map(async ([name, field]) => {
|
|
118
|
+
return {
|
|
119
|
+
name,
|
|
120
|
+
error: await runValidation(field.getValue(), field.rules, field.validate, context)
|
|
121
|
+
};
|
|
122
|
+
}));
|
|
123
|
+
const nextErrors = {};
|
|
124
|
+
for (const { name, error } of results) if (error) nextErrors[name] = error;
|
|
125
|
+
if (Object.keys(nextErrors).length > 0) {
|
|
126
|
+
errors.value = nextErrors;
|
|
127
|
+
isSubmitting.value = false;
|
|
128
|
+
isSubmitted.value = true;
|
|
129
|
+
onInvalid?.(nextErrors);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
errors.value = {};
|
|
133
|
+
isSubmitted.value = true;
|
|
134
|
+
isSubmitting.value = false;
|
|
135
|
+
await onValid(currentValues, { setErrors });
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
errors,
|
|
139
|
+
isSubmitting,
|
|
140
|
+
isSubmitted,
|
|
141
|
+
submitCount,
|
|
142
|
+
isDisabled,
|
|
143
|
+
isValid,
|
|
144
|
+
isDirty,
|
|
145
|
+
isTouched,
|
|
146
|
+
validationMode,
|
|
147
|
+
values,
|
|
148
|
+
defaultValues,
|
|
149
|
+
registerField,
|
|
150
|
+
unregisterField,
|
|
151
|
+
triggerFieldValidation,
|
|
152
|
+
getFieldRef,
|
|
153
|
+
setErrors,
|
|
154
|
+
setError,
|
|
155
|
+
clearErrors,
|
|
156
|
+
getValues,
|
|
157
|
+
setValue,
|
|
158
|
+
trigger,
|
|
159
|
+
reset,
|
|
160
|
+
handleSubmit
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
164
|
+
export { createFormState };
|
|
165
|
+
|
|
166
|
+
//# sourceMappingURL=form.state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.state.js","names":[],"sources":["../../../src/components/form/form.state.ts"],"sourcesContent":["import { computed, ref, type Ref, type ComputedRef } from 'vue'\nimport { runValidation } from './validation'\nimport type { FormContext, FieldRegistration, ValidationMode } from './form.context'\n\n// Internal options — callers pass Refs so reactive props (from Form.vue's toRef) stay live\ninterface FormStateOptions {\n defaultValues?: Record<string, unknown>\n validationMode?: Ref<ValidationMode>\n isDisabled?: Ref<boolean>\n}\n\nexport function createFormState(options: FormStateOptions = {}): FormContext {\n const { defaultValues = {} } = options\n\n const errors = ref<Record<string, string>>({})\n const isSubmitting = ref(false)\n const isSubmitted = ref(false)\n const submitCount = ref(0)\n const fields = new Map<string, FieldRegistration>()\n const fieldCount = ref(0)\n\n // ── Registration ─────────────────────────────────────────────────────────────\n\n function registerField(reg: FieldRegistration): void {\n fields.set(reg.name, reg)\n fieldCount.value++\n }\n\n function unregisterField(name: string): void {\n fields.delete(name)\n fieldCount.value--\n const next = { ...errors.value }\n delete next[name]\n errors.value = next\n }\n\n // ── Reactive values ─────────────────────────────────────────────────────────\n\n const values: ComputedRef<Record<string, unknown>> = computed(() => {\n void fieldCount.value // track register/unregister events\n const result: Record<string, unknown> = {}\n for (const [name, field] of fields.entries()) {\n result[name] = field.valueRef.value\n }\n return result\n })\n\n function getFieldRef(name: string): Ref<unknown> | undefined {\n return fields.get(name)?.valueRef\n }\n\n // ── Computed state ──────────────────────────────────────────────────────────\n\n const isValid: ComputedRef<boolean> = computed(() => {\n void fieldCount.value\n return Object.keys(errors.value).length === 0\n })\n\n const isDirty: ComputedRef<boolean> = computed(() => {\n void fieldCount.value\n for (const field of fields.values()) {\n if (field.dirty.value) return true\n }\n return false\n })\n\n const isTouched: ComputedRef<boolean> = computed(() => {\n void fieldCount.value\n for (const field of fields.values()) {\n if (field.touched.value) return true\n }\n return false\n })\n\n const validationMode: ComputedRef<ValidationMode> = computed(\n () => options.validationMode?.value ?? 'on-submit',\n )\n\n const isDisabled: ComputedRef<boolean> = computed(\n () => options.isDisabled?.value ?? false,\n )\n\n // ── Helpers ─────────────────────────────────────────────────────────────────\n\n function getAllValues(): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [name, field] of fields.entries()) {\n result[name] = field.getValue()\n }\n return result\n }\n\n // ── Validation ───────────────────────────────────────────────────────────────\n\n async function triggerFieldValidation(name: string): Promise<void> {\n const field = fields.get(name)\n if (!field) return\n const error = await runValidation(\n field.getValue(),\n field.rules,\n field.validate,\n { values: getAllValues() },\n )\n const next = { ...errors.value }\n if (error) {\n next[name] = error\n } else {\n delete next[name]\n }\n errors.value = next\n }\n\n async function trigger(name?: string): Promise<boolean> {\n if (name) {\n await triggerFieldValidation(name)\n return !errors.value[name]\n }\n const results = await Promise.all(\n [...fields.entries()].map(async ([fieldName, field]) => {\n const error = await runValidation(\n field.getValue(),\n field.rules,\n field.validate,\n { values: getAllValues() },\n )\n return { name: fieldName, error }\n }),\n )\n const next: Record<string, string> = {}\n for (const { name: fieldName, error } of results) {\n if (error) next[fieldName] = error\n }\n errors.value = next\n return Object.keys(next).length === 0\n }\n\n // ── Error management ─────────────────────────────────────────────────────────\n\n function setErrors(newErrors: Record<string, string>): void {\n errors.value = { ...errors.value, ...newErrors }\n isSubmitting.value = false\n }\n\n function setError(name: string, message: string): void {\n errors.value = { ...errors.value, [name]: message }\n }\n\n function clearErrors(name?: string): void {\n if (name) {\n const next = { ...errors.value }\n delete next[name]\n errors.value = next\n } else {\n errors.value = {}\n }\n }\n\n // ── Values ───────────────────────────────────────────────────────────────────\n\n function getValues(): Record<string, unknown> {\n return getAllValues()\n }\n\n function setValue(name: string, value: unknown): void {\n const field = fields.get(name)\n if (field) field.setValue(value)\n }\n\n // ── Reset ────────────────────────────────────────────────────────────────────\n\n function reset(): void {\n for (const field of fields.values()) {\n field.reset()\n }\n errors.value = {}\n isSubmitting.value = false\n isSubmitted.value = false\n submitCount.value = 0\n }\n\n // ── Submit ───────────────────────────────────────────────────────────────────\n\n async function handleSubmit(\n onValid: (\n values: Record<string, unknown>,\n helpers: { setErrors(errors: Record<string, string>): void },\n ) => void | Promise<void>,\n onInvalid?: (errors: Record<string, string>) => void,\n ): Promise<void> {\n isSubmitting.value = true\n submitCount.value++\n\n const currentValues = getAllValues()\n const context = { values: currentValues }\n\n const results = await Promise.all(\n [...fields.entries()].map(async ([name, field]) => {\n const error = await runValidation(field.getValue(), field.rules, field.validate, context)\n return { name, error }\n }),\n )\n\n const nextErrors: Record<string, string> = {}\n for (const { name, error } of results) {\n if (error) nextErrors[name] = error\n }\n\n if (Object.keys(nextErrors).length > 0) {\n errors.value = nextErrors\n isSubmitting.value = false\n isSubmitted.value = true\n onInvalid?.(nextErrors)\n return\n }\n\n errors.value = {}\n isSubmitted.value = true\n isSubmitting.value = false\n await onValid(currentValues, { setErrors })\n }\n\n return {\n errors,\n isSubmitting,\n isSubmitted,\n submitCount,\n isDisabled,\n isValid,\n isDirty,\n isTouched,\n validationMode,\n values,\n defaultValues,\n registerField,\n unregisterField,\n triggerFieldValidation,\n getFieldRef,\n setErrors,\n setError,\n clearErrors,\n getValues,\n setValue,\n trigger,\n reset,\n handleSubmit,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useFormInject } from "./form.context.js";
|
|
2
|
+
import { runValidation } from "./validation.js";
|
|
3
|
+
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
|
4
|
+
//#region src/components/form/useField.ts
|
|
5
|
+
function useField(name, options = {}) {
|
|
6
|
+
const ctx = useFormInject();
|
|
7
|
+
const modelValue = ref(options.defaultValue !== void 0 ? options.defaultValue : ctx?.defaultValues[name]);
|
|
8
|
+
const localError = ref(void 0);
|
|
9
|
+
const touched = ref(false);
|
|
10
|
+
const dirty = ref(false);
|
|
11
|
+
const hasBeenInvalid = ref(false);
|
|
12
|
+
const resolvedDefault = computed(() => {
|
|
13
|
+
if (options.defaultValue !== void 0) return options.defaultValue;
|
|
14
|
+
return ctx?.defaultValues[name];
|
|
15
|
+
});
|
|
16
|
+
const error = computed(() => ctx ? ctx.errors.value[name] : localError.value);
|
|
17
|
+
const isInvalid = computed(() => !!error.value);
|
|
18
|
+
const isDisabled = computed(() => ctx?.isDisabled.value ?? false);
|
|
19
|
+
const effectiveMode = computed(() => options.validationMode ?? ctx?.validationMode.value ?? "on-submit");
|
|
20
|
+
watch(error, (e) => {
|
|
21
|
+
if (e) hasBeenInvalid.value = true;
|
|
22
|
+
});
|
|
23
|
+
watch(modelValue, (val) => {
|
|
24
|
+
dirty.value = val !== resolvedDefault.value;
|
|
25
|
+
});
|
|
26
|
+
async function triggerValidation(val) {
|
|
27
|
+
const context = ctx ? { values: ctx.getValues() } : void 0;
|
|
28
|
+
const err = await runValidation(val, options.rules, options.validate, context);
|
|
29
|
+
if (ctx) {
|
|
30
|
+
const next = { ...ctx.errors.value };
|
|
31
|
+
if (err) next[name] = err;
|
|
32
|
+
else delete next[name];
|
|
33
|
+
ctx.errors.value = next;
|
|
34
|
+
} else localError.value = err;
|
|
35
|
+
}
|
|
36
|
+
async function handleUpdate(val) {
|
|
37
|
+
modelValue.value = val;
|
|
38
|
+
if (!ctx || effectiveMode.value === "on-change" || hasBeenInvalid.value) await triggerValidation(val);
|
|
39
|
+
}
|
|
40
|
+
async function handleBlur() {
|
|
41
|
+
touched.value = true;
|
|
42
|
+
if (effectiveMode.value === "on-blur") await triggerValidation(modelValue.value);
|
|
43
|
+
}
|
|
44
|
+
function reset() {
|
|
45
|
+
modelValue.value = resolvedDefault.value;
|
|
46
|
+
localError.value = void 0;
|
|
47
|
+
touched.value = false;
|
|
48
|
+
dirty.value = false;
|
|
49
|
+
hasBeenInvalid.value = false;
|
|
50
|
+
if (ctx) {
|
|
51
|
+
const next = { ...ctx.errors.value };
|
|
52
|
+
delete next[name];
|
|
53
|
+
ctx.errors.value = next;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const depStoppers = [];
|
|
57
|
+
function setupDepWatchers(deps) {
|
|
58
|
+
for (const stop of depStoppers) stop();
|
|
59
|
+
depStoppers.length = 0;
|
|
60
|
+
if (!ctx || !deps?.length) return;
|
|
61
|
+
for (const dep of deps) {
|
|
62
|
+
const depRef = ctx.getFieldRef(dep);
|
|
63
|
+
if (!depRef) continue;
|
|
64
|
+
depStoppers.push(watch(depRef, () => void triggerValidation(modelValue.value)));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
ctx?.registerField({
|
|
69
|
+
name,
|
|
70
|
+
valueRef: modelValue,
|
|
71
|
+
getValue: () => modelValue.value,
|
|
72
|
+
getDefaultValue: () => resolvedDefault.value,
|
|
73
|
+
setValue: (val) => {
|
|
74
|
+
modelValue.value = val;
|
|
75
|
+
},
|
|
76
|
+
reset,
|
|
77
|
+
touched,
|
|
78
|
+
dirty,
|
|
79
|
+
rules: options.rules,
|
|
80
|
+
validate: options.validate
|
|
81
|
+
});
|
|
82
|
+
setupDepWatchers(options.deps);
|
|
83
|
+
});
|
|
84
|
+
onUnmounted(() => {
|
|
85
|
+
for (const stop of depStoppers) stop();
|
|
86
|
+
ctx?.unregisterField(name);
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
modelValue,
|
|
90
|
+
error,
|
|
91
|
+
isInvalid,
|
|
92
|
+
isTouched: touched,
|
|
93
|
+
isDirty: dirty,
|
|
94
|
+
isDisabled,
|
|
95
|
+
fieldProps: computed(() => ({
|
|
96
|
+
name,
|
|
97
|
+
modelValue: modelValue.value,
|
|
98
|
+
"onUpdate:modelValue": handleUpdate,
|
|
99
|
+
isInvalid: isInvalid.value,
|
|
100
|
+
errorMessage: error.value,
|
|
101
|
+
isDisabled: isDisabled.value,
|
|
102
|
+
onBlur: handleBlur
|
|
103
|
+
})),
|
|
104
|
+
handleUpdate,
|
|
105
|
+
handleBlur,
|
|
106
|
+
reset
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { useField };
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=useField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useField.js","names":[],"sources":["../../../src/components/form/useField.ts"],"sourcesContent":["import { computed, onMounted, onUnmounted, ref, watch, type ComputedRef, type Ref } from 'vue'\nimport { useFormInject } from './form.context'\nimport { runValidation } from './validation'\nimport type { FieldRules, CustomValidator, ValidationMode } from './form.context'\n\nexport interface FieldOptions {\n defaultValue?: unknown\n rules?: FieldRules\n validate?: CustomValidator\n validationMode?: ValidationMode\n deps?: string[]\n}\n\nexport interface FieldProps {\n name: string\n modelValue: unknown\n 'onUpdate:modelValue': (value: unknown) => Promise<void>\n isInvalid: boolean\n errorMessage: string | undefined\n isDisabled: boolean\n onBlur: () => Promise<void>\n}\n\nexport interface FieldHandle {\n modelValue: Ref<unknown>\n error: ComputedRef<string | undefined>\n isInvalid: ComputedRef<boolean>\n isTouched: Ref<boolean>\n isDirty: Ref<boolean>\n isDisabled: ComputedRef<boolean>\n fieldProps: ComputedRef<FieldProps>\n handleUpdate(value: unknown): Promise<void>\n handleBlur(): Promise<void>\n reset(): void\n}\n\nexport function useField(name: string, options: FieldOptions = {}): FieldHandle {\n const ctx = useFormInject()\n\n const modelValue = ref<unknown>(\n options.defaultValue !== undefined\n ? options.defaultValue\n : ctx?.defaultValues[name],\n )\n\n const localError = ref<string | undefined>(undefined)\n const touched = ref(false)\n const dirty = ref(false)\n const hasBeenInvalid = ref(false)\n\n const resolvedDefault = computed(() => {\n if (options.defaultValue !== undefined) return options.defaultValue\n return ctx?.defaultValues[name]\n })\n\n const error: ComputedRef<string | undefined> = computed(() =>\n ctx ? ctx.errors.value[name] : localError.value,\n )\n const isInvalid: ComputedRef<boolean> = computed(() => !!error.value)\n const isDisabled: ComputedRef<boolean> = computed(() => ctx?.isDisabled.value ?? false)\n const effectiveMode = computed(() => options.validationMode ?? ctx?.validationMode.value ?? 'on-submit')\n\n watch(error, (e) => { if (e) hasBeenInvalid.value = true })\n watch(modelValue, (val) => { dirty.value = val !== resolvedDefault.value })\n\n // ── Validation ───────────────────────────────────────────────────────────────\n\n async function triggerValidation(val: unknown): Promise<void> {\n const context = ctx ? { values: ctx.getValues() } : undefined\n const err = await runValidation(val, options.rules, options.validate, context)\n\n if (ctx) {\n const next = { ...ctx.errors.value }\n if (err) {\n next[name] = err\n } else {\n delete next[name]\n }\n ctx.errors.value = next\n } else {\n localError.value = err\n }\n }\n\n async function handleUpdate(val: unknown): Promise<void> {\n modelValue.value = val\n // In standalone mode (no form) there is no submit event, so always validate on change.\n // In form mode, respect the configured validation mode.\n if (!ctx || effectiveMode.value === 'on-change' || hasBeenInvalid.value) {\n await triggerValidation(val)\n }\n }\n\n async function handleBlur(): Promise<void> {\n touched.value = true\n if (effectiveMode.value === 'on-blur') {\n await triggerValidation(modelValue.value)\n }\n }\n\n function reset(): void {\n modelValue.value = resolvedDefault.value\n localError.value = undefined\n touched.value = false\n dirty.value = false\n hasBeenInvalid.value = false\n if (ctx) {\n const next = { ...ctx.errors.value }\n delete next[name]\n ctx.errors.value = next\n }\n }\n\n // ── Deps watching ─────────────────────────────────────────────────────────────\n\n const depStoppers: (() => void)[] = []\n\n function setupDepWatchers(deps: string[] | undefined): void {\n for (const stop of depStoppers) stop()\n depStoppers.length = 0\n if (!ctx || !deps?.length) return\n for (const dep of deps) {\n const depRef = ctx.getFieldRef(dep)\n if (!depRef) continue\n depStoppers.push(watch(depRef, () => void triggerValidation(modelValue.value)))\n }\n }\n\n // ── Registration ─────────────────────────────────────────────────────────────\n\n onMounted(() => {\n ctx?.registerField({\n name,\n valueRef: modelValue,\n getValue: () => modelValue.value,\n getDefaultValue: () => resolvedDefault.value,\n setValue: (val) => { modelValue.value = val },\n reset,\n touched,\n dirty,\n rules: options.rules,\n validate: options.validate,\n })\n setupDepWatchers(options.deps)\n })\n\n onUnmounted(() => {\n for (const stop of depStoppers) stop()\n ctx?.unregisterField(name)\n })\n\n // ── fieldProps ────────────────────────────────────────────────────────────────\n\n const fieldProps: ComputedRef<FieldProps> = computed(() => ({\n name,\n modelValue: modelValue.value,\n 'onUpdate:modelValue': handleUpdate,\n isInvalid: isInvalid.value,\n errorMessage: error.value,\n isDisabled: isDisabled.value,\n onBlur: handleBlur,\n }))\n\n return {\n modelValue,\n error,\n isInvalid,\n isTouched: touched,\n isDirty: dirty,\n isDisabled,\n fieldProps,\n handleUpdate,\n handleBlur,\n reset,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { formContextKey } from "./form.context.js";
|
|
2
|
+
import { createFormState } from "./form.state.js";
|
|
3
|
+
import { provide, ref } from "vue";
|
|
4
|
+
//#region src/components/form/useForm.ts
|
|
5
|
+
function useForm(options = {}) {
|
|
6
|
+
const ctx = createFormState({
|
|
7
|
+
defaultValues: options.defaultValues,
|
|
8
|
+
validationMode: ref(options.validationMode ?? "on-submit"),
|
|
9
|
+
isDisabled: ref(options.isDisabled ?? false)
|
|
10
|
+
});
|
|
11
|
+
provide(formContextKey, ctx);
|
|
12
|
+
return ctx;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { useForm };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=useForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useForm.js","names":[],"sources":["../../../src/components/form/useForm.ts"],"sourcesContent":["import { provide, ref } from 'vue'\nimport { formContextKey, type FormContext, type FormOptions } from './form.context'\nimport { createFormState } from './form.state'\n\nexport function useForm(options: FormOptions = {}): FormContext {\n const ctx = createFormState({\n defaultValues: options.defaultValues,\n validationMode: ref(options.validationMode ?? 'on-submit'),\n isDisabled: ref(options.isDisabled ?? false),\n })\n provide(formContextKey, ctx)\n return ctx\n}\n"],"mappings":";;;;AAIA,SAAgB,QAAQ,UAAuB,EAAE,EAAe;CAC9D,MAAM,MAAM,gBAAgB;EAC1B,eAAe,QAAQ;EACvB,gBAAgB,IAAI,QAAQ,kBAAkB,YAAY;EAC1D,YAAY,IAAI,QAAQ,cAAc,MAAM;EAC7C,CAAC;AACF,SAAQ,gBAAgB,IAAI;AAC5B,QAAO"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import HoverCard_vue_vue_type_script_lang_default from "./HoverCard.vue_vue_type_script_lang.js";
|
|
2
|
+
//#region src/components/hover-card/HoverCard.vue
|
|
3
|
+
var HoverCard_default = HoverCard_vue_vue_type_script_lang_default;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { HoverCard_default as default };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=HoverCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCard.js","names":[],"sources":["../../../src/components/hover-card/HoverCard.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { defineComponent, computed, h } from 'vue'\nimport { HoverCardRoot } from 'reka-ui'\n\n/**\n * HoverCard root component. Wraps Reka UI's HoverCardRoot.\n *\n * Important: we use the Options-API / render-function style here (not `<script setup>`)\n * to avoid Vue SFC's compiled template from forwarding `open: undefined` to HoverCardRoot.\n * Reka's `useVModel` checks `props.open === undefined` to choose uncontrolled vs controlled\n * mode, but a template `:open=\"props.open\"` always provides the key (even as `undefined`),\n * forcing controlled mode and breaking `defaultOpen`. The render function lets us omit the\n * key entirely when `open` is not provided by the consumer. This mirrors Popover.vue.\n */\nexport default defineComponent({\n name: 'HoverCard',\n props: {\n defaultOpen: { type: Boolean, default: false },\n open: { type: Boolean, default: undefined },\n openDelay: { type: Number, default: 700 },\n closeDelay: { type: Number, default: 300 },\n },\n emits: ['update:open'],\n setup(props, { slots, emit }) {\n const rootProps = computed(() => {\n const p: Record<string, unknown> = {\n defaultOpen: props.defaultOpen,\n openDelay: props.openDelay,\n closeDelay: props.closeDelay,\n 'onUpdate:open': (val: boolean) => emit('update:open', val),\n }\n if (props.open !== undefined) {\n p.open = props.open\n }\n return p\n })\n\n return () => h(HoverCardRoot, rootProps.value, slots)\n },\n})\n</script>\n"],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { computed, defineComponent, h } from "vue";
|
|
2
|
+
import { HoverCardRoot } from "reka-ui";
|
|
3
|
+
//#region src/components/hover-card/HoverCard.vue?vue&type=script&lang.ts
|
|
4
|
+
/**
|
|
5
|
+
* HoverCard root component. Wraps Reka UI's HoverCardRoot.
|
|
6
|
+
*
|
|
7
|
+
* Important: we use the Options-API / render-function style here (not `<script setup>`)
|
|
8
|
+
* to avoid Vue SFC's compiled template from forwarding `open: undefined` to HoverCardRoot.
|
|
9
|
+
* Reka's `useVModel` checks `props.open === undefined` to choose uncontrolled vs controlled
|
|
10
|
+
* mode, but a template `:open="props.open"` always provides the key (even as `undefined`),
|
|
11
|
+
* forcing controlled mode and breaking `defaultOpen`. The render function lets us omit the
|
|
12
|
+
* key entirely when `open` is not provided by the consumer. This mirrors Popover.vue.
|
|
13
|
+
*/
|
|
14
|
+
var HoverCard_vue_vue_type_script_lang_default = defineComponent({
|
|
15
|
+
name: "HoverCard",
|
|
16
|
+
props: {
|
|
17
|
+
defaultOpen: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
open: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: void 0
|
|
24
|
+
},
|
|
25
|
+
openDelay: {
|
|
26
|
+
type: Number,
|
|
27
|
+
default: 700
|
|
28
|
+
},
|
|
29
|
+
closeDelay: {
|
|
30
|
+
type: Number,
|
|
31
|
+
default: 300
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
emits: ["update:open"],
|
|
35
|
+
setup(props, { slots, emit }) {
|
|
36
|
+
const rootProps = computed(() => {
|
|
37
|
+
const p = {
|
|
38
|
+
defaultOpen: props.defaultOpen,
|
|
39
|
+
openDelay: props.openDelay,
|
|
40
|
+
closeDelay: props.closeDelay,
|
|
41
|
+
"onUpdate:open": (val) => emit("update:open", val)
|
|
42
|
+
};
|
|
43
|
+
if (props.open !== void 0) p.open = props.open;
|
|
44
|
+
return p;
|
|
45
|
+
});
|
|
46
|
+
return () => h(HoverCardRoot, rootProps.value, slots);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//#endregion
|
|
50
|
+
export { HoverCard_vue_vue_type_script_lang_default as default };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=HoverCard.vue_vue_type_script_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCard.vue_vue_type_script_lang.js","names":[],"sources":["../../../src/components/hover-card/HoverCard.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { defineComponent, computed, h } from 'vue'\nimport { HoverCardRoot } from 'reka-ui'\n\n/**\n * HoverCard root component. Wraps Reka UI's HoverCardRoot.\n *\n * Important: we use the Options-API / render-function style here (not `<script setup>`)\n * to avoid Vue SFC's compiled template from forwarding `open: undefined` to HoverCardRoot.\n * Reka's `useVModel` checks `props.open === undefined` to choose uncontrolled vs controlled\n * mode, but a template `:open=\"props.open\"` always provides the key (even as `undefined`),\n * forcing controlled mode and breaking `defaultOpen`. The render function lets us omit the\n * key entirely when `open` is not provided by the consumer. This mirrors Popover.vue.\n */\nexport default defineComponent({\n name: 'HoverCard',\n props: {\n defaultOpen: { type: Boolean, default: false },\n open: { type: Boolean, default: undefined },\n openDelay: { type: Number, default: 700 },\n closeDelay: { type: Number, default: 300 },\n },\n emits: ['update:open'],\n setup(props, { slots, emit }) {\n const rootProps = computed(() => {\n const p: Record<string, unknown> = {\n defaultOpen: props.defaultOpen,\n openDelay: props.openDelay,\n closeDelay: props.closeDelay,\n 'onUpdate:open': (val: boolean) => emit('update:open', val),\n }\n if (props.open !== undefined) {\n p.open = props.open\n }\n return p\n })\n\n return () => h(HoverCardRoot, rootProps.value, slots)\n },\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAA,6CAAe,gBAAgB;CAC7B,MAAM;CACN,OAAO;EACL,aAAa;GAAE,MAAM;GAAS,SAAS;GAAO;EAC9C,MAAM;GAAE,MAAM;GAAS,SAAS,KAAA;GAAW;EAC3C,WAAW;GAAE,MAAM;GAAQ,SAAS;GAAK;EACzC,YAAY;GAAE,MAAM;GAAQ,SAAS;GAAK;EAC3C;CACD,OAAO,CAAC,cAAc;CACtB,MAAM,OAAO,EAAE,OAAO,QAAQ;EAC5B,MAAM,YAAY,eAAe;GAC/B,MAAM,IAA6B;IACjC,aAAa,MAAM;IACnB,WAAW,MAAM;IACjB,YAAY,MAAM;IAClB,kBAAkB,QAAiB,KAAK,eAAe,IAAI;IAC7D;AACA,OAAI,MAAM,SAAS,KAAA,EACjB,GAAE,OAAO,MAAM;AAEjB,UAAO;IACR;AAED,eAAa,EAAE,eAAe,UAAU,OAAO,MAAK;;CAEvD,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import HoverCardArrow_vue_vue_type_script_setup_true_lang_default from "./HoverCardArrow.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
//#region src/components/hover-card/HoverCardArrow.vue
|
|
3
|
+
var HoverCardArrow_default = HoverCardArrow_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { HoverCardArrow_default as default };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=HoverCardArrow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCardArrow.js","names":[],"sources":["../../../src/components/hover-card/HoverCardArrow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { HoverCardArrow } from 'reka-ui'\n\nconst props = defineProps<{\n as?: string | object\n asChild?: boolean\n width?: number\n height?: number\n class?: string\n}>()\n</script>\n\n<template>\n <HoverCardArrow\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :width=\"props.width\"\n :height=\"props.height\"\n :class=\"props.class\"\n v-bind=\"$attrs\"\n />\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createBlock, defineComponent, mergeProps, openBlock, unref } from "vue";
|
|
2
|
+
import { HoverCardArrow } from "reka-ui";
|
|
3
|
+
//#region src/components/hover-card/HoverCardArrow.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var HoverCardArrow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
5
|
+
__name: "HoverCardArrow",
|
|
6
|
+
props: {
|
|
7
|
+
as: {},
|
|
8
|
+
asChild: { type: Boolean },
|
|
9
|
+
width: {},
|
|
10
|
+
height: {},
|
|
11
|
+
class: {}
|
|
12
|
+
},
|
|
13
|
+
setup(__props) {
|
|
14
|
+
const props = __props;
|
|
15
|
+
return (_ctx, _cache) => {
|
|
16
|
+
return openBlock(), createBlock(unref(HoverCardArrow), mergeProps({
|
|
17
|
+
as: props.as,
|
|
18
|
+
"as-child": props.asChild,
|
|
19
|
+
width: props.width,
|
|
20
|
+
height: props.height,
|
|
21
|
+
class: props.class
|
|
22
|
+
}, _ctx.$attrs), null, 16, [
|
|
23
|
+
"as",
|
|
24
|
+
"as-child",
|
|
25
|
+
"width",
|
|
26
|
+
"height",
|
|
27
|
+
"class"
|
|
28
|
+
]);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
//#endregion
|
|
33
|
+
export { HoverCardArrow_vue_vue_type_script_setup_true_lang_default as default };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=HoverCardArrow.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCardArrow.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/hover-card/HoverCardArrow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { HoverCardArrow } from 'reka-ui'\n\nconst props = defineProps<{\n as?: string | object\n asChild?: boolean\n width?: number\n height?: number\n class?: string\n}>()\n</script>\n\n<template>\n <HoverCardArrow\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :width=\"props.width\"\n :height=\"props.height\"\n :class=\"props.class\"\n v-bind=\"$attrs\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;EAGA,MAAM,QAAQ;;uBAUZ,YAOE,MAAA,eAAA,EAPF,WAOE;IANC,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,OAAO,MAAM;IACb,QAAQ,MAAM;IACd,OAAO,MAAM;MACNA,KAAAA,OAAM,EAAA,MAAA,IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import HoverCardContent_vue_vue_type_script_setup_true_lang_default from "./HoverCardContent.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
//#region src/components/hover-card/HoverCardContent.vue
|
|
3
|
+
var HoverCardContent_default = HoverCardContent_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { HoverCardContent_default as default };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=HoverCardContent.js.map
|