diff --git a/dist/ngeblog-admin-assets/Form-Cq7QSysK.js b/dist/ngeblog-admin-assets/Form-Cz729KU0.js similarity index 95% rename from dist/ngeblog-admin-assets/Form-Cq7QSysK.js rename to dist/ngeblog-admin-assets/Form-Cz729KU0.js index d95ae65..a0b299b 100644 --- a/dist/ngeblog-admin-assets/Form-Cq7QSysK.js +++ b/dist/ngeblog-admin-assets/Form-Cz729KU0.js @@ -1,4 +1,4 @@ -import { r as reactive, m as markRaw, d as defineComponent, c as customRef, a as ref, w as watchEffect, n as nextTick, u as unref, o as onBeforeUnmount, h as h$1, T as Teleport, g as getCurrentInstance, _ as _export_sfc, b as watch, e as onMounted, f as openBlock, i as createElementBlock, j as createBaseVNode, k as normalizeClass, l as createCommentVNode, p as createVNode, F as Fragment$1, q as renderList, t as toDisplayString, s as withCtx, v as withDirectives, x as vModelSelect, y as _sfc_main$4, z as vModelText, A as createStaticVNode, B as computed, C as shallowRef, D as triggerRef, E as onScopeDispose, G as onUnmounted, H as inject, I as cloneVNode, J as provide, K as toRaw, L as isRef, M as shallowReadonly, N as getCurrentScope, O as createBlock, P as renderSlot, Q as normalizeStyle, R as Transition, S as mergeProps, U as createTextVNode, V as axios, W as useForm, X as apiBasePath, Y as resolveComponent, Z as Container, $ as SkeletonContent, a0 as withModifiers, a1 as vModelCheckbox, a2 as useRoute, a3 as useRouter, a4 as slugify, a5 as _sfc_main$5 } from "./ngeblog.js"; +import { r as reactive, m as markRaw, d as defineComponent, c as customRef, a as ref, w as watchEffect, n as nextTick, u as unref, o as onBeforeUnmount, h as h$1, T as Teleport, g as getCurrentInstance, _ as _export_sfc, b as watch, e as onMounted, f as openBlock, i as createElementBlock, j as createBaseVNode, k as normalizeClass, l as createCommentVNode, p as createVNode, F as Fragment$1, q as renderList, t as toDisplayString, s as withCtx, v as withDirectives, x as vModelSelect, y as FormControl, z as vModelText, A as createStaticVNode, B as computed, C as shallowRef, D as triggerRef, E as onScopeDispose, G as onUnmounted, H as inject, I as cloneVNode, J as provide, K as toRaw, L as isRef, M as shallowReadonly, N as getCurrentScope, O as createBlock, P as renderSlot, Q as normalizeStyle, R as Transition, S as mergeProps, U as createTextVNode, V as useRoute, W as useRouter, X as useAxiosFetch, Y as useForm, Z as apiBasePath, $ as resolveComponent, a0 as Container, a1 as slugify, a2 as SkeletonContent, a3 as withModifiers, a4 as vModelCheckbox, a5 as NotFound } from "./ngeblog.js"; function OrderedMap(content) { this.content = content; } @@ -15362,6 +15362,65 @@ function markPasteRule(config) { } }); } +const Placeholder = Extension.create({ + name: "placeholder", + addOptions() { + return { + emptyEditorClass: "is-editor-empty", + emptyNodeClass: "is-empty", + placeholder: "Write something …", + showOnlyWhenEditable: true, + considerAnyAsEmpty: false, + showOnlyCurrent: true, + includeChildren: false + }; + }, + addProseMirrorPlugins() { + return [ + new Plugin({ + key: new PluginKey("placeholder"), + props: { + decorations: ({ doc: doc2, selection }) => { + var _a; + const active = this.editor.isEditable || !this.options.showOnlyWhenEditable; + const { anchor } = selection; + const decorations = []; + if (!active) { + return null; + } + const { firstChild } = doc2.content; + const isLeaf = firstChild && firstChild.type.isLeaf; + const isAtom = firstChild && firstChild.isAtom; + const isValidNode = this.options.considerAnyAsEmpty ? true : firstChild && firstChild.type.name === ((_a = doc2.type.contentMatch.defaultType) === null || _a === void 0 ? void 0 : _a.name); + const isEmptyDoc = doc2.content.childCount <= 1 && firstChild && isValidNode && (firstChild.nodeSize <= 2 && (!isLeaf || !isAtom)); + doc2.descendants((node, pos) => { + const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize; + const isEmpty = !node.isLeaf && !node.childCount; + if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) { + const classes = [this.options.emptyNodeClass]; + if (isEmptyDoc) { + classes.push(this.options.emptyEditorClass); + } + const decoration = Decoration.node(pos, pos + node.nodeSize, { + class: classes.join(" "), + "data-placeholder": typeof this.options.placeholder === "function" ? this.options.placeholder({ + editor: this.editor, + node, + pos, + hasAnchor + }) : this.options.placeholder + }); + decorations.push(decoration); + } + return this.options.includeChildren; + }); + return DecorationSet.create(doc2, decorations); + } + } + }) + ]; + } +}); const inputRegex$4 = /^\s*>\s$/; const Blockquote = Node$1.create({ name: "blockquote", @@ -17529,7 +17588,20 @@ const _sfc_main$3 = { const editorElement = ref(); onMounted(() => { editorElement.value = new Editor2({ - extensions: [StarterKit], + extensions: [ + StarterKit, + Placeholder.configure({ + // Use a placeholder: + placeholder: "Write something amazing 🔥" + // Use different placeholders depending on the node type: + // placeholder: ({ node }) => { + // if (node.type.name === 'heading') { + // return 'What’s the title?' + // } + // return 'Can you add some further context?' + // }, + }) + ], editorProps: { attributes: { class: "prose prose-sm sm:prose-base lg:prose-lg mx-auto focus:outline-none dark:prose-invert px-2" @@ -17571,85 +17643,151 @@ const _sfc_main$3 = { onClick: _cache[3] || (_cache[3] = ($event) => editorElement.value.chain().focus().toggleCode().run()), disabled: !editorElement.value.can().chain().focus().toggleCode().run() }, " code ", 10, _hoisted_6$3), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("paragraph") }]), - onClick: _cache[4] || (_cache[4] = ($event) => editorElement.value.chain().focus().setParagraph().run()) - }, " paragraph ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 1 - }) - }]), - onClick: _cache[5] || (_cache[5] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 1 }).run()) - }, " h1 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 2 - }) - }]), - onClick: _cache[6] || (_cache[6] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 2 }).run()) - }, " h2 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 3 - }) - }]), - onClick: _cache[7] || (_cache[7] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 3 }).run()) - }, " h3 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 4 - }) - }]), - onClick: _cache[8] || (_cache[8] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 4 }).run()) - }, " h4 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 5 - }) - }]), - onClick: _cache[9] || (_cache[9] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 5 }).run()) - }, " h5 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { - "is-active": editorElement.value.isActive("heading", { - level: 6 - }) - }]), - onClick: _cache[10] || (_cache[10] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 6 }).run()) - }, " h6 ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("bulletList") }]), - onClick: _cache[11] || (_cache[11] = ($event) => editorElement.value.chain().focus().toggleBulletList().run()) - }, " bullet list ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("orderedList") }]), - onClick: _cache[12] || (_cache[12] = ($event) => editorElement.value.chain().focus().toggleOrderedList().run()) - }, " ordered list ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("codeBlock") }]), - onClick: _cache[13] || (_cache[13] = ($event) => editorElement.value.chain().focus().toggleCodeBlock().run()) - }, " code block ", 2), - createBaseVNode("button", { - type: "button", - class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("blockquote") }]), - onClick: _cache[14] || (_cache[14] = ($event) => editorElement.value.chain().focus().toggleBlockquote().run()) - }, " blockquote ", 2), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("paragraph") }]), + onClick: _cache[4] || (_cache[4] = ($event) => editorElement.value.chain().focus().setParagraph().run()) + }, + " paragraph ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 1 + }) + }]), + onClick: _cache[5] || (_cache[5] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 1 }).run()) + }, + " h1 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 2 + }) + }]), + onClick: _cache[6] || (_cache[6] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 2 }).run()) + }, + " h2 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 3 + }) + }]), + onClick: _cache[7] || (_cache[7] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 3 }).run()) + }, + " h3 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 4 + }) + }]), + onClick: _cache[8] || (_cache[8] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 4 }).run()) + }, + " h4 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 5 + }) + }]), + onClick: _cache[9] || (_cache[9] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 5 }).run()) + }, + " h5 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { + "is-active": editorElement.value.isActive("heading", { + level: 6 + }) + }]), + onClick: _cache[10] || (_cache[10] = ($event) => editorElement.value.chain().focus().toggleHeading({ level: 6 }).run()) + }, + " h6 ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("bulletList") }]), + onClick: _cache[11] || (_cache[11] = ($event) => editorElement.value.chain().focus().toggleBulletList().run()) + }, + " bullet list ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("orderedList") }]), + onClick: _cache[12] || (_cache[12] = ($event) => editorElement.value.chain().focus().toggleOrderedList().run()) + }, + " ordered list ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("codeBlock") }]), + onClick: _cache[13] || (_cache[13] = ($event) => editorElement.value.chain().focus().toggleCodeBlock().run()) + }, + " code block ", + 2 + /* CLASS */ + ), + createBaseVNode( + "button", + { + type: "button", + class: normalizeClass(["border px-2 py-1", { "is-active": editorElement.value.isActive("blockquote") }]), + onClick: _cache[14] || (_cache[14] = ($event) => editorElement.value.chain().focus().toggleBlockquote().run()) + }, + " blockquote ", + 2 + /* CLASS */ + ), createBaseVNode("button", { type: "button", class: "border px-2 py-1", @@ -17665,13 +17803,13 @@ const _sfc_main$3 = { class: "border px-2 py-1", onClick: _cache[17] || (_cache[17] = ($event) => editorElement.value.chain().focus().clearNodes().run()) }, " clear nodes ") - ])) : createCommentVNode("", true), + ])) : createCommentVNode("v-if", true), createVNode(unref(EditorContent), { editor: editorElement.value }, null, 8, ["editor"]) ]); }; } }; -const ContentEditor = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-6ab0bc8b"]]); +const ContentEditor = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-5ea4f861"], ["__file", "/Users/antoni/Packages/ngeblog/resources/js/components/ContentEditor.vue"]]); const _hoisted_1$2 = { class: "collapse rounded border", open: "" @@ -17681,28 +17819,58 @@ const _hoisted_3$2 = { class: "collapse-content p-0" }; const _hoisted_4$2 = { class: "flex flex-col divide-y" }; const _hoisted_5$2 = { class: "relative grid grid-cols-3 justify-center gap-2 p-4 pt-8" }; const _hoisted_6$2 = { class: "absolute left-1 top-1 inline-flex h-8 w-8 items-center justify-center self-start rounded-full border bg-gray-200 p-2" }; -const _hoisted_7$2 = /* @__PURE__ */ createBaseVNode("option", { value: "text" }, "Text", -1); -const _hoisted_8$2 = /* @__PURE__ */ createBaseVNode("option", { value: "textarea" }, "Textarea", -1); +const _hoisted_7$2 = /* @__PURE__ */ createBaseVNode( + "option", + { value: "text" }, + "Text", + -1 + /* HOISTED */ +); +const _hoisted_8$2 = /* @__PURE__ */ createBaseVNode( + "option", + { value: "textarea" }, + "Textarea", + -1 + /* HOISTED */ +); const _hoisted_9$2 = [ _hoisted_7$2, _hoisted_8$2 ]; -const _hoisted_10$2 = /* @__PURE__ */ createBaseVNode("input", { - type: "text", - placeholder: "e.g: Co Author", - class: "input input-sm input-bordered" -}, null, -1); -const _hoisted_11$2 = /* @__PURE__ */ createBaseVNode("input", { - type: "text", - placeholder: "e.g: Sobirin Rodriguez", - class: "input input-sm input-bordered" -}, null, -1); -const _hoisted_12$1 = /* @__PURE__ */ createBaseVNode("div", { class: "absolute right-1 top-1 flex" }, [ - /* @__PURE__ */ createBaseVNode("button", { - type: "button", - class: "btn btn-outline btn-error btn-sm" - }, " Delete ") -], -1); +const _hoisted_10$2 = /* @__PURE__ */ createBaseVNode( + "input", + { + type: "text", + placeholder: "e.g: Co Author", + class: "input input-sm input-bordered" + }, + null, + -1 + /* HOISTED */ +); +const _hoisted_11$2 = /* @__PURE__ */ createBaseVNode( + "input", + { + type: "text", + placeholder: "e.g: Sobirin Rodriguez", + class: "input input-sm input-bordered" + }, + null, + -1 + /* HOISTED */ +); +const _hoisted_12$1 = /* @__PURE__ */ createBaseVNode( + "div", + { class: "absolute right-1 top-1 flex" }, + [ + /* @__PURE__ */ createBaseVNode("button", { + type: "button", + class: "btn btn-outline btn-error btn-sm" + }, " Delete ") + ], + -1 + /* HOISTED */ +); const _sfc_main$2 = { __name: "FormMetas", props: { @@ -17721,70 +17889,100 @@ const _sfc_main$2 = { _hoisted_2$2, createBaseVNode("div", _hoisted_3$2, [ createBaseVNode("div", _hoisted_4$2, [ - (openBlock(), createElementBlock(Fragment$1, null, renderList([1, 2, 3], (i2) => { - return createBaseVNode("div", _hoisted_5$2, [ - createBaseVNode("div", _hoisted_6$2, toDisplayString(i2), 1), - createVNode(_sfc_main$4, { - label: "Field Type:", - required: "", - class: "" - }, { - default: withCtx(() => [ - withDirectives(createBaseVNode("select", { - "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => metaItem.field_type = $event), - class: "select select-bordered select-sm" - }, _hoisted_9$2, 512), [ - [vModelSelect, metaItem.field_type] - ]) - ]), - _: 1 - }), - createVNode(_sfc_main$4, { - label: "Key:", - required: "", - class: "" - }, { - default: withCtx(() => [ - withDirectives(createBaseVNode("input", { - type: "text", - "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => metaItem.key = $event), - placeholder: "e.g: co_author", - class: "input input-sm input-bordered" - }, null, 512), [ - [vModelText, metaItem.key] - ]) - ]), - _: 1 - }), - createVNode(_sfc_main$4, { - label: "Label:", - required: false, - class: "" - }, { - default: withCtx(() => [ - _hoisted_10$2 - ]), - _: 1 - }), - createVNode(_sfc_main$4, { - label: "Value:", - required: "", - class: "col-span-full" - }, { - default: withCtx(() => [ - _hoisted_11$2 - ]), - _: 1 - }), - _hoisted_12$1 - ]); - }), 64)) + (openBlock(), createElementBlock( + Fragment$1, + null, + renderList([1, 2, 3], (i2) => { + return createBaseVNode("div", _hoisted_5$2, [ + createBaseVNode( + "div", + _hoisted_6$2, + toDisplayString(i2), + 1 + /* TEXT */ + ), + createVNode(FormControl, { + label: "Field Type:", + required: "", + class: "" + }, { + default: withCtx(() => [ + withDirectives(createBaseVNode( + "select", + { + "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => metaItem.field_type = $event), + class: "select select-bordered select-sm" + }, + [..._hoisted_9$2], + 512 + /* NEED_PATCH */ + ), [ + [vModelSelect, metaItem.field_type] + ]) + ]), + _: 1 + /* STABLE */ + }), + createVNode(FormControl, { + label: "Key:", + required: "", + class: "" + }, { + default: withCtx(() => [ + withDirectives(createBaseVNode( + "input", + { + type: "text", + "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => metaItem.key = $event), + placeholder: "e.g: co_author", + class: "input input-sm input-bordered" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vModelText, metaItem.key] + ]) + ]), + _: 1 + /* STABLE */ + }), + createVNode(FormControl, { + label: "Label:", + required: false, + class: "" + }, { + default: withCtx(() => [ + _hoisted_10$2 + ]), + _: 1 + /* STABLE */ + }), + createVNode(FormControl, { + label: "Value:", + required: "", + class: "col-span-full" + }, { + default: withCtx(() => [ + _hoisted_11$2 + ]), + _: 1 + /* STABLE */ + }), + _hoisted_12$1 + ]); + }), + 64 + /* STABLE_FRAGMENT */ + )) ]) - ]) + ]), + createCommentVNode(' ') ]); }; } }; +const FormMetas = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__file", "/Users/antoni/Packages/ngeblog/resources/js/components/FormMetas.vue"]]); function memo(getDeps, fn, opts) { let deps = opts.initialDeps ?? []; let result; @@ -18009,7 +18207,7 @@ class Virtualizer { this.notify(isScrolling); }, { - key: false, + key: "maybeNotify", debug: () => this.options.debug, initialDeps: [ this.isScrolling, @@ -18146,7 +18344,7 @@ class Virtualizer { return measurements; }, { - key: false, + key: "getMeasurements", debug: () => this.options.debug } ); @@ -18160,7 +18358,7 @@ class Virtualizer { }) : null; }, { - key: false, + key: "calculateRange", debug: () => this.options.debug } ); @@ -18179,7 +18377,7 @@ class Virtualizer { }); }, { - key: false, + key: "getIndexes", debug: () => this.options.debug } ); @@ -18221,6 +18419,9 @@ class Virtualizer { const delta = size - itemSize; if (delta !== 0) { if (item.start < this.scrollOffset + this.scrollAdjustments) { + if (this.options.debug) { + console.info("correction", delta); + } this._scrollToOffset(this.scrollOffset, { adjustments: this.scrollAdjustments += delta, behavior: void 0 @@ -18249,7 +18450,7 @@ class Virtualizer { return virtualItems; }, { - key: false, + key: "getIndexes", debug: () => this.options.debug } ); @@ -20654,23 +20855,29 @@ const _hoisted_7$1 = { key: 0, class: /* @__PURE__ */ normalizeClass([]) }; -const _hoisted_8$1 = /* @__PURE__ */ createBaseVNode("svg", { - xmlns: "http://www.w3.org/2000/svg", - viewBox: "0 0 24 24", - fill: "none", - stroke: "currentColor", - "stroke-width": "2", - "stroke-linecap": "round", - "stroke-linejoin": "round", - class: "h-6 w-6 flex-none" -}, [ - /* @__PURE__ */ createBaseVNode("path", { - stroke: "none", - d: "M0 0h24v24H0z", - fill: "none" - }), - /* @__PURE__ */ createBaseVNode("path", { d: "M5 12l5 5l10 -10" }) -], -1); +const _hoisted_8$1 = /* @__PURE__ */ createBaseVNode( + "svg", + { + xmlns: "http://www.w3.org/2000/svg", + viewBox: "0 0 24 24", + fill: "none", + stroke: "currentColor", + "stroke-width": "2", + "stroke-linecap": "round", + "stroke-linejoin": "round", + class: "h-6 w-6 flex-none" + }, + [ + /* @__PURE__ */ createBaseVNode("path", { + stroke: "none", + d: "M0 0h24v24H0z", + fill: "none" + }), + /* @__PURE__ */ createBaseVNode("path", { d: "M5 12l5 5l10 -10" }) + ], + -1 + /* HOISTED */ +); const _hoisted_9$1 = [ _hoisted_8$1 ]; @@ -20829,171 +21036,203 @@ const _sfc_main$1 = { }, { default: withCtx(({ open }) => [ renderSlot(_ctx.$slots, "selected"), - createVNode(unref(nt), { - ref_key: "trigger", - ref: trigger, - as: "div", - role: "button", - class: normalizeClass(["relative flex w-full items-center"]) - }, { - default: withCtx(() => [ - renderSlot(_ctx.$slots, "default", { - open, - disabled: __props.disabled, - loading: __props.loading - }, () => [ - createBaseVNode("button", { - class: normalizeClass([ - "w-full rounded border px-4 py-2 text-left shadow" - ]), - disabled: __props.disabled, - type: "button" - }, [ - renderSlot(_ctx.$slots, "label", {}, () => [ - label.value ? (openBlock(), createElementBlock("span", _hoisted_2$1, toDisplayString(label.value), 1)) : (openBlock(), createElementBlock("span", _hoisted_3$1, toDisplayString(__props.placeholder || "Select"), 1)) - ]) - ], 8, _hoisted_1$1), - __props.loading ? (openBlock(), createElementBlock("span", _hoisted_4$1)) : createCommentVNode("", true) - ]) - ]), - _: 2 - }, 1536), - open ? (openBlock(), createElementBlock("div", { - key: 0, - ref_key: "floating", - ref: floating, - style: normalizeStyle(unref(floatingStyles)), - class: normalizeClass(["group z-20 w-full bg-white"]) - }, [ - createVNode(Transition, mergeProps({ appear: "" }, { - leaveActiveClass: "transition ease-in duration-100", - leaveFromClass: "opacity-100", - leaveToClass: "opacity-0" - }), { + createVNode( + unref(nt), + { + ref_key: "trigger", + ref: trigger, + as: "div", + role: "button", + class: normalizeClass(["relative flex w-full items-center"]) + }, + { default: withCtx(() => [ - createVNode(unref(ut), { - static: "", - as: "ul", - class: normalizeClass([ - "relative scroll-py-1 overflow-y-auto shadow focus:outline-none", - // uiMenu.base - "ring-1 ring-gray-200 dark:ring-gray-700", - // uiMenu.ring - "max-h-60" - // uiMenu.height - ]) - }, { - default: withCtx(() => { - var _a, _b; - return [ - __props.searchable ? (openBlock(), createBlock(unref(it), { - key: 0, - "display-value": () => query.value, - name: "q", - placeholder: __props.searchablePlaceholder, - autofocus: "", - autocomplete: "off", - class: normalizeClass([ - "sticky top-0 z-10 mb-1 block w-full border-0 border-b border-gray-200 bg-white px-3 py-2 text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-transparent dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:placeholder-gray-500" - ]), - onChange: _cache[0] || (_cache[0] = (event) => query.value = event.target.value) - }, null, 8, ["display-value", "placeholder"])) : createCommentVNode("", true), - (openBlock(true), createElementBlock(Fragment$1, null, renderList(unref(filteredOptions), (option, index) => { - return openBlock(), createBlock(unref(rt), { - as: "template", - key: index, - value: __props.valueAttribute ? option[__props.valueAttribute] : option, - disabled: option.disabled - }, { - default: withCtx(({ active, selected, disabled: optionDisabled }) => [ - createBaseVNode("li", { - class: normalizeClass([ - "relative flex cursor-default select-none items-center justify-between gap-1 px-3 py-1.5", - // uiMenu.option.base, - active ? "bg-gray-100 dark:bg-gray-900" : "", - selected ? "bg-teal-100 dark:bg-teal-700" : "" - ]) - }, [ - createBaseVNode("div", _hoisted_5$1, [ - renderSlot(_ctx.$slots, "option", { - option, - active, - selected - }, () => [ - createBaseVNode("span", _hoisted_6$1, toDisplayString(["string", "number"].includes( - typeof option - ) ? option : option[__props.labelAttribute]), 1) - ]) - ]), - selected ? (openBlock(), createElementBlock("span", _hoisted_7$1, _hoisted_9$1)) : createCommentVNode("", true) - ], 2) - ]), - _: 2 - }, 1032, ["value", "disabled"]); - }), 128)), - props.createable ? (openBlock(), createBlock(unref(rt), { key: 1 }, { - default: withCtx(() => [ - createTextVNode(' Create "' + toDisplayString(query.value) + '"? ', 1) - ]), - _: 1 - })) : __props.searchable && query.value && !((_a = unref(filteredOptions)) == null ? void 0 : _a.length) ? (openBlock(), createElementBlock("p", _hoisted_10$1, [ - renderSlot(_ctx.$slots, "option-empty", { query: query.value }, () => [ - createTextVNode(' No results for "' + toDisplayString(query.value) + '". ', 1) - ]) - ])) : !((_b = unref(filteredOptions)) == null ? void 0 : _b.length) ? (openBlock(), createElementBlock("p", _hoisted_11$1, [ - renderSlot(_ctx.$slots, "empty", { query: query.value }, () => [ - createTextVNode(toDisplayString(props.loading ? "Loading..." : "No options."), 1) - ]) - ])) : createCommentVNode("", true) - ]; - }), - _: 3 - }) + renderSlot(_ctx.$slots, "default", { + open, + disabled: __props.disabled, + loading: __props.loading + }, () => [ + createBaseVNode("button", { + class: normalizeClass([ + "w-full rounded border px-4 py-2 text-left shadow" + ]), + disabled: __props.disabled, + type: "button" + }, [ + renderSlot(_ctx.$slots, "label", {}, () => [ + label.value ? (openBlock(), createElementBlock( + "span", + _hoisted_2$1, + toDisplayString(label.value), + 1 + /* TEXT */ + )) : (openBlock(), createElementBlock( + "span", + _hoisted_3$1, + toDisplayString(__props.placeholder || "Select"), + 1 + /* TEXT */ + )) + ]) + ], 8, _hoisted_1$1), + __props.loading ? (openBlock(), createElementBlock("span", _hoisted_4$1)) : createCommentVNode("v-if", true) + ]) ]), - _: 3 - }, 16) - ], 4)) : createCommentVNode("", true) + _: 2 + /* DYNAMIC */ + }, + 1536 + /* NEED_PATCH, DYNAMIC_SLOTS */ + ), + open ? (openBlock(), createElementBlock( + "div", + { + key: 0, + ref_key: "floating", + ref: floating, + style: normalizeStyle(unref(floatingStyles)), + class: normalizeClass(["group z-20 w-full bg-white"]) + }, + [ + createVNode( + Transition, + mergeProps({ appear: "" }, { + leaveActiveClass: "transition ease-in duration-100", + leaveFromClass: "opacity-100", + leaveToClass: "opacity-0" + }), + { + default: withCtx(() => [ + createVNode(unref(ut), { + static: "", + as: "ul", + class: normalizeClass([ + "relative scroll-py-1 overflow-y-auto shadow focus:outline-none", + // uiMenu.base + "ring-1 ring-gray-200 dark:ring-gray-700", + // uiMenu.ring + "max-h-60" + // uiMenu.height + ]) + }, { + default: withCtx(() => { + var _a, _b; + return [ + __props.searchable ? (openBlock(), createBlock(unref(it), { + key: 0, + "display-value": () => query.value, + name: "q", + placeholder: __props.searchablePlaceholder, + autofocus: "", + autocomplete: "off", + class: normalizeClass([ + "sticky top-0 z-10 mb-1 block w-full border-0 border-b border-gray-200 bg-white px-3 py-2 text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-transparent dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:placeholder-gray-500" + ]), + onChange: _cache[0] || (_cache[0] = (event) => query.value = event.target.value) + }, null, 8, ["display-value", "placeholder"])) : createCommentVNode("v-if", true), + (openBlock(true), createElementBlock( + Fragment$1, + null, + renderList(unref(filteredOptions), (option, index) => { + return openBlock(), createBlock(unref(rt), { + as: "template", + key: index, + value: __props.valueAttribute ? option[__props.valueAttribute] : option, + disabled: option.disabled + }, { + default: withCtx(({ active, selected, disabled: optionDisabled }) => [ + createBaseVNode( + "li", + { + class: normalizeClass([ + "relative flex cursor-default select-none items-center justify-between gap-1 px-3 py-1.5", + // uiMenu.option.base, + active ? "bg-gray-100 dark:bg-gray-900" : "", + selected ? "bg-teal-100 dark:bg-teal-700" : "" + ]) + }, + [ + createBaseVNode("div", _hoisted_5$1, [ + renderSlot(_ctx.$slots, "option", { + option, + active, + selected + }, () => [ + createBaseVNode( + "span", + _hoisted_6$1, + toDisplayString(["string", "number"].includes( + typeof option + ) ? option : option[__props.labelAttribute]), + 1 + /* TEXT */ + ) + ]) + ]), + selected ? (openBlock(), createElementBlock("span", _hoisted_7$1, [..._hoisted_9$1])) : createCommentVNode("v-if", true) + ], + 2 + /* CLASS */ + ) + ]), + _: 2 + /* DYNAMIC */ + }, 1032, ["value", "disabled"]); + }), + 128 + /* KEYED_FRAGMENT */ + )), + props.createable ? (openBlock(), createBlock(unref(rt), { key: 1 }, { + default: withCtx(() => [ + createTextVNode( + ' Create "' + toDisplayString(query.value) + '"? ', + 1 + /* TEXT */ + ) + ]), + _: 1 + /* STABLE */ + })) : __props.searchable && query.value && !((_a = unref(filteredOptions)) == null ? void 0 : _a.length) ? (openBlock(), createElementBlock("p", _hoisted_10$1, [ + renderSlot(_ctx.$slots, "option-empty", { query: query.value }, () => [ + createTextVNode( + ' No results for "' + toDisplayString(query.value) + '". ', + 1 + /* TEXT */ + ) + ]) + ])) : !((_b = unref(filteredOptions)) == null ? void 0 : _b.length) ? (openBlock(), createElementBlock("p", _hoisted_11$1, [ + renderSlot(_ctx.$slots, "empty", { query: query.value }, () => [ + createTextVNode( + toDisplayString(props.loading ? "Loading..." : "No options."), + 1 + /* TEXT */ + ) + ]) + ])) : createCommentVNode("v-if", true) + ]; + }), + _: 3 + /* FORWARDED */ + }) + ]), + _: 3 + /* FORWARDED */ + }, + 16 + /* FULL_PROPS */ + ) + ], + 4 + /* STYLE */ + )) : createCommentVNode("v-if", true) ]), _: 3 + /* FORWARDED */ }, 8, ["model-value", "multiple"]); }; } }; -function useAxiosFetch() { - const initialState = { - data: null, - loading: false, - error: null, - requestHeaders: null, - responseHeaders: null - }; - const state = reactive({ ...initialState }); - const fetchData = async (url, method = "GET", config = {}) => { - state.loading = true; - state.error = null; - state.requestHeaders = config.headers || null; - state.responseHeaders = null; - try { - const response = await axios({ url, method, ...config }); - state.data = response.data; - state.responseHeaders = response.headers; - } catch (err) { - console.error("Something went wrong: ", err); - state.error = err; - } finally { - state.loading = false; - } - return state.data; - }; - const reset = () => { - Object.assign(state, initialState); - }; - return { - state, - fetchData, - reset - }; -} +const ComboboxField = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__file", "/Users/antoni/Packages/ngeblog/resources/js/components/Fields/ComboboxField.vue"]]); const _hoisted_1 = { class: "mb-8" }; const _hoisted_2 = { class: "flex items-center gap-2 text-2xl font-bold tracking-wide" }; const _hoisted_3 = { @@ -21004,7 +21243,13 @@ const _hoisted_4 = { key: 0 }; const _hoisted_5 = { key: 1 }; const _hoisted_6 = { class: "form-control" }; const _hoisted_7 = { class: "input input-bordered flex items-center gap-2" }; -const _hoisted_8 = /* @__PURE__ */ createBaseVNode("span", { class: "-ml-4 flex items-center self-stretch rounded-l-lg bg-gray-100 px-2 text-sm" }, /* @__PURE__ */ toDisplayString("Slug:"), -1); +const _hoisted_8 = /* @__PURE__ */ createBaseVNode( + "span", + { class: "-ml-4 flex items-center self-stretch rounded-l-lg bg-gray-100 px-2 text-sm" }, + /* @__PURE__ */ toDisplayString("Slug:"), + -1 + /* HOISTED */ +); const _hoisted_9 = { class: "label flex flex-col items-start md:flex-row" }; const _hoisted_10 = ["textContent"]; const _hoisted_11 = { class: "mb-4 flex flex-wrap items-center gap-2" }; @@ -21013,7 +21258,13 @@ const _hoisted_12 = { class: "badge" }; const _hoisted_13 = { class: "label inline-flex cursor-pointer gap-4" }; -const _hoisted_14 = /* @__PURE__ */ createBaseVNode("span", { class: "label-text" }, "Visibility", -1); +const _hoisted_14 = /* @__PURE__ */ createBaseVNode( + "span", + { class: "label-text" }, + "Visibility", + -1 + /* HOISTED */ +); const _hoisted_15 = { class: "flex flex-col gap-4" }; const _hoisted_16 = { key: 0, @@ -21028,22 +21279,28 @@ const _hoisted_19 = { role: "alert", class: "alert alert-error flex flex-col text-white" }; -const _hoisted_20 = /* @__PURE__ */ createBaseVNode("div", { class: "flex items-center gap-2" }, [ - /* @__PURE__ */ createBaseVNode("svg", { - xmlns: "http://www.w3.org/2000/svg", - class: "h-6 w-6 shrink-0 stroke-current", - fill: "none", - viewBox: "0 0 24 24" - }, [ - /* @__PURE__ */ createBaseVNode("path", { - "stroke-linecap": "round", - "stroke-linejoin": "round", - "stroke-width": "2", - d: "M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" - }) - ]), - /* @__PURE__ */ createBaseVNode("span", { class: "text-lg font-medium" }, " Whoops! Validation failed. ") -], -1); +const _hoisted_20 = /* @__PURE__ */ createBaseVNode( + "div", + { class: "flex items-center gap-2" }, + [ + /* @__PURE__ */ createBaseVNode("svg", { + xmlns: "http://www.w3.org/2000/svg", + class: "h-6 w-6 shrink-0 stroke-current", + fill: "none", + viewBox: "0 0 24 24" + }, [ + /* @__PURE__ */ createBaseVNode("path", { + "stroke-linecap": "round", + "stroke-linejoin": "round", + "stroke-width": "2", + d: "M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" + }) + ]), + /* @__PURE__ */ createBaseVNode("span", { class: "text-lg font-medium" }, " Whoops! Validation failed. ") + ], + -1 + /* HOISTED */ +); const _hoisted_21 = { class: "flex items-center justify-between gap-4 border-t py-4" }; const _hoisted_22 = ["disabled"]; const _sfc_main = { @@ -21055,7 +21312,6 @@ const _sfc_main = { const { state: postState, fetchData: fetchPostData } = useAxiosFetch(); const { state: tagsState, fetchData: fetchTagData } = useAxiosFetch(); const searchableTags = async (q) => { - console.log("jancok", { q }); const data = await fetchTagData( apiBasePath(`tags/dropdown`) + `?search=${q}` ); @@ -21070,26 +21326,6 @@ const _sfc_main = { metas: [], tags: [] }); - const submit = () => { - const handleSuccess = () => { - return router.push({ name: "posts-index" }); - }; - if (route.params.id) { - postForm.submit({ - method: "put", - url: apiBasePath(`posts/${postState.data.id}/update`), - onSuccess() { - return handleSuccess(); - } - }); - } else { - postForm.submit({ - onSuccess() { - return handleSuccess(); - } - }); - } - }; const loadPageData = async () => { if (route.params.id) { await fetchPostData(apiBasePath(`posts/${route.params.id}`)); @@ -21121,11 +21357,31 @@ const _sfc_main = { postForm.slug = slugify(val); } ); + const submit = () => { + const handleSuccess = () => { + return router.push({ name: "posts-index" }); + }; + if (route.params.id) { + postForm.submit({ + method: "put", + url: apiBasePath(`posts/${postState.data.id}/update`), + onSuccess() { + return handleSuccess(); + } + }); + } else { + postForm.submit({ + onSuccess() { + return handleSuccess(); + } + }); + } + }; return (_ctx, _cache) => { var _a, _b; const _component_router_link = resolveComponent("router-link"); return openBlock(), createElementBlock("div", null, [ - ((_b = (_a = unref(postState).error) == null ? void 0 : _a.response) == null ? void 0 : _b.status) === 404 ? (openBlock(), createBlock(_sfc_main$5, { key: 0 })) : (openBlock(), createBlock(Container, { key: 1 }, { + ((_b = (_a = unref(postState).error) == null ? void 0 : _a.response) == null ? void 0 : _b.status) === 404 ? (openBlock(), createBlock(NotFound, { key: 0 })) : (openBlock(), createBlock(Container, { key: 1 }, { default: withCtx(() => [ createBaseVNode("div", _hoisted_1, [ createBaseVNode("h1", _hoisted_2, [ @@ -21137,160 +21393,240 @@ const _sfc_main = { createTextVNode(" ← Posts List ") ]), _: 1 + /* STABLE */ }), - unref(postState).loading ? (openBlock(), createElementBlock("span", _hoisted_3)) : (openBlock(), createElementBlock(Fragment$1, { key: 1 }, [ - _ctx.$route.params.id && unref(postState).data ? (openBlock(), createElementBlock("span", _hoisted_4, " Edit Post " + toDisplayString(unref(postState).data.title), 1)) : (openBlock(), createElementBlock("span", _hoisted_5, "Add new Post")) - ], 64)) + unref(postState).loading ? (openBlock(), createElementBlock("span", _hoisted_3)) : (openBlock(), createElementBlock( + Fragment$1, + { key: 1 }, + [ + _ctx.$route.params.id && unref(postState).data ? (openBlock(), createElementBlock( + "span", + _hoisted_4, + " Edit Post " + toDisplayString(unref(postState).data.title), + 1 + /* TEXT */ + )) : (openBlock(), createElementBlock("span", _hoisted_5, "Add new Post")) + ], + 64 + /* STABLE_FRAGMENT */ + )) ]) ]), unref(postState).loading ? (openBlock(), createBlock(SkeletonContent, { key: 0, class: "mx-auto max-w-xl" - })) : (openBlock(), createElementBlock("form", { - key: 1, - onSubmit: _cache[7] || (_cache[7] = withModifiers(() => submit(), ["prevent"])), - class: "mx-auto flex max-w-5xl flex-col gap-4" - }, [ - createVNode(_sfc_main$4, { - label: "Post Title", - required: true, - "error-message": unref(postForm).errors["title"] - }, { - default: withCtx(() => [ - withDirectives(createBaseVNode("input", { - type: "text", - "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(postForm).title = $event), - placeholder: "e.g: Awesome Technology", - class: normalizeClass(["input input-bordered", { - "input-error": unref(postForm).errors["title"] - }]) - }, null, 2), [ - [vModelText, unref(postForm).title] - ]) - ]), - _: 1 - }, 8, ["error-message"]), - createBaseVNode("div", _hoisted_6, [ - createBaseVNode("label", _hoisted_7, [ - _hoisted_8, - withDirectives(createBaseVNode("input", { - type: "text", - "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => unref(postForm).slug = $event), - class: "w-full", - placeholder: "e.g: awesome-technology" - }, null, 512), [ - [vModelText, unref(postForm).slug] + })) : (openBlock(), createElementBlock( + "form", + { + key: 1, + onSubmit: _cache[7] || (_cache[7] = withModifiers(() => submit(), ["prevent"])), + class: "mx-auto flex max-w-5xl flex-col gap-4" + }, + [ + createVNode(FormControl, { + label: "Post Title", + required: true, + "error-message": unref(postForm).errors["title"] + }, { + default: withCtx(() => [ + withDirectives(createBaseVNode( + "input", + { + type: "text", + "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(postForm).title = $event), + placeholder: "e.g: Awesome Technology", + class: normalizeClass(["input input-bordered", { + "input-error": unref(postForm).errors["title"] + }]) + }, + null, + 2 + /* CLASS */ + ), [ + [vModelText, unref(postForm).title] + ]) + ]), + _: 1 + /* STABLE */ + }, 8, ["error-message"]), + createBaseVNode("div", _hoisted_6, [ + createBaseVNode("label", _hoisted_7, [ + _hoisted_8, + withDirectives(createBaseVNode( + "input", + { + type: "text", + "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => unref(postForm).slug = $event), + class: "w-full", + placeholder: "e.g: awesome-technology" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vModelText, unref(postForm).slug] + ]) + ]), + createBaseVNode("div", _hoisted_9, [ + unref(postForm).errors["slug"] ? (openBlock(), createElementBlock("p", { + key: 0, + textContent: toDisplayString(unref(postForm).errors["slug"]), + class: "text-error" + }, null, 8, _hoisted_10)) : createCommentVNode("v-if", true) ]) ]), - createBaseVNode("div", _hoisted_9, [ - unref(postForm).errors["slug"] ? (openBlock(), createElementBlock("p", { - key: 0, - textContent: toDisplayString(unref(postForm).errors["slug"]), - class: "text-error" - }, null, 8, _hoisted_10)) : createCommentVNode("", true) - ]) - ]), - createVNode(_sfc_main$4, { - as: "div", - label: "Post Tags" - }, { - default: withCtx(() => [ - createVNode(_sfc_main$1, { - modelValue: unref(postForm).tags, - "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => unref(postForm).tags = $event), - placeholder: "Select tags...", - searchable: searchableTags, - "searchable-lazy": false, - loading: unref(tagsState).loading, - "label-attribute": "title", - by: "id", - multiple: "" - }, { - selected: withCtx(() => [ - createBaseVNode("div", _hoisted_11, [ - (openBlock(true), createElementBlock(Fragment$1, null, renderList(unref(postForm).tags, (tag) => { - return openBlock(), createElementBlock("div", _hoisted_12, toDisplayString(tag.title), 1); - }), 256)) - ]) - ]), - _: 1 - }, 8, ["modelValue", "loading"]) - ]), - _: 1 - }), - createBaseVNode("div", null, [ - createBaseVNode("label", _hoisted_13, [ - _hoisted_14, - withDirectives(createBaseVNode("input", { - type: "checkbox", - class: "toggle", - "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => unref(postForm).is_visible = $event) - }, null, 512), [ - [vModelCheckbox, unref(postForm).is_visible] - ]) - ]) - ]), - createVNode(_sfc_main$4, { label: "Post Excerpt" }, { - default: withCtx(() => [ - withDirectives(createBaseVNode("textarea", { - "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => unref(postForm).excerpt = $event), - class: normalizeClass(["textarea textarea-bordered h-24", { - "input-error": unref(postForm).errors["excerpt"] - }]), - placeholder: "Describe the post introduction." - }, null, 2), [ - [vModelText, unref(postForm).excerpt] + createVNode(FormControl, { + as: "div", + label: "Post Tags" + }, { + default: withCtx(() => [ + createVNode(ComboboxField, { + modelValue: unref(postForm).tags, + "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => unref(postForm).tags = $event), + placeholder: "Select tags...", + searchable: searchableTags, + "searchable-lazy": false, + loading: unref(tagsState).loading, + "label-attribute": "title", + by: "id", + multiple: "" + }, { + selected: withCtx(() => [ + createBaseVNode("div", _hoisted_11, [ + (openBlock(true), createElementBlock( + Fragment$1, + null, + renderList(unref(postForm).tags, (tag) => { + return openBlock(), createElementBlock( + "div", + _hoisted_12, + toDisplayString(tag.title), + 1 + /* TEXT */ + ); + }), + 256 + /* UNKEYED_FRAGMENT */ + )) + ]) + ]), + _: 1 + /* STABLE */ + }, 8, ["modelValue", "loading"]) + ]), + _: 1 + /* STABLE */ + }), + createBaseVNode("div", null, [ + createBaseVNode("label", _hoisted_13, [ + _hoisted_14, + withDirectives(createBaseVNode( + "input", + { + type: "checkbox", + class: "toggle", + "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => unref(postForm).is_visible = $event) + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vModelCheckbox, unref(postForm).is_visible] + ]) ]) ]), - _: 1 - }), - createBaseVNode("div", _hoisted_15, [ - createVNode(ContentEditor, { - modelValue: unref(postForm).content, - "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => unref(postForm).content = $event) - }, null, 8, ["modelValue"]), - unref(postForm).errors.content ? (openBlock(), createElementBlock("p", _hoisted_16, toDisplayString(unref(postForm).errors.content), 1)) : createCommentVNode("", true) - ]), - createBaseVNode("div", _hoisted_17, [ - createVNode(_sfc_main$2, { - modelValue: unref(postForm).metas, - "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => unref(postForm).metas = $event) - }, null, 8, ["modelValue"]) - ]), - Object.keys(unref(postForm).errors).length ? (openBlock(), createElementBlock("div", _hoisted_18, [ - createBaseVNode("div", _hoisted_19, [ - _hoisted_20, - createBaseVNode("ul", null, [ - (openBlock(true), createElementBlock(Fragment$1, null, renderList(unref(postForm).errors, (err) => { - return openBlock(), createElementBlock("li", null, toDisplayString(err), 1); - }), 256)) - ]) - ]) - ])) : createCommentVNode("", true), - createBaseVNode("div", _hoisted_21, [ - createVNode(_component_router_link, { - to: { name: "posts-index" }, - class: "btn px-8" - }, { + createVNode(FormControl, { label: "Post Excerpt" }, { default: withCtx(() => [ - createTextVNode(" ← Cancel ") + withDirectives(createBaseVNode( + "textarea", + { + "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => unref(postForm).excerpt = $event), + class: normalizeClass(["textarea textarea-bordered h-24", { + "input-error": unref(postForm).errors["excerpt"] + }]), + placeholder: "Describe the post introduction." + }, + null, + 2 + /* CLASS */ + ), [ + [vModelText, unref(postForm).excerpt] + ]) ]), _: 1 + /* STABLE */ }), - createBaseVNode("button", { - type: "submit", - class: "btn btn-primary px-8", - disabled: unref(postForm).processing - }, toDisplayString(unref(postForm).processing ? "Saving..." : "Save"), 9, _hoisted_22) - ]) - ], 32)) + createBaseVNode("div", _hoisted_15, [ + createVNode(ContentEditor, { + modelValue: unref(postForm).content, + "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => unref(postForm).content = $event) + }, null, 8, ["modelValue"]), + unref(postForm).errors.content ? (openBlock(), createElementBlock( + "p", + _hoisted_16, + toDisplayString(unref(postForm).errors.content), + 1 + /* TEXT */ + )) : createCommentVNode("v-if", true) + ]), + createBaseVNode("div", _hoisted_17, [ + createVNode(FormMetas, { + modelValue: unref(postForm).metas, + "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => unref(postForm).metas = $event) + }, null, 8, ["modelValue"]) + ]), + Object.keys(unref(postForm).errors).length ? (openBlock(), createElementBlock("div", _hoisted_18, [ + createBaseVNode("div", _hoisted_19, [ + _hoisted_20, + createBaseVNode("ul", null, [ + (openBlock(true), createElementBlock( + Fragment$1, + null, + renderList(unref(postForm).errors, (err) => { + return openBlock(), createElementBlock( + "li", + null, + toDisplayString(err), + 1 + /* TEXT */ + ); + }), + 256 + /* UNKEYED_FRAGMENT */ + )) + ]) + ]) + ])) : createCommentVNode("v-if", true), + createBaseVNode("div", _hoisted_21, [ + createVNode(_component_router_link, { + to: { name: "posts-index" }, + class: "btn px-8" + }, { + default: withCtx(() => [ + createTextVNode(" ← Cancel ") + ]), + _: 1 + /* STABLE */ + }), + createBaseVNode("button", { + type: "submit", + class: "btn btn-primary px-8", + disabled: unref(postForm).processing + }, toDisplayString(unref(postForm).processing ? "Saving..." : "Save"), 9, _hoisted_22) + ]) + ], + 32 + /* NEED_HYDRATION */ + )) ]), _: 1 + /* STABLE */ })) ]); }; } }; +const Form = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "/Users/antoni/Packages/ngeblog/resources/js/pages/posts/Form.vue"]]); export { - _sfc_main as default + Form as default }; diff --git a/dist/ngeblog-admin-assets/Form.css b/dist/ngeblog-admin-assets/Form.css index d0d96ec..5cb339a 100644 --- a/dist/ngeblog-admin-assets/Form.css +++ b/dist/ngeblog-admin-assets/Form.css @@ -1,5 +1,5 @@ -.is-active[data-v-6ab0bc8b] { +.is-active[data-v-5ea4f861] { --tw-bg-opacity: 1; background-color: var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity))); --tw-text-opacity: 1; diff --git a/dist/ngeblog-admin-assets/ngeblog.css b/dist/ngeblog-admin-assets/ngeblog.css index b74e575..528675d 100644 --- a/dist/ngeblog-admin-assets/ngeblog.css +++ b/dist/ngeblog-admin-assets/ngeblog.css @@ -1430,6 +1430,16 @@ html { --tw-bg-opacity: 1; background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); } +.toast { + position: fixed; + display: flex; + min-width: -moz-fit-content; + min-width: fit-content; + flex-direction: column; + white-space: nowrap; + gap: 0.5rem; + padding: 1rem; +} .toggle { flex-shrink: 0; --tglbg: var(--fallback-b1,oklch(var(--b1)/1)); @@ -1453,6 +1463,13 @@ html { 0 0 0 2px var(--tglbg) inset, var(--togglehandleborder); } +.alert-info { + border-color: var(--fallback-in,oklch(var(--in)/0.2)); + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + --alert-bg: var(--fallback-in,oklch(var(--in)/1)); + --alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1)); +} .alert-error { border-color: var(--fallback-er,oklch(var(--er)/0.2)); --tw-text-opacity: 1; @@ -2363,6 +2380,9 @@ details.collapse summary::-webkit-details-marker { color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); --tw-placeholder-opacity: 0.2; } +.toast > * { + animation: toast-pop 0.25s ease-out; +} @keyframes toast-pop { 0% { @@ -2626,6 +2646,55 @@ details.collapse summary::-webkit-details-marker { padding-left: 2rem; padding-right: 0.75rem; } +:where(.toast) { + bottom: 0px; + inset-inline-end: 0px; + inset-inline-start: auto; + top: auto; + --tw-translate-x: 0px; + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-start) { + inset-inline-end: auto; + inset-inline-start: 0px; + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-center) { + inset-inline-end: 50%; + inset-inline-start: 50%; + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +:is([dir="rtl"] .toast:where(.toast-center)) { + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-end) { + inset-inline-end: 0px; + inset-inline-start: auto; + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-bottom) { + bottom: 0px; + top: auto; + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-middle) { + bottom: auto; + top: 50%; + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.toast:where(.toast-top) { + bottom: auto; + top: 0px; + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} .avatar.online:before { content: ""; position: absolute; @@ -3315,6 +3384,9 @@ details.collapse summary::-webkit-details-marker { .prose-sm :where(.prose-sm > :last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { margin-bottom: 0; } +.visible { + visibility: visible; +} .collapse { visibility: collapse; } @@ -4027,6 +4099,14 @@ details.collapse summary::-webkit-details-marker { background-color: red; } +/* Placeholder (at the top) */ +.tiptap p.is-editor-empty:first-child::before { + content: attr(data-placeholder); + float: left; + color: #adb5bd; + pointer-events: none; + height: 0; + } .dark\:prose-invert:is(.dark *) { --tw-prose-body: var(--tw-prose-invert-body); --tw-prose-headings: var(--tw-prose-invert-headings); @@ -4047,7 +4127,6 @@ details.collapse summary::-webkit-details-marker { --tw-prose-th-borders: var(--tw-prose-invert-th-borders); --tw-prose-td-borders: var(--tw-prose-invert-td-borders); } - @media (min-width: 640px) { .sm\:prose-base { @@ -4297,7 +4376,6 @@ details.collapse summary::-webkit-details-marker { margin-bottom: 0; } } - @media (min-width: 1024px) { .lg\:prose-lg { @@ -4547,169 +4625,135 @@ details.collapse summary::-webkit-details-marker { margin-bottom: 0; } } - .placeholder\:text-sm::-moz-placeholder { font-size: 0.875rem; line-height: 1.25rem; } - .placeholder\:text-sm::placeholder { font-size: 0.875rem; line-height: 1.25rem; } - .placeholder\:italic::-moz-placeholder { font-style: italic; } - .placeholder\:italic::placeholder { font-style: italic; } - .placeholder\:text-gray-400::-moz-placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } - .placeholder\:text-gray-400::placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } - .hover\:rotate-12:hover { --tw-rotate: 12deg; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } - .hover\:scale-125:hover { --tw-scale-x: 1.25; --tw-scale-y: 1.25; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } - .hover\:bg-gray-200:hover { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } - .hover\:bg-teal-100:hover { --tw-bg-opacity: 1; background-color: rgb(204 251 241 / var(--tw-bg-opacity)); } - .hover\:fill-current:hover { fill: currentColor; } - .hover\:underline-offset-4:hover { text-underline-offset: 4px; } - .focus\:bg-teal-100:focus { --tw-bg-opacity: 1; background-color: rgb(204 251 241 / var(--tw-bg-opacity)); } - .focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; } - .focus\:ring-0:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color); box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } - .focus\:ring-transparent:focus { --tw-ring-color: transparent; } - .dark\:border-gray-500:is(.dark *) { --tw-border-opacity: 1; border-color: rgb(107 114 128 / var(--tw-border-opacity)); } - .dark\:border-gray-700:is(.dark *) { --tw-border-opacity: 1; border-color: rgb(55 65 81 / var(--tw-border-opacity)); } - .dark\:bg-gray-500:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(107 114 128 / var(--tw-bg-opacity)); } - .dark\:bg-gray-600:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } - .dark\:bg-gray-800:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(31 41 55 / var(--tw-bg-opacity)); } - .dark\:bg-gray-900:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(17 24 39 / var(--tw-bg-opacity)); } - .dark\:bg-gray-950:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(3 7 18 / var(--tw-bg-opacity)); } - .dark\:bg-teal-700:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(15 118 110 / var(--tw-bg-opacity)); } - .dark\:text-black:is(.dark *) { --tw-text-opacity: 1; color: rgb(0 0 0 / var(--tw-text-opacity)); } - .dark\:text-gray-100:is(.dark *) { --tw-text-opacity: 1; color: rgb(243 244 246 / var(--tw-text-opacity)); } - .dark\:text-gray-200:is(.dark *) { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } - .dark\:text-gray-400:is(.dark *) { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } - .dark\:text-gray-500:is(.dark *) { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } - .dark\:text-neutral-300:is(.dark *) { --tw-text-opacity: 1; color: rgb(212 212 212 / var(--tw-text-opacity)); } - .dark\:placeholder-gray-500:is(.dark *)::-moz-placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } - .dark\:placeholder-gray-500:is(.dark *)::placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } - .dark\:ring-gray-700:is(.dark *) { --tw-ring-opacity: 1; --tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity)); } - @media (min-width: 640px) { .sm\:mx-auto { @@ -4768,7 +4812,6 @@ details.collapse summary::-webkit-details-marker { line-height: 1.25rem; } } - @media (min-width: 768px) { .md\:h-10 { @@ -4792,7 +4835,6 @@ details.collapse summary::-webkit-details-marker { line-height: 1.75rem; } } - @media (min-width: 1024px) { .lg\:flex { diff --git a/dist/ngeblog-admin-assets/ngeblog.js b/dist/ngeblog-admin-assets/ngeblog.js index 3c89a6b..0225e4e 100644 --- a/dist/ngeblog-admin-assets/ngeblog.js +++ b/dist/ngeblog-admin-assets/ngeblog.js @@ -1,4 +1,4 @@ -const __vite__fileDeps=["ngeblog-admin-assets/Form-Cq7QSysK.js","ngeblog-admin-assets/Form.css"],__vite__mapDeps=i=>i.map(i=>__vite__fileDeps[i]); +const __vite__fileDeps=["ngeblog-admin-assets/Form-Cz729KU0.js","ngeblog-admin-assets/Form.css"],__vite__mapDeps=i=>i.map(i=>__vite__fileDeps[i]); /** * @vue/shared v3.4.27 * (c) 2018-present Yuxi (Evan) You and Vue contributors @@ -10,8 +10,8 @@ function makeMap(str, expectsLowerCase) { const set2 = new Set(str.split(",")); return expectsLowerCase ? (val) => set2.has(val.toLowerCase()) : (val) => set2.has(val); } -const EMPTY_OBJ = {}; -const EMPTY_ARR = []; +const EMPTY_OBJ = Object.freeze({}); +const EMPTY_ARR = Object.freeze([]); const NOOP = () => { }; const NO = () => false; @@ -49,6 +49,9 @@ const isReservedProp = /* @__PURE__ */ makeMap( // the leading comma is intentional so empty string "" is also included ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" ); +const isBuiltInDirective = /* @__PURE__ */ makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); const cacheStringFunction = (fn) => { const cache = /* @__PURE__ */ Object.create(null); return (str) => { @@ -147,6 +150,12 @@ function normalizeClass(value) { } return res.trim(); } +const HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; +const SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; +const MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; +const isHTMLTag = /* @__PURE__ */ makeMap(HTML_TAGS); +const isSVGTag = /* @__PURE__ */ makeMap(SVG_TAGS); +const isMathMLTag = /* @__PURE__ */ makeMap(MATH_TAGS); const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; const isSpecialBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs); function includeBooleanAttr(value) { @@ -243,6 +252,9 @@ const stringifySymbol = (v, i = "") => { * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/ +function warn$3(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} let activeEffectScope; class EffectScope { constructor(detached = false) { @@ -269,6 +281,8 @@ class EffectScope { } finally { activeEffectScope = currentEffectScope; } + } else { + warn$3(`cannot run an inactive effect scope.`); } } /** @@ -322,6 +336,10 @@ function getCurrentScope() { function onScopeDispose(fn) { if (activeEffectScope) { activeEffectScope.cleanups.push(fn); + } else { + warn$3( + `onScopeDispose() is called when there is no active effect scope to be associated with.` + ); } } let activeEffect; @@ -436,6 +454,7 @@ function resetScheduling() { } } function trackEffect(effect2, dep, debuggerEventExtraInfo) { + var _a; if (dep.get(effect2) !== effect2._trackId) { dep.set(effect2, effect2._trackId); const oldDep = effect2.deps[effect2._depsLength]; @@ -447,10 +466,14 @@ function trackEffect(effect2, dep, debuggerEventExtraInfo) { } else { effect2._depsLength++; } + { + (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend$1({ effect: effect2 }, debuggerEventExtraInfo)); + } } } const queueEffectSchedulers = []; function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) { + var _a; pauseScheduling(); for (const effect2 of dep.keys()) { let tracking; @@ -459,6 +482,9 @@ function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) { effect2._dirtyLevel = dirtyLevel; } if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) { + { + (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend$1({ effect: effect2 }, debuggerEventExtraInfo)); + } effect2.trigger(); if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) { effect2._shouldSchedule = false; @@ -477,8 +503,8 @@ const createDep = (cleanup, computed2) => { return dep; }; const targetMap = /* @__PURE__ */ new WeakMap(); -const ITERATE_KEY = Symbol(""); -const MAP_KEY_ITERATE_KEY = Symbol(""); +const ITERATE_KEY = Symbol("iterate"); +const MAP_KEY_ITERATE_KEY = Symbol("Map key iterate"); function track(target, type, key) { if (shouldTrack && activeEffect) { let depsMap = targetMap.get(target); @@ -491,7 +517,12 @@ function track(target, type, key) { } trackEffect( activeEffect, - dep + dep, + { + target, + type, + key + } ); } } @@ -545,7 +576,15 @@ function trigger(target, type, key, newValue, oldValue, oldTarget) { if (dep) { triggerEffects( dep, - 4 + 4, + { + target, + type, + key, + newValue, + oldValue, + oldTarget + } ); } } @@ -667,17 +706,17 @@ class MutableReactiveHandler extends BaseReactiveHandler { if (!hadKey) { trigger(target, "add", key, value); } else if (hasChanged(value, oldValue)) { - trigger(target, "set", key, value); + trigger(target, "set", key, value, oldValue); } } return result; } deleteProperty(target, key) { const hadKey = hasOwn(target, key); - target[key]; + const oldValue = target[key]; const result = Reflect.deleteProperty(target, key); if (result && hadKey) { - trigger(target, "delete", key, void 0); + trigger(target, "delete", key, void 0, oldValue); } return result; } @@ -702,9 +741,21 @@ class ReadonlyReactiveHandler extends BaseReactiveHandler { super(true, isShallow2); } set(target, key) { + { + warn$3( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } return true; } deleteProperty(target, key) { + { + warn$3( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } return true; } } @@ -772,13 +823,15 @@ function set$1(key, value) { if (!hadKey) { key = toRaw(key); hadKey = has2.call(target, key); + } else { + checkIdentityKeys(target, has2, key); } const oldValue = get2.call(target, key); target.set(key, value); if (!hadKey) { trigger(target, "add", key, value); } else if (hasChanged(value, oldValue)) { - trigger(target, "set", key, value); + trigger(target, "set", key, value, oldValue); } return this; } @@ -789,20 +842,23 @@ function deleteEntry(key) { if (!hadKey) { key = toRaw(key); hadKey = has2.call(target, key); + } else { + checkIdentityKeys(target, has2, key); } - get2 ? get2.call(target, key) : void 0; + const oldValue = get2 ? get2.call(target, key) : void 0; const result = target.delete(key); if (hadKey) { - trigger(target, "delete", key, void 0); + trigger(target, "delete", key, void 0, oldValue); } return result; } function clear() { const target = toRaw(this); const hadItems = target.size !== 0; + const oldTarget = isMap$1(target) ? new Map(target) : new Set(target); const result = target.clear(); if (hadItems) { - trigger(target, "clear", void 0, void 0); + trigger(target, "clear", void 0, void 0, oldTarget); } return result; } @@ -850,6 +906,13 @@ function createIterableMethod(method, isReadonly2, isShallow2) { } function createReadonlyMethod(type) { return function(...args) { + { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn$3( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } return type === "delete" ? false : type === "clear" ? void 0 : this; }; } @@ -972,6 +1035,15 @@ const readonlyCollectionHandlers = { const shallowReadonlyCollectionHandlers = { get: /* @__PURE__ */ createInstrumentationGetter(true, true) }; +function checkIdentityKeys(target, has2, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has2.call(target, rawKey)) { + const type = toRawType(target); + warn$3( + `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` + ); + } +} const reactiveMap = /* @__PURE__ */ new WeakMap(); const shallowReactiveMap = /* @__PURE__ */ new WeakMap(); const readonlyMap = /* @__PURE__ */ new WeakMap(); @@ -1034,6 +1106,9 @@ function shallowReadonly(target) { } function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { if (!isObject$2(target)) { + { + warn$3(`value cannot be made reactive: ${String(target)}`); + } return target; } if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { @@ -1081,6 +1156,7 @@ function markRaw(value) { } const toReactive = (value) => isObject$2(value) ? reactive(value) : value; const toReadonly = (value) => isObject$2(value) ? readonly(value) : value; +const COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided. Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`; class ComputedRefImpl { constructor(getter, _setter, isReadonly2, isSSR) { this.getter = getter; @@ -1106,6 +1182,11 @@ class ComputedRefImpl { } trackRefValue(self2); if (self2.effect._dirtyLevel >= 2) { + if (this._warnRecursive) { + warn$3(COMPUTED_SIDE_EFFECT_WARN, ` + +getter: `, this.getter); + } triggerRefValue(self2, 2); } return self2._value; @@ -1128,12 +1209,18 @@ function computed$1(getterOrOptions, debugOptions, isSSR = false) { const onlyGetter = isFunction$2(getterOrOptions); if (onlyGetter) { getter = getterOrOptions; - setter = NOOP; + setter = () => { + warn$3("Write operation failed: computed value is readonly"); + }; } else { getter = getterOrOptions.get; setter = getterOrOptions.set; } const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR); + if (debugOptions && !isSSR) { + cRef.effect.onTrack = debugOptions.onTrack; + cRef.effect.onTrigger = debugOptions.onTrigger; + } return cRef; } function trackRefValue(ref2) { @@ -1145,7 +1232,12 @@ function trackRefValue(ref2) { (_a = ref2.dep) != null ? _a : ref2.dep = createDep( () => ref2.dep = void 0, ref2 instanceof ComputedRefImpl ? ref2 : void 0 - ) + ), + { + target: ref2, + type: "get", + key: "value" + } ); } } @@ -1155,7 +1247,13 @@ function triggerRefValue(ref2, dirtyLevel = 4, newVal) { if (dep) { triggerEffects( dep, - dirtyLevel + dirtyLevel, + { + target: ref2, + type: "set", + key: "value", + newValue: newVal + } ); } } @@ -1192,12 +1290,12 @@ class RefImpl { if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal; this._value = useDirectValue ? newVal : toReactive(newVal); - triggerRefValue(this, 4); + triggerRefValue(this, 4, newVal); } } } function triggerRef(ref2) { - triggerRefValue(ref2, 4); + triggerRefValue(ref2, 4, ref2.value); } function unref(ref2) { return isRef(ref2) ? ref2.value : ref2; @@ -1244,6 +1342,12 @@ function customRef(factory) { * @license MIT **/ const stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} function warn$1(msg, ...args) { pauseTracking(); const instance = stack.length ? stack[stack.length - 1].component : null; @@ -1344,6 +1448,46 @@ function formatProp(key, value, raw) { return raw ? value : [`${key}=`, value]; } } +function assertNumber(val, type) { + if (val === void 0) { + return; + } else if (typeof val !== "number") { + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + } else if (isNaN(val)) { + warn$1(`${type} is NaN - the duration expression might be incorrect.`); + } +} +const ErrorTypeStrings$1 = { + ["sp"]: "serverPrefetch hook", + ["bc"]: "beforeCreate hook", + ["c"]: "created hook", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [11]: "app warnHandler", + [12]: "ref function", + [13]: "async component loader", + [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://github.com/vuejs/core ." +}; function callWithErrorHandling(fn, instance, type, args) { try { return args ? fn(...args) : fn(); @@ -1367,6 +1511,10 @@ function callWithAsyncErrorHandling(fn, instance, type, args) { values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); } return values; + } else { + warn$1( + `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}` + ); } } function handleError(err, instance, type, throwInDev = true) { @@ -1374,7 +1522,7 @@ function handleError(err, instance, type, throwInDev = true) { if (instance) { let cur = instance.parent; const exposedInstance = instance.proxy; - const errorInfo = `https://vuejs.org/error-reference/#runtime-${type}`; + const errorInfo = ErrorTypeStrings$1[type]; while (cur) { const errorCapturedHooks = cur.ec; if (errorCapturedHooks) { @@ -1403,7 +1551,19 @@ function handleError(err, instance, type, throwInDev = true) { } function logError(err, type, contextVNode, throwInDev = true) { { - console.error(err); + const info = ErrorTypeStrings$1[type]; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + throw err; + } else { + console.error(err); + } } } let isFlushing = false; @@ -1415,6 +1575,7 @@ let activePostFlushCbs = null; let postFlushIndex = 0; const resolvedPromise = /* @__PURE__ */ Promise.resolve(); let currentFlushPromise = null; +const RECURSION_LIMIT = 100; function nextTick(fn) { const p2 = currentFlushPromise || resolvedPromise; return fn ? p2.then(this ? fn.bind(this) : fn) : p2; @@ -1473,12 +1634,18 @@ function queuePostFlushCb(cb) { queueFlush(); } function flushPreFlushCbs(instance, seen2, i = isFlushing ? flushIndex + 1 : 0) { + { + seen2 = seen2 || /* @__PURE__ */ new Map(); + } for (; i < queue.length; i++) { const cb = queue[i]; if (cb && cb.pre) { if (instance && cb.id !== instance.uid) { continue; } + if (checkRecursiveUpdates(seen2, cb)) { + continue; + } queue.splice(i, 1); i--; cb(); @@ -1496,7 +1663,13 @@ function flushPostFlushCbs(seen2) { return; } activePostFlushCbs = deduped; + { + seen2 = seen2 || /* @__PURE__ */ new Map(); + } for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + if (checkRecursiveUpdates(seen2, activePostFlushCbs[postFlushIndex])) { + continue; + } activePostFlushCbs[postFlushIndex](); } activePostFlushCbs = null; @@ -1517,31 +1690,301 @@ const comparator = (a, b) => { function flushJobs(seen2) { isFlushPending = false; isFlushing = true; + { + seen2 = seen2 || /* @__PURE__ */ new Map(); + } queue.sort(comparator); + const check = (job) => checkRecursiveUpdates(seen2, job); try { for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { const job = queue[flushIndex]; if (job && job.active !== false) { - if (false) - ; + if (check(job)) { + continue; + } callWithErrorHandling(job, null, 14); } } } finally { flushIndex = 0; queue.length = 0; - flushPostFlushCbs(); + flushPostFlushCbs(seen2); isFlushing = false; currentFlushPromise = null; if (queue.length || pendingPostFlushCbs.length) { - flushJobs(); + flushJobs(seen2); + } + } +} +function checkRecursiveUpdates(seen2, fn) { + if (!seen2.has(fn)) { + seen2.set(fn, 1); + } else { + const count = seen2.get(fn); + if (count > RECURSION_LIMIT) { + const instance = fn.ownerInstance; + const componentName = instance && getComponentName(instance.type); + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 + ); + return true; + } else { + seen2.set(fn, count + 1); + } + } +} +let isHmrUpdating = false; +const hmrDirtyComponents = /* @__PURE__ */ new Set(); +{ + getGlobalThis().__VUE_HMR_RUNTIME__ = { + createRecord: tryWrap(createRecord), + rerender: tryWrap(rerender), + reload: tryWrap(reload) + }; +} +const map = /* @__PURE__ */ new Map(); +function registerHMR(instance) { + const id = instance.type.__hmrId; + let record = map.get(id); + if (!record) { + createRecord(id, instance.type); + record = map.get(id); + } + record.instances.add(instance); +} +function unregisterHMR(instance) { + map.get(instance.type.__hmrId).instances.delete(instance); +} +function createRecord(id, initialDef) { + if (map.has(id)) { + return false; + } + map.set(id, { + initialDef: normalizeClassComponent(initialDef), + instances: /* @__PURE__ */ new Set() + }); + return true; +} +function normalizeClassComponent(component) { + return isClassComponent(component) ? component.__vccOpts : component; +} +function rerender(id, newRender) { + const record = map.get(id); + if (!record) { + return; + } + record.initialDef.render = newRender; + [...record.instances].forEach((instance) => { + if (newRender) { + instance.render = newRender; + normalizeClassComponent(instance.type).render = newRender; + } + instance.renderCache = []; + isHmrUpdating = true; + instance.effect.dirty = true; + instance.update(); + isHmrUpdating = false; + }); +} +function reload(id, newComp) { + const record = map.get(id); + if (!record) + return; + newComp = normalizeClassComponent(newComp); + updateComponentDef(record.initialDef, newComp); + const instances = [...record.instances]; + for (const instance of instances) { + const oldComp = normalizeClassComponent(instance.type); + if (!hmrDirtyComponents.has(oldComp)) { + if (oldComp !== record.initialDef) { + updateComponentDef(oldComp, newComp); + } + hmrDirtyComponents.add(oldComp); + } + instance.appContext.propsCache.delete(instance.type); + instance.appContext.emitsCache.delete(instance.type); + instance.appContext.optionsCache.delete(instance.type); + if (instance.ceReload) { + hmrDirtyComponents.add(oldComp); + instance.ceReload(newComp.styles); + hmrDirtyComponents.delete(oldComp); + } else if (instance.parent) { + instance.parent.effect.dirty = true; + queueJob(instance.parent.update); + } else if (instance.appContext.reload) { + instance.appContext.reload(); + } else if (typeof window !== "undefined") { + window.location.reload(); + } else { + console.warn( + "[HMR] Root or manually mounted instance modified. Full reload required." + ); + } + } + queuePostFlushCb(() => { + for (const instance of instances) { + hmrDirtyComponents.delete( + normalizeClassComponent(instance.type) + ); + } + }); +} +function updateComponentDef(oldComp, newComp) { + extend$1(oldComp, newComp); + for (const key in oldComp) { + if (key !== "__file" && !(key in newComp)) { + delete oldComp[key]; } } } +function tryWrap(fn) { + return (id, arg) => { + try { + return fn(id, arg); + } catch (e) { + console.error(e); + console.warn( + `[HMR] Something went wrong during Vue component hot-reload. Full reload required.` + ); + } + }; +} +let devtools$1; +let buffer = []; +let devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools$1) { + devtools$1.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook$1(hook, target) { + var _a, _b; + devtools$1 = hook; + if (devtools$1) { + devtools$1.enabled = true; + buffer.forEach(({ event, args }) => devtools$1.emit(event, ...args)); + buffer = []; + } else if ( + // handle late devtools injection - only do this if we are in an actual + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook$1(newHook, target); + }); + setTimeout(() => { + if (!devtools$1) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +function devtoolsUnmountApp(app) { + emit$1("app:unmount", app); +} +const devtoolsComponentAdded = /* @__PURE__ */ createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +const devtoolsComponentUpdated = /* @__PURE__ */ createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +const _devtoolsComponentRemoved = /* @__PURE__ */ createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +const devtoolsComponentRemoved = (component) => { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +/*! #__NO_SIDE_EFFECTS__ */ +// @__NO_SIDE_EFFECTS__ +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + component.parent ? component.parent.uid : void 0, + component + ); + }; +} +const devtoolsPerfStart = /* @__PURE__ */ createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +const devtoolsPerfEnd = /* @__PURE__ */ createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} function emit(instance, event, ...rawArgs) { if (instance.isUnmounted) return; const props = instance.vnode.props || EMPTY_OBJ; + { + const { + emitsOptions, + propsOptions: [propsOptions] + } = instance; + if (emitsOptions) { + if (!(event in emitsOptions) && true) { + if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { + warn$1( + `Component emitted event "${event}" but it is neither declared in the emits option nor as an "${toHandlerKey(event)}" prop.` + ); + } + } else { + const validator2 = emitsOptions[event]; + if (isFunction$2(validator2)) { + const isValid = validator2(...rawArgs); + if (!isValid) { + warn$1( + `Invalid event arguments: event validation failed for event "${event}".` + ); + } + } + } + } + } let args = rawArgs; const isModelListener2 = event.startsWith("update:"); const modelArg = isModelListener2 && event.slice(7); @@ -1555,6 +1998,22 @@ function emit(instance, event, ...rawArgs) { args = rawArgs.map(looseToNumber); } } + { + devtoolsComponentEmit(instance, event, args); + } + { + const lowerCaseEvent = event.toLowerCase(); + if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { + warn$1( + `Event "${lowerCaseEvent}" is emitted in component ${formatComponentName( + instance, + instance.type + )} but the handler is registered for "${event}". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "${hyphenate( + event + )}" instead of "${event}".` + ); + } + } let handlerName; let handler = props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249) props[handlerName = toHandlerKey(camelize(event))]; @@ -1663,6 +2122,9 @@ function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { setBlockTracking(1); } } + { + devtoolsComponentUpdated(ctx); + } return res; }; renderFnWithContext._n = true; @@ -1670,7 +2132,9 @@ function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { renderFnWithContext._d = true; return renderFnWithContext; } +let accessedAttrs = false; function markAttrsAccessed() { + accessedAttrs = true; } function renderComponentRoot(instance) { const { @@ -1693,10 +2157,13 @@ function renderComponentRoot(instance) { const prev = setCurrentRenderingInstance(instance); let result; let fallthroughAttrs; + { + accessedAttrs = false; + } try { if (vnode.shapeFlag & 4) { const proxyToUse = withProxy || proxy; - const thisProxy = false ? new Proxy(proxyToUse, { + const thisProxy = setupState.__isScriptSetup ? new Proxy(proxyToUse, { get(target, key, receiver) { warn$1( `Property '${String( @@ -1711,7 +2178,7 @@ function renderComponentRoot(instance) { thisProxy, proxyToUse, renderCache, - false ? shallowReadonly(props) : props, + true ? shallowReadonly(props) : props, setupState, data, ctx @@ -1720,12 +2187,13 @@ function renderComponentRoot(instance) { fallthroughAttrs = attrs; } else { const render2 = Component; - if (false) - ; + if (attrs === props) { + markAttrsAccessed(); + } result = normalizeVNode( render2.length > 1 ? render2( - false ? shallowReadonly(props) : props, - false ? { + true ? shallowReadonly(props) : props, + true ? { get attrs() { markAttrsAccessed(); return shallowReadonly(attrs); @@ -1734,7 +2202,7 @@ function renderComponentRoot(instance) { emit: emit2 } : { attrs, slots, emit: emit2 } ) : render2( - false ? shallowReadonly(props) : props, + true ? shallowReadonly(props) : props, null ) ); @@ -1746,6 +2214,10 @@ function renderComponentRoot(instance) { result = createVNode(Comment); } let root2 = result; + let setRoot = void 0; + if (result.patchFlag > 0 && result.patchFlag & 2048) { + [root2, setRoot] = getChildRoot(result); + } if (fallthroughAttrs && inheritAttrs !== false) { const keys2 = Object.keys(fallthroughAttrs); const { shapeFlag } = root2; @@ -1758,22 +2230,81 @@ function renderComponentRoot(instance) { ); } root2 = cloneVNode(root2, fallthroughAttrs, false, true); + } else if (!accessedAttrs && root2.type !== Comment) { + const allAttrs = Object.keys(attrs); + const eventAttrs = []; + const extraAttrs = []; + for (let i = 0, l = allAttrs.length; i < l; i++) { + const key = allAttrs[i]; + if (isOn(key)) { + if (!isModelListener(key)) { + eventAttrs.push(key[2].toLowerCase() + key.slice(3)); + } + } else { + extraAttrs.push(key); + } + } + if (extraAttrs.length) { + warn$1( + `Extraneous non-props attributes (${extraAttrs.join(", ")}) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.` + ); + } + if (eventAttrs.length) { + warn$1( + `Extraneous non-emits event listeners (${eventAttrs.join(", ")}) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option.` + ); + } } } } if (vnode.dirs) { + if (!isElementRoot(root2)) { + warn$1( + `Runtime directive used on component with non-element root node. The directives will not function as intended.` + ); + } root2 = cloneVNode(root2, null, false, true); root2.dirs = root2.dirs ? root2.dirs.concat(vnode.dirs) : vnode.dirs; } if (vnode.transition) { + if (!isElementRoot(root2)) { + warn$1( + `Component inside renders non-element root node that cannot be animated.` + ); + } root2.transition = vnode.transition; } - { + if (setRoot) { + setRoot(root2); + } else { result = root2; } setCurrentRenderingInstance(prev); return result; } +const getChildRoot = (vnode) => { + const rawChildren = vnode.children; + const dynamicChildren = vnode.dynamicChildren; + const childRoot = filterSingleRoot(rawChildren, false); + if (!childRoot) { + return [vnode, void 0]; + } else if (childRoot.patchFlag > 0 && childRoot.patchFlag & 2048) { + return getChildRoot(childRoot); + } + const index = rawChildren.indexOf(childRoot); + const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1; + const setRoot = (updatedRoot) => { + rawChildren[index] = updatedRoot; + if (dynamicChildren) { + if (dynamicIndex > -1) { + dynamicChildren[dynamicIndex] = updatedRoot; + } else if (updatedRoot.patchFlag > 0) { + vnode.dynamicChildren = [...dynamicChildren, updatedRoot]; + } + } + }; + return [normalizeVNode(childRoot), setRoot]; +}; function filterSingleRoot(children, recurse = true) { let singleRoot; for (let i = 0; i < children.length; i++) { @@ -1784,6 +2315,9 @@ function filterSingleRoot(children, recurse = true) { return; } else { singleRoot = child; + if (recurse && singleRoot.patchFlag > 0 && singleRoot.patchFlag & 2048) { + return filterSingleRoot(singleRoot.children); + } } } } else { @@ -1810,10 +2344,16 @@ const filterModelListeners = (attrs, props) => { } return res; }; +const isElementRoot = (vnode) => { + return vnode.shapeFlag & (6 | 1) || vnode.type === Comment; +}; function shouldUpdateComponent(prevVNode, nextVNode, optimized) { const { props: prevProps, children: prevChildren, component } = prevVNode; const { props: nextProps, children: nextChildren, patchFlag } = nextVNode; const emits = component.emitsOptions; + if ((prevChildren || nextChildren) && isHmrUpdating) { + return true; + } if (nextVNode.dirs || nextVNode.transition) { return true; } @@ -1915,7 +2455,16 @@ function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false if (!res && maybeSelfReference) { return Component; } + if (warnMissing && !res) { + const extra = type === COMPONENTS ? ` +If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); + } return res; + } else { + warn$1( + `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` + ); } } function resolve(registry, name) { @@ -2181,7 +2730,14 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, sl } } } +let hasWarned = false; function createSuspenseBoundary(vnode, parentSuspense, parentComponent, container, hiddenContainer, anchor, namespace, slotScopeIds, optimized, rendererInternals, isHydrating = false) { + if (!hasWarned) { + hasWarned = true; + console[console.info ? "info" : "log"]( + ` is an experimental feature and its API will likely change.` + ); + } const { p: patch, m: move, @@ -2198,6 +2754,9 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe } } const timeout = vnode.props ? toNumber$1(vnode.props.timeout) : void 0; + { + assertNumber(timeout, `Suspense timeout`); + } const initialAnchor = anchor; const suspense = { vnode, @@ -2216,6 +2775,18 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe isUnmounted: false, effects: [], resolve(resume = false, sync = false) { + { + if (!resume && !suspense.pendingBranch) { + throw new Error( + `suspense.resolve() is called without a pending branch.` + ); + } + if (suspense.isUnmounted) { + throw new Error( + `suspense.resolve() is called on an already unmounted suspense boundary.` + ); + } + } const { vnode: vnode2, activeBranch, @@ -2343,6 +2914,9 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe } instance.asyncResolved = true; const { vnode: vnode2 } = instance; + { + pushWarningContext(vnode2); + } handleSetupResult(instance, asyncSetupResult, false); if (hydratedEl) { vnode2.el = hydratedEl; @@ -2366,6 +2940,9 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe remove2(placeholder); } updateHOCHostEl(instance, vnode2.el); + { + popWarningContext(); + } if (isInPendingSuspense && --suspense.deps === 0) { suspense.resolve(); } @@ -2446,6 +3023,9 @@ function normalizeSuspenseSlot(s) { } if (isArray$3(s)) { const singleChild = filterSingleRoot(s); + if (!singleChild && s.filter((child) => child !== NULL_DYNAMIC_COMPONENT).length > 0) { + warn$1(` slots expect a single root node.`); + } s = singleChild; } s = normalizeVNode(s); @@ -2487,6 +3067,11 @@ const ssrContextKey = Symbol.for("v-scx"); const useSSRContext = () => { { const ctx = inject(ssrContextKey); + if (!ctx) { + warn$1( + `Server rendering context not provided. Make sure to only call useSSRContext() conditionally in the server build.` + ); + } return ctx; } }; @@ -2495,6 +3080,11 @@ function watchEffect(effect2, options) { } const INITIAL_WATCHER_VALUE = {}; function watch(source, cb, options) { + if (!isFunction$2(cb)) { + warn$1( + `\`watch(fn, options?)\` signature has been moved to a separate API. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.` + ); + } return doWatch(source, cb, options); } function doWatch(source, cb, { @@ -2512,6 +3102,35 @@ function doWatch(source, cb, { unwatch(); }; } + if (deep !== void 0 && typeof deep === "number") { + warn$1( + `watch() "deep" option with number value will be used as watch depth in future versions. Please use a boolean instead to avoid potential breakage.` + ); + } + if (!cb) { + if (immediate !== void 0) { + warn$1( + `watch() "immediate" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (deep !== void 0) { + warn$1( + `watch() "deep" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (once !== void 0) { + warn$1( + `watch() "once" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + } + const warnInvalidSource = (s) => { + warn$1( + `Invalid watch source: `, + s, + `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` + ); + }; const instance = currentInstance; const reactiveGetter = (source2) => deep === true ? source2 : ( // for deep: false, only traverse root-level properties @@ -2536,8 +3155,9 @@ function doWatch(source, cb, { return reactiveGetter(s); } else if (isFunction$2(s)) { return callWithErrorHandling(s, instance, 2); - } else - ; + } else { + warnInvalidSource(s); + } }); } else if (isFunction$2(source)) { if (cb) { @@ -2557,6 +3177,7 @@ function doWatch(source, cb, { } } else { getter = NOOP; + warnInvalidSource(source); } if (cb && deep) { const baseGetter = getter; @@ -2631,6 +3252,10 @@ function doWatch(source, cb, { remove(scope.effects, effect2); } }; + { + effect2.onTrack = onTrack; + effect2.onTrigger = onTrigger; + } if (cb) { if (immediate) { job(); @@ -2701,8 +3326,14 @@ function traverse(value, depth = Infinity, seen2) { } return value; } +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} function withDirectives(vnode, directives) { if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); return vnode; } const instance = getExposeProxy(currentRenderingInstance) || currentRenderingInstance.proxy; @@ -2803,15 +3434,25 @@ const BaseTransitionImpl = { } let child = children[0]; if (children.length > 1) { + let hasFound = false; for (const c of children) { if (c.type !== Comment) { + if (hasFound) { + warn$1( + " can only be used on a single element or component. Use for lists." + ); + break; + } child = c; - break; + hasFound = true; } } } const rawProps = toRaw(props); const { mode } = rawProps; + if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { + warn$1(`invalid mode: ${mode}`); + } if (state.isLeaving) { return emptyPlaceholder(child); } @@ -3024,6 +3665,9 @@ function getKeepAliveChild(vnode) { if (!isKeepAlive(vnode)) { return vnode; } + if (vnode.component) { + return vnode.component.subTree; + } const { shapeFlag, children } = vnode; if (children) { if (shapeFlag & 16) { @@ -3138,6 +3782,11 @@ function injectHook(type, hook, target = currentInstance, prepend = false) { hooks.push(wrappedHook); } return wrappedHook; + } else { + const apiName = toHandlerKey(ErrorTypeStrings$1[type].replace(/ hook$/, "")); + warn$1( + `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.` + ); } } const createHook = (lifecycle) => (hook, target = currentInstance) => ( @@ -3169,6 +3818,9 @@ function renderList(source, renderItem, cache, index) { ret[i] = renderItem(source[i], i, void 0, cached && cached[i]); } } else if (typeof source === "number") { + if (!Number.isInteger(source)) { + warn$1(`The v-for range expect an integer value but got ${source}.`); + } ret = new Array(source); for (let i = 0; i < source; i++) { ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); @@ -3202,6 +3854,12 @@ function renderSlot(slots, name, props = {}, fallback, noSlotted) { return createVNode("slot", props, fallback && fallback()); } let slot = slots[name]; + if (slot && slot.length > 1) { + warn$1( + `SSR-optimized slot function detected in a non-SSR-optimized render function. You need to mark this component with $dynamic-slots in the parent template.` + ); + slot = () => []; + } if (slot && slot._c) { slot._d = false; } @@ -3250,10 +3908,10 @@ const publicPropertiesMap = ( $: (i) => i, $el: (i) => i.vnode.el, $data: (i) => i.data, - $props: (i) => i.props, - $attrs: (i) => i.attrs, - $slots: (i) => i.slots, - $refs: (i) => i.refs, + $props: (i) => shallowReadonly(i.props), + $attrs: (i) => shallowReadonly(i.attrs), + $slots: (i) => shallowReadonly(i.slots), + $refs: (i) => shallowReadonly(i.refs), $parent: (i) => getPublicInstance(i.parent), $root: (i) => getPublicInstance(i.root), $emit: (i) => i.emit, @@ -3266,6 +3924,7 @@ const publicPropertiesMap = ( $watch: (i) => instanceWatch.bind(i) }) ); +const isReservedPrefix = (key) => key === "_" || key === "$"; const hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); const PublicInstanceProxyHandlers = { get({ _: instance }, key) { @@ -3273,6 +3932,9 @@ const PublicInstanceProxyHandlers = { return true; } const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } let normalizedProps; if (key[0] !== "$") { const n = accessCache[key]; @@ -3312,6 +3974,9 @@ const PublicInstanceProxyHandlers = { if (publicGetter) { if (key === "$attrs") { track(instance.attrs, "get", ""); + markAttrsAccessed(); + } else if (key === "$slots") { + track(instance, "get", key); } return publicGetter(instance); } else if ( @@ -3329,24 +3994,50 @@ const PublicInstanceProxyHandlers = { { return globalProperties[key]; } - } else - ; + } else if (currentRenderingInstance && (!isString$1(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + warn$1( + `Property ${JSON.stringify( + key + )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` + ); + } else if (instance === currentRenderingInstance) { + warn$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } }, set({ _: instance }, key, value) { const { data, setupState, ctx } = instance; if (hasSetupBinding(setupState, key)) { setupState[key] = value; return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate diff --git a/resources/js/components/ContentEditor.vue b/resources/js/components/ContentEditor.vue index 8b426de..1beea7c 100644 --- a/resources/js/components/ContentEditor.vue +++ b/resources/js/components/ContentEditor.vue @@ -223,6 +223,7 @@ + + diff --git a/resources/js/components/Widgets/CounterWidget.vue b/resources/js/components/Widgets/CounterWidget.vue index aa44de6..28674cd 100644 --- a/resources/js/components/Widgets/CounterWidget.vue +++ b/resources/js/components/Widgets/CounterWidget.vue @@ -1,7 +1,6 @@ diff --git a/resources/js/composables/loadData.js b/resources/js/composables/loadData.js deleted file mode 100644 index 70008bf..0000000 --- a/resources/js/composables/loadData.js +++ /dev/null @@ -1,32 +0,0 @@ -import axios from "axios"; -import { reactive } from "vue"; - -export function useLoadData(defaultUrl = null) { - return reactive({ - loading: false, - data: null, - fetchData(overrideUrl = null, cb = null) { - const self = this; - self.loading = true; - const url = overrideUrl ? overrideUrl : defaultUrl; - - axios - .get(url) - .then((response) => { - self.data = response.data; - - if (typeof cb === "function") { - cb(self.data); - } - }) - .finally(() => { - self.loading = false; - }); - }, - - promise(overrideUrl = null) { - const url = overrideUrl ? overrideUrl : defaultUrl; - return axios.get(url); - }, - }); -} diff --git a/resources/js/composables/confirmable.js b/resources/js/composables/useConfirmable.js similarity index 100% rename from resources/js/composables/confirmable.js rename to resources/js/composables/useConfirmable.js diff --git a/resources/js/composables/useToastable.js b/resources/js/composables/useToastable.js new file mode 100644 index 0000000..85b276d --- /dev/null +++ b/resources/js/composables/useToastable.js @@ -0,0 +1,29 @@ +import { reactive } from "vue"; + +export const toasts = reactive({ + list: [], +}); + +export function useToastable() { + const addToast = ( + message, + { type = "success", duration = 3000, isHtml = false } = {}, + ) => { + const id = Date.now(); + toasts.list.push({ id, message, type, isHtml }); + + // Automatically remove the toast after the specified duration + setTimeout(() => { + removeToast(id); + }, duration); + }; + + const removeToast = (id) => { + toasts.list = toasts.list.filter((toast) => toast.id !== id); + }; + + return { + addToast, + removeToast, + }; +} diff --git a/resources/js/pages/posts/Form.vue b/resources/js/pages/posts/Form.vue index 40c3af7..e4164d7 100644 --- a/resources/js/pages/posts/Form.vue +++ b/resources/js/pages/posts/Form.vue @@ -21,7 +21,6 @@ const { state: postState, fetchData: fetchPostData } = useAxiosFetch(); const { state: tagsState, fetchData: fetchTagData } = useAxiosFetch(); const searchableTags = async (q) => { - console.log("jancok", { q }); const data = await fetchTagData( apiBasePath(`tags/dropdown`) + `?search=${q}`, ); @@ -38,28 +37,6 @@ const postForm = useForm("post", apiBasePath("posts"), { tags: [], }); -const submit = () => { - const handleSuccess = () => { - return router.push({ name: "posts-index" }); - }; - - if (route.params.id) { - postForm.submit({ - method: "put", - url: apiBasePath(`posts/${postState.data.id}/update`), - onSuccess() { - return handleSuccess(); - }, - }); - } else { - postForm.submit({ - onSuccess() { - return handleSuccess(); - }, - }); - } -}; - const loadPageData = async () => { if (route.params.id) { await fetchPostData(apiBasePath(`posts/${route.params.id}`)); @@ -97,12 +74,33 @@ watch( postForm.slug = slugify(val); }, ); + +const submit = () => { + const handleSuccess = () => { + return router.push({ name: "posts-index" }); + }; + + if (route.params.id) { + postForm.submit({ + method: "put", + url: apiBasePath(`posts/${postState.data.id}/update`), + onSuccess() { + return handleSuccess(); + }, + }); + } else { + postForm.submit({ + onSuccess() { + return handleSuccess(); + }, + }); + } +};