vimalk78's picture
feat(crossword): generated crosswords with clues
486eff6
import{r as m,a as R,R as E}from"./vendor-nf7bT_Uh.js";(function(){const c=document.createElement("link").relList;if(c&&c.supports&&c.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))n(t);new MutationObserver(t=>{for(const r of t)if(r.type==="childList")for(const l of r.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&n(l)}).observe(document,{childList:!0,subtree:!0});function o(t){const r={};return t.integrity&&(r.integrity=t.integrity),t.referrerPolicy&&(r.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?r.credentials="include":t.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function n(t){if(t.ep)return;t.ep=!0;const r=o(t);fetch(t.href,r)}})();var S={exports:{}},N={};/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var _=m,$=Symbol.for("react.element"),k=Symbol.for("react.fragment"),O=Object.prototype.hasOwnProperty,T=_.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,L={key:!0,ref:!0,__self:!0,__source:!0};function P(s,c,o){var n,t={},r=null,l=null;o!==void 0&&(r=""+o),c.key!==void 0&&(r=""+c.key),c.ref!==void 0&&(l=c.ref);for(n in c)O.call(c,n)&&!L.hasOwnProperty(n)&&(t[n]=c[n]);if(s&&s.defaultProps)for(n in c=s.defaultProps,c)t[n]===void 0&&(t[n]=c[n]);return{$$typeof:$,type:s,key:r,ref:l,props:t,_owner:T.current}}N.Fragment=k;N.jsx=P;N.jsxs=P;S.exports=N;var e=S.exports,w={},C=R;w.createRoot=C.createRoot,w.hydrateRoot=C.hydrateRoot;const A=({onTopicsChange:s,availableTopics:c=[],selectedTopics:o=[],customSentence:n="",onSentenceChange:t})=>{const r=l=>{const x=o.includes(l)?o.filter(i=>i!==l):[...o,l];s(x)};return e.jsxs("div",{className:"topic-selector",children:[e.jsx("h3",{children:"Select Topics"}),e.jsx("div",{className:"topic-buttons",children:c.map(l=>e.jsx("button",{className:`topic-btn ${o.includes(l.name)?"selected":""}`,onClick:()=>r(l.name),children:l.name},l.id))}),e.jsxs("div",{className:"sentence-input-container",children:[e.jsx("label",{htmlFor:"custom-sentence",className:"sentence-label",children:"Custom Sentence (optional)"}),e.jsx("textarea",{id:"custom-sentence",className:"sentence-input",value:n,onChange:l=>t&&t(l.target.value),placeholder:"Enter a sentence to influence word selection...",rows:"3",maxLength:"200"}),e.jsxs("div",{className:"sentence-info",children:[e.jsxs("span",{className:"char-count",children:[n.length,"/200 characters"]}),n&&e.jsx("button",{type:"button",className:"clear-sentence-btn",onClick:()=>t&&t(""),title:"Clear sentence",children:"Clear"})]})]}),e.jsxs("p",{className:"selected-count",children:[o.length," topic",o.length!==1?"s":""," selected"]})]})},F=({grid:s,clues:c,showSolution:o,onCellChange:n})=>{const[t,r]=m.useState({}),l=(d,a,u)=>{const p=`${d}-${a}`,f={...t,[p]:u.toUpperCase()};r(f),n&&n(d,a,u)},x=(d,a)=>{if(o&&!i(d,a))return s[d][a];const u=`${d}-${a}`;return t[u]||""},i=(d,a)=>s[d][a]===".",h=(d,a)=>{if(!c)return null;const u=c.find(p=>p.position.row===d&&p.position.col===a);return u?u.number:null};if(!s||s.length===0)return e.jsx("div",{className:"puzzle-grid",children:"No puzzle loaded"});const g=s.length,z=s[0]?s[0].length:0;return e.jsx("div",{className:"puzzle-container",children:e.jsx("div",{className:"puzzle-grid",style:{gridTemplateColumns:`repeat(${z}, 35px)`,gridTemplateRows:`repeat(${g}, 35px)`},children:s.map((d,a)=>d.map((u,p)=>{const f=h(a,p);return i(a,p)?e.jsx("div",{className:"grid-cell empty-cell",style:{visibility:"hidden"}},`${a}-${p}`):e.jsxs("div",{className:"grid-cell white-cell",children:[f&&e.jsx("span",{className:"cell-number",children:f}),e.jsx("input",{type:"text",maxLength:"1",value:x(a,p),onChange:y=>l(a,p,y.target.value),className:`cell-input ${o?"solution-text":""}`,disabled:o})]},`${a}-${p}`)}))})})},D=({clues:s=[]})=>{const c=s.filter(t=>t.direction==="across"),o=s.filter(t=>t.direction==="down"),n=({title:t,clueList:r})=>e.jsxs("div",{className:"clue-section",children:[e.jsx("h4",{children:t}),e.jsx("ol",{children:r.map(l=>e.jsxs("li",{className:"clue-item",children:[e.jsx("span",{className:"clue-number",children:l.number}),e.jsx("span",{className:"clue-text",children:l.text})]},`${l.number}-${l.direction}`))})]});return e.jsxs("div",{className:"clue-list",children:[e.jsx(n,{title:"Across",clueList:c}),e.jsx(n,{title:"Down",clueList:o})]})},G=({message:s="Generating puzzle..."})=>e.jsxs("div",{className:"loading-spinner",children:[e.jsx("div",{className:"spinner"}),e.jsx("p",{className:"loading-message",children:s})]}),B=()=>{const[s,c]=m.useState(null),[o,n]=m.useState(!1),[t,r]=m.useState(null),[l,x]=m.useState([]),i="",h=m.useCallback(async()=>{try{n(!0);const a=await fetch(`${i}/api/topics`);if(!a.ok)throw new Error("Failed to fetch topics");const u=await a.json();x(u)}catch(a){r(a.message)}finally{n(!1)}},[i]),g=m.useCallback(async(a,u="medium",p=!1,f="")=>{try{n(!0),r(null);const j=await fetch(`${i}/api/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({topics:a,difficulty:u,useAI:p,...f&&{customSentence:f}})});if(!j.ok){const b=await j.json().catch(()=>({}));throw new Error(b.message||"Failed to generate puzzle")}const y=await j.json();return c(y),y}catch(j){return r(j.message),null}finally{n(!1)}},[i]),z=m.useCallback(async a=>{try{const u=await fetch(`${i}/api/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({puzzle:s,answers:a})});if(!u.ok)throw new Error("Failed to validate answers");return await u.json()}catch(u){return r(u.message),null}},[i,s]),d=m.useCallback(()=>{c(null),r(null)},[]);return{puzzle:s,loading:o,error:t,topics:l,fetchTopics:h,generatePuzzle:g,validateAnswers:z,resetPuzzle:d}};function U(){const[s,c]=m.useState([]),[o,n]=m.useState("medium"),[t,r]=m.useState(!1),[l,x]=m.useState(""),{puzzle:i,loading:h,error:g,topics:z,fetchTopics:d,generatePuzzle:a,resetPuzzle:u}=B();m.useEffect(()=>{d()},[d]);const p=async()=>{if(s.length===0){alert("Please select at least one topic");return}await a(s,o,!1,l)},f=v=>{c(v)},j=v=>{x(v)},y=()=>{u(),c([]),r(!1),n("medium"),x("")},b=()=>{r(!0)};return e.jsxs("div",{className:"crossword-app",children:[e.jsxs("header",{className:"app-header",children:[e.jsx("h1",{className:"app-title",children:"Crossword Puzzle Generator"}),e.jsx("p",{children:"Select topics and generate your custom crossword puzzle!"})]}),e.jsx(A,{onTopicsChange:f,availableTopics:z,selectedTopics:s,customSentence:l,onSentenceChange:j}),e.jsxs("div",{className:"puzzle-controls",children:[e.jsxs("select",{value:o,onChange:v=>n(v.target.value),className:"control-btn",children:[e.jsx("option",{value:"easy",children:"Easy"}),e.jsx("option",{value:"medium",children:"Medium"}),e.jsx("option",{value:"hard",children:"Hard"})]}),e.jsx("button",{onClick:p,disabled:h||s.length===0,className:"control-btn generate-btn",children:h?"Generating...":"Generate Puzzle"}),e.jsx("button",{onClick:y,className:"control-btn reset-btn",children:"Reset"}),i&&!t&&e.jsx("button",{onClick:b,className:"control-btn reveal-btn",children:"Reveal Solution"})]}),g&&e.jsxs("div",{className:"error-message",children:["Error: ",g]}),h&&e.jsx(G,{}),i&&!h&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"puzzle-info",children:e.jsxs("span",{className:"puzzle-stats",children:[i.metadata.wordCount," words • ",i.metadata.size,"×",i.metadata.size," grid"]})}),e.jsxs("div",{className:"puzzle-layout",children:[e.jsx(F,{grid:i.grid,clues:i.clues,showSolution:t}),e.jsx(D,{clues:i.clues})]})]}),!i&&!h&&!g&&e.jsx("div",{style:{textAlign:"center",padding:"40px",color:"#7f8c8d"},children:'Select topics and click "Generate Puzzle" to start!'})]})}w.createRoot(document.getElementById("root")).render(e.jsx(E.StrictMode,{children:e.jsx(U,{})}));
//# sourceMappingURL=index-7dkEH9uQ.js.map