jenesius-vue-form
Advanced tools
Comparing version 2.0.8 to 2.0.9
@@ -8,2 +8,4 @@ import EventEmitter from "jenesius-event-emitter"; | ||
static EVENT_SAVE: string; | ||
static EVENT_VALUE: string; | ||
static EVENT_UPDATE_ABILITY: string; | ||
/** | ||
@@ -15,3 +17,3 @@ * @description Вызывается всякий раз, когда форма была изменена. Внимание! | ||
static EVENT_DISABLED: string; | ||
static getParentForm(): Form; | ||
static getParentForm(): Form | undefined; | ||
/**=========**/ | ||
@@ -67,8 +69,2 @@ /** | ||
protected recursiveChangeItem(values: any, path?: string): void; | ||
/** | ||
* @description Частный случай setValues, используется для input элементов. | ||
* | ||
* change, changeByName - прослойка над setValue | ||
* */ | ||
changeByName(name: string, value: any): void; | ||
cleanChanges(): void; | ||
@@ -86,4 +82,4 @@ change(values?: Values): void; | ||
protected mergeValues(values: Values): void; | ||
depend(item: any): () => void; | ||
unsubscribe(item: any): void; | ||
depend(item: any): () => void; | ||
dependInput(name: string, i: any): () => void; | ||
@@ -90,0 +86,0 @@ /** |
import EventEmitter from "jenesius-event-emitter"; | ||
import Form from "./Form"; | ||
export default class Input extends EventEmitter { | ||
parentForm: Form; | ||
parentForm?: Form; | ||
name: string; | ||
@@ -9,2 +9,3 @@ validation: any[]; | ||
get value(): import("../types").Values | undefined; | ||
set value(v: import("../types").Values | undefined); | ||
get disabled(): boolean; | ||
@@ -11,0 +12,0 @@ change(v: any): void; |
@@ -7,1 +7,5 @@ export interface Values { | ||
export declare type ValidationGuard = () => void; | ||
export interface OptionRow { | ||
title: string; | ||
value: any; | ||
} |
/*! | ||
* jenesius-vue-form v2.0.8 | ||
* jenesius-vue-form v2.0.9 | ||
* (c) 2022 Jenesius | ||
@@ -83,2 +83,4 @@ * @license MIT | ||
var checkPrimitiveType = (v) => v === null || v === undefined || Array.isArray(v) || typeof v !== 'object'; | ||
/** | ||
@@ -109,3 +111,3 @@ * @description Мержит два объекта, полностью не перезаписываю значения. | ||
} | ||
if (typeof newValues !== 'object' || newValues === null) | ||
if (checkPrimitiveType(newValues)) | ||
set(formValues, newValues, path); | ||
@@ -124,4 +126,2 @@ else { | ||
var checkPrimitiveType = (v) => v === null || v === undefined || typeof v !== 'object'; | ||
/** | ||
@@ -195,4 +195,6 @@ * @description Метод вернёт новый объект, заменив все примитивные значения | ||
// last item | ||
if (index === path.length - 1) | ||
if (index === path.length - 1) { | ||
// value = JSON.parse(JSON.stringify(value)) | ||
link[name] = value; | ||
} | ||
else { | ||
@@ -292,3 +294,3 @@ link = link[name] || (() => { | ||
static getParentForm() { | ||
return vue.inject(Form.PROVIDE_NAME); | ||
return vue.inject(Form.PROVIDE_NAME, undefined); | ||
} | ||
@@ -368,12 +370,2 @@ /** | ||
} | ||
/** | ||
* @description Частный случай setValues, используется для input элементов. | ||
* | ||
* change, changeByName - прослойка над setValue | ||
* */ | ||
changeByName(name, value) { | ||
this.setValues({ | ||
[name]: value | ||
}); | ||
} | ||
cleanChanges() { | ||
@@ -401,2 +393,3 @@ __classPrivateFieldSet(this, _Form_changes, {}, "f"); | ||
} | ||
this.emit(Form.EVENT_VALUE, values); | ||
this.changeValuesOfItem(this.values); | ||
@@ -414,2 +407,6 @@ } | ||
} | ||
depend(item) { | ||
this.dependencies.push(item); | ||
return () => this.unsubscribe(item); | ||
} | ||
unsubscribe(item) { | ||
@@ -421,6 +418,2 @@ const index = this.dependencies.indexOf(item); | ||
} | ||
depend(item) { | ||
this.dependencies.push(item); | ||
return () => this.unsubscribe(item); | ||
} | ||
dependInput(name, i) { | ||
@@ -493,2 +486,3 @@ i.name = name; | ||
disable(name) { | ||
this.emit(Form.EVENT_UPDATE_ABILITY, name); | ||
if (name) | ||
@@ -500,2 +494,3 @@ this.disableByName(name); | ||
enable(name) { | ||
this.emit(Form.EVENT_UPDATE_ABILITY, name); | ||
if (name) | ||
@@ -585,2 +580,4 @@ this.enableByName(name); | ||
Form.EVENT_SAVE = 'save'; | ||
Form.EVENT_VALUE = 'value'; | ||
Form.EVENT_UPDATE_ABILITY = 'update:ability'; | ||
/** | ||
@@ -640,9 +637,18 @@ * @description Вызывается всякий раз, когда форма была изменена. Внимание! | ||
get value() { | ||
return this.parentForm.getValueByName(this.name); | ||
var _a; | ||
return (_a = this.parentForm) === null || _a === void 0 ? void 0 : _a.getValueByName(this.name); | ||
} | ||
set value(v) { | ||
var _a; | ||
(_a = this.parentForm) === null || _a === void 0 ? void 0 : _a.setValues({ | ||
[this.name]: v | ||
}); | ||
} | ||
get disabled() { | ||
return this.parentForm.getDisabledByName(this.name); | ||
var _a; | ||
return ((_a = this.parentForm) === null || _a === void 0 ? void 0 : _a.getDisabledByName(this.name)) || false; | ||
} | ||
change(v) { | ||
this.parentForm.input(this.name, v); | ||
var _a; | ||
(_a = this.parentForm) === null || _a === void 0 ? void 0 : _a.input(this.name, v); | ||
} | ||
@@ -674,2 +680,3 @@ /** | ||
function useInputController(input) { | ||
var _a; | ||
const state = vue.reactive({ | ||
@@ -698,5 +705,7 @@ value: input.value, | ||
}; | ||
const off = input.parentForm.dependInput(input.name, controls); | ||
const off = (_a = input.parentForm) === null || _a === void 0 ? void 0 : _a.dependInput(input.name, controls); | ||
vue.onUnmounted(() => { | ||
off(); | ||
if (off) { | ||
off(); | ||
} | ||
}); | ||
@@ -742,4 +751,4 @@ return state; | ||
var css_248z = "\n.container__input-text[data-v-4dc31c1e]{\r\n display: flex;\r\n flex-direction: column;\n}\n.widget-input-text[data-v-4dc31c1e]{\r\n height: 30px;\r\n border-radius: 4px;\r\n border: 1px solid #c8c8c8;\r\n outline: none;\r\n padding: 0 4px;\r\n color: #1c1c1c;\n}\n.widget-input-text[data-v-4dc31c1e]:focus{\r\n border-color: #b2b2b2;\n}\n.widget-input__label[data-v-4dc31c1e]{\r\n color: #333;\r\n font-size: 13px;\r\n margin: 4px 0;\n}\r\n"; | ||
styleInject(css_248z); | ||
var css_248z$8 = "\n.widget-input-wrap[data-v-5a53a125]{\r\n display: flex;\r\n flex-direction: column;\n}\n.widget-input__label[data-v-5a53a125]{\r\n color: #333;\r\n font-size: 13px;\r\n margin: 4px 0;\n}\n.input-errors[data-v-5a53a125]{\r\n display: flex;\r\n flex-direction: column;\r\n gap: 5px;\r\n padding: 5px 0;\n}\n.input-error-label[data-v-5a53a125]{\r\n color: red;\r\n margin: 0;\r\n font-size: 15px;\n}\r\n"; | ||
styleInject(css_248z$8); | ||
@@ -754,9 +763,39 @@ var _export_sfc = (sfc, props) => { | ||
const _hoisted_1 = { class: "container__input-text" }; | ||
const _hoisted_2 = { | ||
const _hoisted_1$6 = { class: "widget-input-wrap" }; | ||
const _hoisted_2$5 = { | ||
key: 0, | ||
class: "widget-input__label" | ||
}; | ||
const _hoisted_3 = ["value", "disabled"]; | ||
const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({ | ||
const _hoisted_3$2 = { class: "input-errors" }; | ||
const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "input-wrap", | ||
props: { | ||
label: { type: String, required: false }, | ||
errors: { type: Array, required: true } | ||
}, | ||
setup(__props) { | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [ | ||
__props.label ? (vue.openBlock(), vue.createElementBlock("p", _hoisted_2$5, vue.toDisplayString(__props.label), 1)) : vue.createCommentVNode("v-if", true), | ||
vue.renderSlot(_ctx.$slots, "default", {}, void 0, true), | ||
vue.createCommentVNode("Errors"), | ||
vue.createElementVNode("div", _hoisted_3$2, [ | ||
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.errors, (str, index) => { | ||
return vue.openBlock(), vue.createElementBlock("p", { | ||
class: "input-error-label", | ||
key: index | ||
}, vue.toDisplayString(str), 1); | ||
}), 128)) | ||
]) | ||
]); | ||
}; | ||
} | ||
}); | ||
var InputWrap = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-5a53a125"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-wrap.vue"]]); | ||
var css_248z$7 = "\n.widget-input-text[data-v-4dc31c1e]{\r\n height: 35px;\r\n border-radius: 4px;\r\n border: 1px solid #c8c8c8;\r\n outline: none;\r\n padding: 0 4px;\r\n color: #1c1c1c;\n}\n.widget-input-text[data-v-4dc31c1e]:focus{\r\n border-color: #b2b2b2;\n}\n.widget-input-text[data-v-4dc31c1e]:disabled{\r\n background-color: #e9e9e9;\n}\r\n"; | ||
styleInject(css_248z$7); | ||
const _hoisted_1$5 = ["value", "disabled"]; | ||
const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-text", | ||
@@ -771,11 +810,55 @@ props: { | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [ | ||
__props.label ? (vue.openBlock(), vue.createElementBlock("p", _hoisted_2, vue.toDisplayString(__props.label), 1)) : vue.createCommentVNode("v-if", true), | ||
vue.createElementVNode("input", { | ||
class: "widget-input-text", | ||
type: "text", | ||
value: __props.modelValue, | ||
onInput: _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", $event.target.value)), | ||
disabled: __props.disabled | ||
}, null, 40, _hoisted_3) | ||
return vue.openBlock(), vue.createBlock(InputWrap, { label: __props.label }, { | ||
default: vue.withCtx(() => [ | ||
vue.createElementVNode("input", { | ||
class: "widget-input-text", | ||
type: "text", | ||
value: __props.modelValue, | ||
onInput: _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", $event.target.value)), | ||
disabled: __props.disabled | ||
}, null, 40, _hoisted_1$5) | ||
]), | ||
_: 1 | ||
}, 8, ["label"]); | ||
}; | ||
} | ||
}); | ||
var WidgetInputText = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-4dc31c1e"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\widget-input-text.vue"]]); | ||
function clickOutside(el, callback) { | ||
function handleClickOutside(e) { | ||
// Clicked outside | ||
if (!el.contains(e.target)) { | ||
callback(); | ||
document.removeEventListener('click', handleClickOutside); | ||
} | ||
} | ||
document.addEventListener('click', handleClickOutside); | ||
// Return off hook | ||
return () => { | ||
document.removeEventListener('click', handleClickOutside); | ||
}; | ||
} | ||
var css_248z$6 = "\n.select-options[data-v-e6a5f7be]{\r\n background-color: white;\r\n z-index: 2;\r\n position: relative;\r\n padding: 2px 2px;\r\n\r\n transition: max-height 200ms;\r\n max-height: 200px;\n}\n.select-options-item[data-v-e6a5f7be]{\r\n padding: 8px 6px;\r\n margin: 0;\r\n\r\n color: #333333;\r\n font-size: 13px;\r\n transition: background-color 0.2s;\n}\n.select-options-item[data-v-e6a5f7be]:hover{\r\n background-color: #f8f8f8;\n}\n.select-options-item_active[data-v-e6a5f7be]{\r\n background-color: #f4f4f4 !important;\r\n border-radius: 3px;\n}\r\n"; | ||
styleInject(css_248z$6); | ||
const _hoisted_1$4 = { class: "select-options" }; | ||
const _hoisted_2$4 = ["onClick"]; | ||
const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-select-options", | ||
props: { | ||
options: { type: Array, required: true }, | ||
value: { type: null, required: true } | ||
}, | ||
setup(__props) { | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4, [ | ||
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.options, (option) => { | ||
return vue.openBlock(), vue.createElementBlock("p", { | ||
class: vue.normalizeClass(["select-options-item", { "select-options-item_active": __props.value === option.value }]), | ||
key: option.value, | ||
onClick: ($event) => _ctx.$emit("select", option.value) | ||
}, vue.toDisplayString(option.title), 11, _hoisted_2$4); | ||
}), 128)) | ||
]); | ||
@@ -785,11 +868,292 @@ }; | ||
}); | ||
var WidgetInputText = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-4dc31c1e"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\widget-input-text.vue"]]); | ||
var WidgetInputSelectOptions = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-e6a5f7be"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-select\\widget-input-select-options.vue"]]); | ||
var css_248z$5 = "\n.arrow[data-v-76555508] {\r\n border: solid #424242;\r\n border-width: 0 2px 2px 0;\r\n display: inline-block;\r\n padding: 3px;\r\n margin: 8px 10px 10px 10px;\r\n transition: transform 150ms;\n}\n.down[data-v-76555508] {\r\n transform: rotate(45deg);\r\n -webkit-transform: rotate(45deg);\n}\n.arrow_active[data-v-76555508]{\r\n transform: rotate(225deg);\n}\n.input-select__current[data-v-76555508]{\r\n height: 35px;\r\n display: flex;\r\n align-items: center;\n}\n.input-select-title[data-v-76555508]{\r\n padding: 0 6px;\r\n color: #1c1c1c;\r\n font-size: 14px;\r\n\r\n flex-grow: 1;\n}\r\n"; | ||
styleInject(css_248z$5); | ||
const _hoisted_1$3 = { class: "input-select__current" }; | ||
const _hoisted_2$3 = { class: "input-select-title" }; | ||
const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-select-current", | ||
props: { | ||
active: { type: Boolean, required: true }, | ||
title: { type: String, required: true } | ||
}, | ||
setup(__props) { | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [ | ||
vue.createElementVNode("p", _hoisted_2$3, vue.toDisplayString(__props.title), 1), | ||
vue.createElementVNode("i", { | ||
class: vue.normalizeClass(["arrow down", { "arrow_active": __props.active }]) | ||
}, null, 2) | ||
]); | ||
}; | ||
} | ||
}); | ||
var WidgetInputSelectCurrent = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-76555508"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-select\\widget-input-select-current.vue"]]); | ||
var css_248z$4 = "\n.container__input-select-wrap[data-v-6636ba60]{\r\n height: 35px;\r\n max-height: 35px;\n}\n.input-select[data-v-6636ba60]{\r\n border: 1px solid #c8c8c8;\r\n border-radius: 4px;\r\n color: #1c1c1c;\r\n cursor: pointer;\r\n overflow: hidden;\n}\n.fade-enter-active[data-v-6636ba60],\r\n .fade-leave-active[data-v-6636ba60] {\r\n transition: max-height 0.2s;\n}\n.fade-enter-from[data-v-6636ba60],\r\n .fade-leave-to[data-v-6636ba60] {\r\n max-height: 0;\n}\n.input-select_disabled[data-v-6636ba60]{\r\n background-color: #e9e9e9;\r\n cursor: default;\n}\r\n\r\n\r\n\r\n\r\n"; | ||
styleInject(css_248z$4); | ||
const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-select", | ||
props: { | ||
label: { type: String, required: false }, | ||
modelValue: { type: null, required: true }, | ||
disabled: { type: Boolean, required: false }, | ||
options: { type: Array, required: true }, | ||
placeholder: { type: String, required: false } | ||
}, | ||
emits: ["update:modelValue"], | ||
setup(__props, { emit }) { | ||
const props = __props; | ||
const inputSelectWrap = vue.ref(); | ||
const active = vue.ref(false); | ||
let off; | ||
function setActive(v = !active.value) { | ||
if (props.disabled) | ||
return active.value = false; | ||
if (v) { | ||
off = clickOutside(inputSelectWrap.value, setActive.bind(null, false)); | ||
} else { | ||
off?.(); | ||
} | ||
active.value = v; | ||
} | ||
function onInput(v) { | ||
if (props.disabled) | ||
return; | ||
emit("update:modelValue", v); | ||
} | ||
const title = vue.computed(() => { | ||
const selected = props.options.find((x) => x.value === props.modelValue); | ||
if (selected) | ||
return selected.title; | ||
return props.placeholder || ""; | ||
}); | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createBlock(InputWrap, { label: __props.label }, { | ||
default: vue.withCtx(() => [ | ||
vue.createElementVNode("div", { | ||
class: "container__input-select-wrap", | ||
ref_key: "inputSelectWrap", | ||
ref: inputSelectWrap | ||
}, [ | ||
vue.createElementVNode("div", { | ||
class: vue.normalizeClass(["input-select", { | ||
"input-select_disabled": __props.disabled | ||
}]) | ||
}, [ | ||
vue.createVNode(WidgetInputSelectCurrent, { | ||
title: vue.unref(title), | ||
active: active.value, | ||
onClick: _cache[0] || (_cache[0] = ($event) => setActive()) | ||
}, null, 8, ["title", "active"]), | ||
vue.createVNode(vue.Transition, { name: "fade" }, { | ||
default: vue.withCtx(() => [ | ||
active.value ? (vue.openBlock(), vue.createBlock(WidgetInputSelectOptions, { | ||
key: 0, | ||
value: __props.modelValue, | ||
options: __props.options, | ||
onSelect: _cache[1] || (_cache[1] = ($event) => (onInput($event), setActive(false))) | ||
}, null, 8, ["value", "options"])) : vue.createCommentVNode("v-if", true) | ||
]), | ||
_: 1 | ||
}) | ||
], 2) | ||
], 512) | ||
]), | ||
_: 1 | ||
}, 8, ["label"]); | ||
}; | ||
} | ||
}); | ||
var WidgetInputSelect = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-6636ba60"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-select\\widget-input-select.vue"]]); | ||
var css_248z$3 = "\n.input-radio-container[data-v-758d019e]{\r\n display: flex;\r\n flex-direction: column;\r\n gap: 14px;\n}\n.input-radio[data-v-758d019e]{\r\n display: flex;\r\n gap: 13px;\r\n align-items: center;\r\n cursor: pointer;\n}\n.input-radio-button[data-v-758d019e]{\r\n height: 20px;\r\n width: 20px;\r\n border-radius: 50%;\r\n border: 1px solid #c8c8c8;\r\n\r\n cursor: pointer;\r\n display: grid;\r\n place-items: center;\n}\n.input-radio-title[data-v-758d019e]{\r\n color: #1c1c1c;\r\n margin: 0;\n}\n.input-radio-button-active[data-v-758d019e]{\r\n height: 12px;\r\n width: 12px;\r\n\r\n border-radius: 50%;\r\n background-color: #4e74ff;\r\n border: 1px solid #f0f0f0;\n}\n.fade-enter-active[data-v-758d019e],\r\n .fade-leave-active[data-v-758d019e] {\r\n transition: 0.3s;\n}\n.fade-enter-from[data-v-758d019e],\r\n .fade-leave-to[data-v-758d019e] {\r\n transform: scale(0);\n}\n.input-radio_disabled[data-v-758d019e]{\r\n cursor: default;\n}\n.input-radio_disabled .input-radio-button[data-v-758d019e]{\r\n background-color: #e9e9e9;\n}\n.input-radio_disabled .input-radio-button-active[data-v-758d019e]{\r\n background-color: #bac7f8\n}\r\n"; | ||
styleInject(css_248z$3); | ||
const _hoisted_1$2 = { class: "input-radio-container" }; | ||
const _hoisted_2$2 = ["onClick"]; | ||
const _hoisted_3$1 = { class: "input-radio-button" }; | ||
const _hoisted_4$1 = { | ||
key: 0, | ||
class: "input-radio-button-active" | ||
}; | ||
const _hoisted_5$1 = { class: "input-radio-title" }; | ||
const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-radio", | ||
props: { | ||
label: { type: String, required: false }, | ||
options: { type: Array, required: true }, | ||
modelValue: { type: null, required: true }, | ||
disabled: { type: Boolean, required: true } | ||
}, | ||
emits: ["update:modelValue"], | ||
setup(__props, { emit }) { | ||
const props = __props; | ||
function onInput(v) { | ||
if (props.disabled) | ||
return; | ||
emit("update:modelValue", v); | ||
} | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createBlock(InputWrap, { label: __props.label }, { | ||
default: vue.withCtx(() => [ | ||
vue.createElementVNode("div", _hoisted_1$2, [ | ||
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.options, (item) => { | ||
return vue.openBlock(), vue.createElementBlock("div", { | ||
class: vue.normalizeClass(["input-radio", { | ||
"input-radio_active": __props.modelValue === item.value, | ||
"input-radio_disabled": __props.disabled | ||
}]), | ||
key: item.value, | ||
onClick: ($event) => onInput(item.value) | ||
}, [ | ||
vue.createElementVNode("div", _hoisted_3$1, [ | ||
vue.createVNode(vue.Transition, { name: "fade" }, { | ||
default: vue.withCtx(() => [ | ||
item.value === __props.modelValue ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$1)) : vue.createCommentVNode("v-if", true) | ||
]), | ||
_: 2 | ||
}, 1024) | ||
]), | ||
vue.createElementVNode("p", _hoisted_5$1, vue.toDisplayString(item.title), 1) | ||
], 10, _hoisted_2$2); | ||
}), 128)) | ||
]) | ||
]), | ||
_: 1 | ||
}, 8, ["label"]); | ||
}; | ||
} | ||
}); | ||
var WidgetInputRadio = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-758d019e"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-radio\\widget-input-radio.vue"]]); | ||
var css_248z$2 = "\n.input-checkbox-container[data-v-8af15344] {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 14px;\n}\n.input-checkbox-button[data-v-8af15344]{\r\n width: 18px;\r\n height: 18px;\r\n margin: 0;\r\n border: 1px solid #c8c8c8;\r\n border-radius: 3px;\r\n display: grid;\r\n place-content: center;\n}\n.input-checkbox_active[data-v-8af15344]{\r\n background-color: #4e74ff;\n}\n.input-checkbox_disabled[data-v-8af15344]{\r\n background-color: #e9e9e9;\n}\n.input-checkbox_disabled.input-checkbox_active[data-v-8af15344]{\r\n background-color: #bac7f8;\n}\n.input-checkbox[data-v-8af15344]{\r\n cursor: pointer;\r\n display: flex;\r\n gap: 13px;\n}\n.input-checkbox_disabled[data-v-8af15344]{\r\n cursor: default;\n}\n.input-checkbox-title[data-v-8af15344]{\r\n color: #1c1c1c;\r\n margin: 0;\n}\ni.check[data-v-8af15344] {\r\n display: none;\r\n width: 4px;\r\n height: 7px;\r\n border: solid white;\r\n border-width: 0 2px 2px 0;\r\n transform: rotate( 45deg);\r\n margin: 1px 1px 4px 1px;\n}\n.input-checkbox_active>i[data-v-8af15344]{\r\n display: inline-block;\n}\r\n"; | ||
styleInject(css_248z$2); | ||
const _withScopeId$1 = (n) => (vue.pushScopeId("data-v-8af15344"), n = n(), vue.popScopeId(), n); | ||
const _hoisted_1$1 = { class: "input-checkbox-container" }; | ||
const _hoisted_2$1 = ["onClick"]; | ||
const _hoisted_3 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "check" }, null, -1)); | ||
const _hoisted_4 = [ | ||
_hoisted_3 | ||
]; | ||
const _hoisted_5 = { class: "input-checkbox-title" }; | ||
const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-checkbox", | ||
props: { | ||
label: { type: String, required: false }, | ||
options: { type: Array, required: true }, | ||
modelValue: { type: null, required: true }, | ||
disabled: { type: Boolean, required: true } | ||
}, | ||
emits: ["update:modelValue"], | ||
setup(__props, { emit }) { | ||
const props = __props; | ||
function isActive(v) { | ||
return props.modelValue?.includes?.(v); | ||
} | ||
function toggle(v) { | ||
const arr = Array.isArray(props.modelValue) ? props.modelValue : []; | ||
const index = arr.indexOf(v); | ||
if (index === -1) { | ||
arr.push(v); | ||
} else | ||
arr.splice(index, 1); | ||
return arr; | ||
} | ||
function onInput(v) { | ||
if (props.disabled) | ||
return; | ||
emit("update:modelValue", toggle(v)); | ||
} | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createBlock(InputWrap, { label: __props.label }, { | ||
default: vue.withCtx(() => [ | ||
vue.createTextVNode(vue.toDisplayString(__props.modelValue) + " ", 1), | ||
vue.createElementVNode("div", _hoisted_1$1, [ | ||
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.options, (item) => { | ||
return vue.openBlock(), vue.createElementBlock("div", { | ||
key: item, | ||
class: "input-checkbox", | ||
onClick: ($event) => onInput(item.value) | ||
}, [ | ||
vue.createElementVNode("div", { | ||
class: vue.normalizeClass(["input-checkbox-button", { | ||
"input-checkbox_active": isActive(item.value), | ||
"input-checkbox_disabled": __props.disabled | ||
}]) | ||
}, _hoisted_4, 2), | ||
vue.createElementVNode("p", _hoisted_5, vue.toDisplayString(item.title), 1) | ||
], 8, _hoisted_2$1); | ||
}), 128)) | ||
]) | ||
]), | ||
_: 1 | ||
}, 8, ["label"]); | ||
}; | ||
} | ||
}); | ||
var WidgetInputCheckbox = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-8af15344"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-checkbox\\widget-input-checkbox.vue"]]); | ||
var css_248z$1 = "\n.input-switch-container[data-v-598ca340]{\r\n display: flex;\r\n gap: 12px;\r\n align-items: center;\n}\n.input-switch[data-v-598ca340] {\r\n width: 38px;\r\n border-radius: 11px;\r\n border: 1px solid #c8c8c8;\r\n height: 21px;\r\n outline: none;\r\n box-sizing: border-box;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\n}\n.input-switch-button[data-v-598ca340]{\r\n height: 15px;\r\n width: 15px;\r\n background-color: #c8c8c8;\r\n border-radius: 50%;\r\n transform: translateX(3px);\r\n transition: transform 0.1s, color 0.1s;\n}\n.input-switch-button_active[data-v-598ca340]{\r\n background-color: #4e74ff;\r\n transform: translateX(18px);\n}\n.input-switch-title[data-v-598ca340]{\r\n margin: 0;\r\n color: #333;\n}\n.input-switch_disabled[data-v-598ca340]{\r\n background-color: #e9e9e9;\r\n cursor: default;\n}\n.input-switch_disabled .input-switch-button_active[data-v-598ca340]{\r\n background-color: #bac7f8;\n}\r\n"; | ||
styleInject(css_248z$1); | ||
const _withScopeId = (n) => (vue.pushScopeId("data-v-598ca340"), n = n(), vue.popScopeId(), n); | ||
const _hoisted_1 = { class: "input-switch-container" }; | ||
const _hoisted_2 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("p", { class: "input-switch-title widget-input-title" }, "123", -1)); | ||
const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "widget-input-switch", | ||
props: { | ||
label: { type: String, required: false }, | ||
modelValue: { type: null, required: true }, | ||
disabled: { type: Boolean, required: true } | ||
}, | ||
emits: ["update:modelValue"], | ||
setup(__props, { emit }) { | ||
const props = __props; | ||
function onInput(v = !props.modelValue) { | ||
if (props.disabled) | ||
return; | ||
emit("update:modelValue", v); | ||
} | ||
return (_ctx, _cache) => { | ||
return vue.openBlock(), vue.createBlock(InputWrap, null, { | ||
default: vue.withCtx(() => [ | ||
vue.createElementVNode("div", _hoisted_1, [ | ||
vue.createElementVNode("div", { | ||
class: vue.normalizeClass(["input-switch", { | ||
"input-switch_disabled": __props.disabled | ||
}]), | ||
onClick: _cache[0] || (_cache[0] = ($event) => onInput()) | ||
}, [ | ||
vue.createElementVNode("div", { | ||
class: vue.normalizeClass(["input-switch-button", { | ||
"input-switch-button_active": !!__props.modelValue | ||
}]) | ||
}, null, 2) | ||
], 2), | ||
_hoisted_2 | ||
]) | ||
]), | ||
_: 1 | ||
}); | ||
}; | ||
} | ||
}); | ||
var WidgetInputSwitch = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-598ca340"], ["__file", "H:\\V3Project\\vue-form\\plugin\\widgets\\inputs\\input-switch\\widget-input-switch.vue"]]); | ||
var css_248z = "\n.widget-input__label{\r\n color: #333;\r\n font-size: 13px;\r\n margin: 4px 0;\n}\r\n"; | ||
styleInject(css_248z); | ||
const _sfc_main = /* @__PURE__ */ vue.defineComponent({ | ||
__name: "input-field", | ||
props: { | ||
type: { type: String, required: true }, | ||
name: { type: String, required: true }, | ||
type: { type: String, required: false, default: "text" }, | ||
name: { type: String, required: false }, | ||
label: { type: String, required: false }, | ||
validation: { type: Array, required: false, default: () => [] } | ||
validation: { type: Array, required: false, default: () => [] }, | ||
options: { type: Array, required: false } | ||
}, | ||
@@ -799,6 +1163,17 @@ setup(__props) { | ||
const store = { | ||
text: WidgetInputText | ||
text: WidgetInputText, | ||
select: WidgetInputSelect, | ||
radio: WidgetInputRadio, | ||
checkbox: WidgetInputCheckbox, | ||
switch: WidgetInputSwitch | ||
}; | ||
const componentItem = vue.computed(() => store[props.type] || store.text); | ||
const { state, input } = useInputState(props.name, props.validation); | ||
vue.watch(() => props.modelValue, (a, b) => { | ||
if (a === b) | ||
return; | ||
input.value = props.modelValue; | ||
}, { | ||
immediate: true | ||
}); | ||
return (_ctx, _cache) => { | ||
@@ -810,4 +1185,5 @@ return vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(componentItem)), { | ||
disabled: vue.unref(state).disabled, | ||
errors: vue.unref(state).errors | ||
}, null, 8, ["modelValue", "label", "disabled", "errors"]); | ||
errors: vue.unref(state).errors, | ||
options: __props.options | ||
}, null, 8, ["modelValue", "label", "disabled", "errors", "options"]); | ||
}; | ||
@@ -814,0 +1190,0 @@ } |
{ | ||
"name": "jenesius-vue-form", | ||
"version": "2.0.8", | ||
"version": "2.0.9", | ||
"description": "Heavy form system for Vue.js", | ||
@@ -5,0 +5,0 @@ "author": "Jenesius", |
# Jenesius Vue Form | ||
Heavy form system for Vue.js v3. Library provides a wide range of functionality and interaction with form elements. | ||
Heavy form system for Vue.js ( Only 3 Version ). Library provides a wide range of | ||
functionality and interaction with form elements. | ||
@@ -8,14 +9,16 @@ ## Links | ||
- [GitHub](https://github.com/Jenesius/vue-form) | ||
## Reason | ||
## Reason For Use | ||
- 🦵 multifunctional form logic. Херово звучит. Многофункциональная система для | ||
работы с формой. Или Большой выбор функционала для работы и управления формой. | ||
- 🖕 you can use this library with your own input components. | ||
- 🤝 create interface using composite and aggregate logical. Read more <- ссылку | ||
- 💪 The functionality of the form allows you to flexibly work with dependent elements. | ||
- 🤝 Create complex interfaces with lots of dependencies. One page can contain many | ||
forms that will be managed from one place. | ||
- ✍ Connect your own input fields to the form. This gives flexibility and | ||
independence on the part of the site design. | ||
*Where the spirit does not work with the hand there is no art.* @Leonardo da Vinci | ||
## Main Form | ||
Для создания формы, необходимо просто создать экземпляр. JenesiusVueForm сделает | ||
большую часть работы за вас. | ||
```js | ||
To create a form, you just need to create an instance. JenesiusVueForm will do | ||
most of the work for you. | ||
```ts | ||
import {Form} from "jenesius-vue-modal" | ||
@@ -26,3 +29,3 @@ const form = new Form() | ||
### Main Form state | ||
Реактивное состояния формы можно получить из *useFormState* хука: | ||
The reactive form state can be obtained from the **useFormState** hook: | ||
```js | ||
@@ -34,6 +37,4 @@ import {useFormState} from "jenesius-vue-modal" | ||
## Proxy Form | ||
Для работы удобно использовать композитный элемент, который хранит в себе другие | ||
инпуты, но не добавляет никакой логики для работы с формой. Отличный пример тому | ||
инпут address, который в себе может хранить такие поля, как: city, country, street. | ||
Composite objects (For example, Address, which contains country, city etc.) | ||
can be created by calling the **useProxyState** hook. | ||
```ts | ||
@@ -43,5 +44,16 @@ import {useProxyState} from "jenesius-vue-modal" | ||
``` | ||
In this example, the Composite field will automatically subscribe to the parent form, | ||
and will also serve as a bridge for all its child elements. | ||
## Input | ||
Для того чтобы связать поле input с формой нужно просто выполнить следующий хук: | ||
When using the built-in input field, the library will do everything for you. | ||
You don't need to sign it on the form yourself. | ||
```ts | ||
import {InputField} from "jenesius-vue-form"; | ||
``` | ||
### Custom Input | ||
In most cases, you will use your own input fields. | ||
In this case, you need to implement a small layer: | ||
```vue | ||
@@ -57,36 +69,10 @@ <input type = "text" | ||
const {state, input} = useInputState(props.name) | ||
// state - {value, disabled} | ||
// state - {value, disabled, errors} | ||
``` | ||
- **input** - контроллер для работы с виджетом. Необходим для обработки изменения | ||
поля ввода. | ||
- **input** - an instance of Input which has several methods to work with | ||
form interaction. | ||
## Validation | ||
Для валидации формы используется метод **validate**, который вернёт true в случае | ||
если всё зависимые элементы - валидны: | ||
```js | ||
form.validate(); // true or false | ||
``` | ||
## Основная логика | ||
1. Значения хранятся только в **агрегатном элементе** | ||
- **агрегатный элемент** - не зависимый(или слабо зависимый) экземпляр Form. Зна | ||
- чения инпутов, disabled поля, hidden поля и т.д. должны храниться в ближайшей | ||
*aggregate* Form. | ||
## InputField widgets | ||
Данная библиотека также предоставляет набор компонент, которые можно легко испол | ||
ьзовать для построения форм: | ||
```vue | ||
<input-field type = "text" name = "username"/> | ||
<script> | ||
import {InputField} from "jenesius-vue-form" | ||
</script> | ||
``` | ||
- **type** - тип инпута. Принимает одно из следующих значения: text. По умолчанию: | ||
text | ||
- **name** - имя контролла, по которому он будет привязан к форме. | ||
- **label** метка элемента. Используется как заголовок. | ||
- **validation** массив обработчиков валидности поля. | ||
## Full Functionality | ||
I recommend going to the [documentation site](http://form.jenesius.com/), | ||
which provides information on | ||
validation, form lock/unlock, and all the states of the form and input fields. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
74865
39
1668
74
3