{ "id": "blhoijlhb905vkc", "name": "Interactive Form", "js": "import slugify from \"slugify\";\n\nlet status = $state(\"idle\"); // \"idle\" | \"loading\" | \"success\" | \"error\"\nlet message = $state(\"\");\nasync function handleSubmit(e) {\n e.preventDefault();\n status = \"loading\";\n message = \"\";\n\n const form = e.target;\n const form_data = new FormData(form);\n\n try {\n const res = await fetch(form_endpoint, {\n method: \"POST\",\n body: form_data,\n headers: { Accept: \"application/json\" },\n });\n\n if (res.ok) {\n status = \"success\";\n form.reset();\n } else {\n const err = await res.json().catch(() => ({}));\n status = \"error\";\n message = err.message;\n }\n } catch {\n status = \"error\";\n message = \"Network error. Please check your connection.\";\n }\n}\n\nfunction slugify_name(text) {\n return slugify(text, {\n replacement: \"_\", // replace spaces with underscores\n lower: false, // convert to lowercase\n strict: true, // remove special chars\n });\n}\n\n// Auto-grow textarea fields on input\nfunction autogrow(node) {\n function resize() {\n node.style.height = \"auto\";\n node.style.height = node.scrollHeight + \"px\";\n }\n\n // Grow once on mount and whenever input changes\n resize();\n node.addEventListener(\"input\", resize);\n\n return {\n destroy() {\n node.removeEventListener(\"input\", resize);\n },\n };\n}\n", "css": "@import url(https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css);\n\n.container {\n padding-block: 2rem;\n}\n\n.success_state {\n padding: 1rem;\n border: 1px solid var(--theme-primary-color, white);\n border-radius: var(--theme-border-radius, 0.25rem);\n}\n\n.error_state {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1rem; \n}", "html": "
{message}
\n {/if}\n \n